Run an infrastructure-first security audit of a repository - secrets archaeology, dependency supply chain, CI/CD pipeline, LLM/AI attack surface, agent skill supply chain, OWASP Top 10, STRIDE threat model, and data classification - with a confidence gate and a pre-emit verification gate that suppress speculative findings. Use when asked for a security audit, threat model, pentest-style review, OWASP pass, or a pre-release security check. Not for reviewing a single diff - use requesting-code-review for that.
88%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Passed
No findings from the security scan
A repository security audit that reports exploitable findings, not absent best practices. The discipline that makes it useful is the filtering: a confidence gate, twenty-two hard exclusions, and a rule that no finding ships unless you can quote the line that motivates it.
Derived from gstack's /cso skill (MIT).
| Mode | Gate | Use |
|---|---|---|
| Daily (default) | 8/10 confidence | Zero noise. Only what you're sure about. |
| Comprehensive | 2/10 confidence | Monthly deep scan. Filter true noise only; mark everything below 8 as TENTATIVE. |
Diff mode: scope every phase to <base>..HEAD instead of full history.
Identify languages, frameworks, package managers, container/IaC tooling, and CI provider. Scope every later grep to the detected stacks. Record what you found; phases that don't apply are skipped, not failed.
Enumerate every trust boundary: inbound routes, webhook endpoints, auth entry points, third-party integrations, background jobs consuming external data, and anything reading from the network or the filesystem at privilege.
Git history for leaked credentials, tracked .env files, CI configs with inline
secrets.
git log -p --all -S "AKIA" --diff-filter=A -- "*.env" "*.yml" "*.yaml" "*.json" "*.toml"
git log -p --all -G "ghp_|gho_|github_pat_"
git log -p --all -G "xoxb-|xoxp-|xapp-"
git log -p --all -G "password|secret|token|api_key" -- "*.env" "*.yml" "*.json" "*.conf"
git ls-files '*.env' '.env.*' | grep -v '.example\|.sample\|.template'High-signal prefixes: AKIA, ghp_, sk-ant-, sk_live_, xoxb-,
-----BEGIN ... PRIVATE KEY-----.
Severity. CRITICAL for live secret patterns in history. HIGH for .env
tracked, CI configs with inline credentials. MEDIUM for suspicious
.env.example values.
FP rules. Placeholders (your_, changeme, TODO) excluded. Test fixtures
excluded unless the same value appears in non-test code. Rotated secrets are
still findings — they were exposed.
Beyond npm audit. Run whichever audit tool the detected package manager
provides; a missing tool is "SKIPPED — not installed", not a finding.
preinstall/postinstall/install) in production depsSeverity. CRITICAL for high/critical CVEs in direct deps. HIGH for install scripts in prod deps, missing lockfile. MEDIUM for abandoned packages, lockfile untracked.
FP rules. devDependency CVEs cap at MEDIUM. node-gyp/cmake install
scripts are expected. Missing lockfile in a library repo is not a finding.
Who can modify workflows, and what secrets can they reach?
pull_request_target with checkout of PR code${{ github.event.* }} inside run:Severity. CRITICAL for pull_request_target + PR checkout, script
injection. HIGH for unpinned third-party actions, unmasked secrets in env:.
MEDIUM for missing CODEOWNERS.
FP rules. First-party actions/* unpinned is MEDIUM. pull_request_target
without PR ref checkout is safe. Secrets in with: are runtime-handled.
USER, secrets as ARG, .env copied into imagespostgres://, mysql://, mongodb://,
redis://), excluding localhost/example.com"*" in IAM actions/resources, secrets in .tf/.tfvarshostNetwork, hostPIDFP rules. docker-compose.yml for local dev on localhost is not a finding.
Terraform "*" in read-only data sources excluded. Manifests under
test//dev//local/ with localhost networking excluded.
Find inbound endpoints that accept anything. For every webhook/callback route,
check whether signature verification exists anywhere in the middleware chain
(hmac, x-hub-signature, stripe-signature, svix, verify, digest).
Also: TLS verification disabled (InsecureSkipVerify, VERIFY_NONE,
NODE_TLS_REJECT_UNAUTHORIZED=0), overly broad OAuth scopes.
Trace code only. Never send live requests to a webhook endpoint.
FP rules. TLS disabled in test code excluded. Internal service-to-service webhooks on private networks cap at MEDIUM. Endpoints behind a gateway that verifies upstream are not findings — but that requires evidence.
A distinct attack class. Search for:
dangerouslySetInnerHTML, v-html,
innerHTML, .html(), raw())eval()/exec()/new Function() over model outputFP rule. User content in the user-message position of a conversation is not prompt injection. Only flag when it reaches a system prompt, tool schema, or function-calling context.
Installed agent skills are executable prompt code, not documentation. Scan repo-local skill files for:
curl, wget, fetch to suspicious targetsANTHROPIC_API_KEY, OPENAI_API_KEY, process.envIGNORE PREVIOUS, system override, disregard,
forget your instructionsScanning globally installed skills and hooks reads files outside the repo — ask before doing it.
FP rule. curl for a documented download or health check needs context. Flag
when the target URL is suspicious or the command carries credential variables.
| Focus | |
|---|---|
| A01 Broken Access Control | Missing auth on routes; IDOR via params[:id]; horizontal/vertical escalation |
| A02 Cryptographic Failures | MD5/SHA1/DES/ECB; data encrypted at rest and in transit; key management |
| A03 Injection | SQL string interpolation; system()/exec()/popen; template injection; see Phase 7 for prompts |
| A04 Insecure Design | Rate limits on auth; account lockout; server-side business-logic validation |
| A05 Security Misconfiguration | Wildcard CORS in prod; CSP headers; debug mode / verbose errors |
| A06 Vulnerable Components | See Phase 3 |
| A07 AuthN Failures | Session lifecycle; password policy; MFA for admin; JWT expiry and refresh rotation |
| A08 Integrity Failures | See Phase 4; deserialization input validation |
| A09 Logging Failures | Auth events, authz failures, admin actions audit-trailed; logs tamper-protected |
| A10 SSRF | URL built from user input; internal service reachability; outbound allowlist |
For each major component from Phase 1:
COMPONENT: [Name]
Spoofing: Can an attacker impersonate a user/service?
Tampering: Can data be modified in transit/at rest?
Repudiation: Can actions be denied? Is there an audit trail?
Information Disclosure: Can sensitive data leak?
Denial of Service: Can the component be overwhelmed?
Elevation of Privilege: Can a user gain unauthorized access?RESTRICTED (breach = legal liability): credentials, payment data, PII
CONFIDENTIAL (breach = business damage): API keys, trade secrets, behavior data
INTERNAL (breach = embarrassment): system logs, configuration
PUBLIC: docs, marketing, public APIsFor each: where stored, how protected, retention and rotation policy.
Every candidate runs this filter before it can become a finding.
*.md documentation. Exception: SKILL.md files are
executable prompt code — Phase 8 findings are never excluded here.Dockerfile.dev / Dockerfile.local issues, unless referenced by prod deploy config.pull_request_target without PR ref checkout is safe.docker-compose.yml are fine; in prod Dockerfiles/K8s they are findings.For each surviving finding, prove it where safe — by reading code, never by sending traffic:
| Finding type | How to verify |
|---|---|
| Secrets | Is the pattern a real key format (length, prefix)? Never test against live APIs. |
| Webhooks | Trace the middleware chain for signature verification. No HTTP requests. |
| SSRF | Trace whether user-controlled URL construction reaches an internal service. |
| CI/CD | Parse the workflow YAML; confirm pull_request_target actually checks out PR code. |
| Dependencies | Is the vulnerable function directly imported/called? If not, mark UNVERIFIED and say it may still be reachable via framework internals. |
| LLM | Trace whether user input actually reaches system-prompt construction. |
Mark each: VERIFIED · UNVERIFIED (pattern match only) · TENTATIVE
(comprehensive mode, below 8/10).
Variant analysis. One verified SSRF means there may be five more. For each VERIFIED finding, extract the pattern, search the whole codebase, and report variants linked to the original.
Independent verification. Spawn a verifier subagent per candidate with the file:line and the FP rules only — never your reasoning, which anchors it. Ask: "Read the code at this location. Is there a vulnerability? Score 1-10. Below 8, explain why it isn't real." Discard what fails the gate. If subagents are unavailable, re-read with a skeptic's eye and note "self-verified".
This is the rule that kills the largest false-positive class. Before any finding reaches the report:
dict.get() may return None" requires quoting the dict initialization.
"Race between A and B" requires quoting both.Framework-meta nudge. When a symbol is generated by a metaclass, descriptor,
ORM Meta, migration, or decorator (Django Meta, Rails has_many, SQLAlchemy
relationship, TypeORM decorators, Prisma client), quote the meta-construct
instead of expecting a literal name in the class body. The bar is "I read the
source that creates this symbol", not "I grepped and found nothing."
| Score | Meaning | Display |
|---|---|---|
| 9-10 | Verified against specific code; concrete exploit | Show |
| 7-8 | High-confidence pattern match | Show |
| 5-6 | Moderate; could be a false positive | Show with "verify this is actually an issue" |
| 3-4 | Suspicious but likely fine | Appendix only |
| 1-2 | Speculation | Only if severity would be P0 |
Every finding MUST carry a concrete exploit scenario — a step-by-step attack path. "This pattern is insecure" is not a finding.
SECURITY FINDINGS
═════════════════
# Sev Conf Status Category Finding Phase File:Line
── ──── ──── ────── ──────── ─────── ───── ─────────
1 CRIT 9/10 VERIFIED Secrets AWS key in git history P2 .env:3
2 CRIT 9/10 VERIFIED CI/CD pull_request_target + checkout P4 .github/ci.yml:12
3 HIGH 8/10 VERIFIED Supply Chain postinstall in prod dep P3 package.json:41
4 HIGH 9/10 UNVERIFIED Integrations Webhook w/o signature verify P6 api/webhooks.ts:24Then, per finding:
## Finding N: [Title] — [file:line]
* Severity: CRITICAL | HIGH | MEDIUM
* Confidence: N/10
* Status: VERIFIED | UNVERIFIED | TENTATIVE
* Phase: N — [name]
* Evidence: <verbatim quoted line(s) that motivate this>
* Exploit: <step-by-step attack path>
* Fix: <specific remediation with example>Close with counts by severity and an explicit statement of which phases were skipped and why.
phatblat/dotfiles
4d65cab
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.