| name | swain-security-check |
| description | Run all security scanners against the project and produce a unified, severity-bucketed report. Orchestrates gitleaks (secrets), osv-scanner/trivy (dependency vulns), semgrep (static analysis), context-file injection scanner (built-in), and repo hygiene checks (built-in). Missing scanners are skipped with install hints — the scan always completes. Triggers on: 'security check', 'security scan', 'run security', 'scan for secrets', 'check for vulnerabilities', 'security audit'. |
| user-invocable | true |
| license | MIT |
| allowed-tools | Bash, Read, Grep, Glob |
| metadata | {"short-description":"Unified security scanning orchestrator","version":"1.0.0","author":"cristos","source":"swain"} |
Security Check
Unified security scanning orchestrator. Checks scanner availability, runs all available scanners against the project, normalizes findings into a severity-bucketed report, and presents results in both JSON and markdown formats.
When invoked
Run the security check script:
python3 skills/swain-security-check/scripts/security_check.py .
For JSON output:
python3 skills/swain-security-check/scripts/security_check.py --json .
Orchestration flow
- Check availability — detect which external scanners are installed (per SPEC-059)
- Run scanners — invoke each available scanner against the project:
- gitleaks (secrets) —
gitleaks detect --source . --report-format json
- osv-scanner or trivy (dependency vulns) — scan lockfiles and manifests
- semgrep (static analysis) —
semgrep --config p/ai-best-practices
- Context-file scanner (built-in, always runs) — scan all agentic context files for injection patterns (SPEC-058, categories A-J)
- Repo hygiene (built-in, always runs) — .gitignore completeness, tracked .env files
- Normalize — map all findings to unified format (scanner, file, line, severity, description, remediation)
- Report — severity-bucketed output (critical/high/medium/low) with summary line
Graceful degradation
Missing external scanners are skipped with a warning — the scan never fails due to a missing tool. The two built-in scanners (context-file scanner and repo hygiene) always run, so the scan always produces results.
Each skipped scanner includes an install hint in the report.
Exit codes
| Code | Meaning |
|---|
| 0 | No findings |
| 1 | Findings present |
| 2 | Error (e.g., invalid path) |
Report format
Severity levels
- Critical — secrets in source, tracked .env files, instruction override patterns
- High — role hijacking, privilege escalation, encoding obfuscation
- Medium — missing .gitignore patterns, dependency vulnerabilities
- Low — informational findings
Per-finding fields
| Field | Description |
|---|
| scanner | Which scanner produced the finding |
| file_path | File where the finding was detected |
| line | Line number (0 if not applicable) |
| severity | critical, high, medium, or low |
| description | What was found |
| remediation | How to fix it |
Summary line
Example: 1 critical, 2 high, 0 medium, 0 low findings (3 total) across 4 scanners
Integration points
- swain-doctor (SPEC-061) — runs a lightweight context-file scan during session startup
- swain-do (SPEC-063) — pre-claim security briefing for security-sensitive tasks
- swain-init — configures gitleaks pre-commit hook during project onboarding
- External security skills (SPEC-065) — hook interface for third-party security skills
External Security Skill Hook Interface (SPEC-065)
External security skills can plug into swain-do's security gates via three hook points. All hooks are no-ops when no external skills are installed -- built-in guidance (SPEC-063) always runs independently.
Hook points
| Hook | When | Input | Output | Capability key |
|---|
| Pre-claim | After threat surface detection, before briefing | Task metadata (title, tags, categories) | Markdown guidance blocks | security-briefing |
| During-implementation | While editing security-sensitive files | File paths being edited | Security context notes | security-context |
| Completion | After implementation, during review | Git diff of changes | Differential review findings | security-review |
Skill detection
Skills are discovered by scanning for SKILL.md files in known directories:
.claude/skills/trailofbits-*/SKILL.md
.agents/skills/trailofbits-*/SKILL.md
.claude/skills/owasp-security/SKILL.md
.agents/skills/owasp-security/SKILL.md
Known skills
| Skill | Detection pattern | Capabilities |
|---|
| Trail of Bits sharp-edges | trailofbits-sharp-edges | security-briefing |
| Trail of Bits insecure-defaults | trailofbits-insecure-defaults | security-briefing |
| Trail of Bits differential-review | trailofbits-differential-review | security-review |
| OWASP Security | owasp-security | security-briefing, security-context |
Adding a new external skill
To integrate a new security skill, call register_skill() -- no changes to core code are required:
from external_hooks import register_skill
register_skill(
name="snyk-security",
detection_pattern="snyk-security",
hook_capabilities=["security-briefing", "security-review"],
)
The skill directory must contain a SKILL.md file at the detection path. The detection pattern supports exact names and glob-style wildcards (*, ?).
Python API
from external_hooks import (
detect_installed_skills,
register_skill,
run_pre_claim_hooks,
run_implementation_hooks,
run_completion_hooks,
)
skills = detect_installed_skills()
skills = detect_installed_skills(search_dirs=["/path/to/project"])
guidance = run_pre_claim_hooks(
task_metadata={"title": "...", "tags": [...], "categories": [...]},
installed_skills=skills,
)
notes = run_implementation_hooks(
file_paths=["src/auth/handler.py"],
installed_skills=skills,
)
findings = run_completion_hooks(
git_diff="diff --git ...",
installed_skills=skills,
)
Design constraints
- External hooks are additive -- they never replace built-in SPEC-063 guidance
- Skills that do not support a given hook point are silently skipped
- Detection is filesystem-only (no network calls, no subprocess invocations)
- The interface is intentionally command-based and loosely coupled
Dependencies
- SPEC-058: Context-file injection scanner (
context_file_scanner.py)
- SPEC-059: Scanner availability detection (
scanner_availability.py)
- SPEC-065: External security skill hook interface (
external_hooks.py)