security-audit · v0.3.0 · 2026-09-24 · sha256 6b5f3c3c4eb69480

security-audit v0.3.0A

Immutable. This exact content is served forever at /api/v1/blob/6b5f3c3c4eb69480.

---
name: security-audit
description: >
  Run a lightweight, local security scan of source repositories for hardcoded
  secrets, risky tracked files, and common vulnerability patterns, then triage
  redacted findings and produce Markdown, JSON, or SARIF. Use for secret scans,
  incremental security checks, repository security audits, or GitHub Code
  Scanning output. Do not use as a dependency-CVE scanner, a substitute for a
  full SAST/DAST assessment, or for ordinary non-security code review.
license: Apache-2.0
metadata:
  author: Kuoshih Yang
  version: "0.3.0"
  repository: https://github.com/YangKuoshih/security-audit
---

# Security Audit

Run deterministic local scanning and context triage first, then use agent
reasoning to validate the remaining vulnerability candidates and prioritize
remediation. Describe the result as a lightweight pattern-based audit, not proof
that a repository is secure.

The preferred scanner requires Python 3.10+. Bash and grep provide a reduced
fallback.

## Resolve the skill

Let `SKILL_DIR` be the directory containing this `SKILL.md`. Resolve every bundled
resource relative to it:

- scanner: `SKILL_DIR/scripts/scan-secrets.py`
- fallback scanner: `SKILL_DIR/scripts/scan-secrets.sh`
- patterns: `SKILL_DIR/scripts/patterns.dat`
- report generator: `SKILL_DIR/scripts/generate-report.py`

Do not assume a product-specific environment variable or installation layout.

## Safety invariants

- Keep scanning and reports local. Never transmit findings, source, or suspected
  secrets to web services, remote tools, connectors, or telemetry.
- Never print or quote raw matches. Scanner output is redacted; preserve that
  redaction in commentary, reports, logs, and errors.
- Do not open files flagged for secret or dangerous-file findings. Triage those
  from redacted JSONL, path, pattern, and severity only.
- For vulnerability-pattern findings, read only the small surrounding region
  needed to assess reachability. If the same file also has a secret finding, do
  not read it.
- Create temporary findings and custom-pattern files with owner-only permissions
  (`umask 077`) and remove temporary files when finished. Preserve a report only
  when the user requested a file.
- Never rotate, revoke, delete, purge git history, upload SARIF, or change source
  code unless the user separately asks for that mutation.

## Scan workflow

### 1. Establish scope

Use the user's requested target, mode, severity, and format. Defaults:

- target: current repository
- mode: full
- minimum severity: low
- format: markdown
- output: return a concise summary in conversation; write a report file only if
  requested or needed for SARIF/JSON

If `.security-audit.yml` exists at the target root, read it and map supported
settings as described below. User arguments override configuration.

Incremental mode must have a valid git base ref. If it does not, stop with the
scanner error; never silently replace an incremental scan with a full scan.

### 2. Run the deterministic scanner

Prefer Python and use a private temporary JSONL file:

```bash
umask 077
python3 "$SKILL_DIR/scripts/scan-secrets.py" \
  --target "$TARGET" \
  --patterns "$SKILL_DIR/scripts/patterns.dat" \
  --output "$FINDINGS"
```

Add only the flags required by scope or configuration:

- incremental: `--base-branch <ref>`
- extra excluded directories: `--exclude-dirs dir1,dir2`
- excluded file/path globs: `--exclude-files '*.min.js,fixtures/**'`
- severity threshold: `--severity-min low|medium|high|critical`
- CI policy threshold: `--fail-on none|low|medium|high|critical` (writes results,
  then exits `3` when a finding meets the threshold)
- custom pattern file: `--extra-patterns <path>` (repeatable)
- deterministic-only scan: `--no-entropy`
- skip tracked dangerous-file checks: `--no-dangerous-files`
- change the 5 MiB per-file safety limit: `--max-file-bytes <positive integer>`

The Python scanner does not follow symlinks, which prevents a repository from
causing an audit to read files outside the requested target. It also performs
deterministic context triage before output: documentation/test vulnerability
heuristics are suppressed, placeholder-like secrets are downgraded, complete PEM
blocks are required, Firebase client API keys are distinguished from general GCP
keys, and SSRF requires a user-input signal. Emitted findings include `confidence`
and `context` fields, including tracked dangerous-file findings.

If Python is unavailable, use the bash scanner. The bash fallback has a smaller
option surface; apply unsupported filtering during triage and disclose that in
scan metadata.

Do not combine scanning with network calls. Capture stderr because it contains
mode, file count, pattern count, and errors but no raw secret values.

### 3. Validate the remaining findings once

Read the redacted JSONL once and analyze all findings in one pass. Treat scanner
severity and confidence as the deterministic baseline; change them only when the
source evidence below clearly justifies the change.

1. Verify remaining broad vulnerability heuristics by checking whether untrusted
   input reaches the sink. Do not open files that also contain secret findings.
2. Correlate related findings. The report generator removes common weaker
   duplicates (for example, entropy plus a vendor-specific token on one line),
   but preserve genuinely different risks at the same location.
3. During agent review, adjust severity by at most one tier from the scanner's
   contextual severity unless
   there is strong evidence:
   - downgrade for unmistakable placeholders or development-only context;
   - upgrade for production/deployment paths or broad production access;
   - never downgrade below Low or upgrade above Critical.
4. Assign confidence:
   - High: exact vendor format or unambiguously dangerous tracked file;
   - Medium: structured but context-dependent match;
   - Low: entropy or broad vulnerability heuristic.
5. For vulnerability findings only, assess whether untrusted input reaches the
   sink and label it `Exploitable`, `Likely exploitable`, `Needs investigation`,
   or `Likely false positive`.
6. Add a one-sentence `context` and tailored `remediation` where useful. For
   confirmed credentials, recommend both removal and rotation; remind the user
   that removing a value from the working tree does not erase git history.

When classification is unclear, consult only the relevant reference:

- secret formats and dangerous files: [references/secret-patterns.md](references/secret-patterns.md)
- vulnerability heuristics: [references/vulnerability-patterns.md](references/vulnerability-patterns.md)
- severity and deduplication: [references/severity-guide.md](references/severity-guide.md)

### 4. Report

For machine-readable output, pass the augmented redacted JSONL to:

```bash
python3 "$SKILL_DIR/scripts/generate-report.py" "$FINDINGS" sarif "$REPORT"
```

Formats are `markdown`, `json`, and `sarif`. Do not wrap JSON or SARIF in a
Markdown fence when the user requested machine-readable output.

For a conversational result, lead with:

- counts by severity and number of files scanned;
- the top three remediation actions;
- blast radius of the highest-confidence findings;
- important limitations or skipped checks;
- report path, if one was written.

A clean scan must say that no pattern findings were detected, not that the code
is secure. Recommend a dependency audit or deeper SAST only when relevant to the
user's goal.

## Configuration mapping

The example schema is in [examples/security-audit.yml](examples/security-audit.yml).
Apply it without editing the installed skill:

- `scan.mode` and `scan.base_branch` -> `--base-branch` for incremental mode.
- `scan.paths` -> scan each requested path and merge redacted JSONL findings.
- `exclude.directories` -> `--exclude-dirs`.
- `exclude.files` plus `exclude.patterns` -> `--exclude-files`.
- `severity.minimum` -> `--severity-min`.
- `ci.fail_on` -> `--fail-on`.
- `output.format` and `output.file` -> report-generator arguments.
- `custom_patterns.secrets` -> write a private temporary tab-delimited pattern
  file (`SEVERITY<TAB>ID<TAB>NAME<TAB>REGEX`) and pass `--extra-patterns`.
- `custom_patterns.allowlist` entries with `file` -> merge into
  `--exclude-files`. Raw-value allowlists are intentionally unsupported because
  applying them outside the scanner would expose values to agent context.

Validate custom IDs as lowercase letters, digits, and hyphens; validate severity
against Critical/High/Medium/Low. If a custom regex is invalid, report the
scanner warning and do not claim it was applied.

## Boundaries

This skill does not inspect package vulnerability databases, execute application
code, probe running services, prove exploitability, or search deleted git history.
Use specialized tools for dependency CVEs, DAST, container/image scanning, IaC
policy engines, or historical-secret scanning when the requested assurance needs
those capabilities.