Harness Security Scan
Lightweight mechanical security scan. Fast triage, not deep review.
When to Use
- As part of the codebase-health-analyst sweep
- For quick security triage on a project or changed files
- On scheduled cron runs for continuous security coverage
- NOT for deep security review (use harness-security-review)
- NOT for threat modeling (use harness-security-review --deep)
Process
Phase 1: SCAN — Run Mechanical Scanner
Resolve project root. Use provided path or cwd.
Load security config. Read harness.config.json and extract security
section. Fall back to defaults if absent.
Determine file scope.
- If
--changed-only or triggered by PR: run git diff --name-only HEAD~1
to get changed files. Filter to source files only (exclude node_modules,
dist, test files per config).
- Otherwise: scan all source files in the project.
Run SecurityScanner. Call SecurityScanner.scanFiles() from
@harness-engineering/core.
Filter by severity threshold. Remove findings below the configured
threshold:
error: only errors
warning: errors and warnings (default)
info: all findings
Check security trends. Check get_security_trends to compare current scan results against the project's security posture history and identify trajectory changes.
Output report. Present findings grouped by severity:
Security Scan: [PASS/FAIL]
Scanned: N files, M rules applied
Errors: N | Warnings: N | Info: N
[List findings with rule ID, file:line, severity, message, remediation]
Gates
- Error-severity findings are blocking. Report is FAIL if any error-severity
finding exists after filtering.
- No AI review. This skill is mechanical only. Do not perform OWASP analysis
or threat modeling.
Harness Integration
harness check-security — CLI command that invokes this skill's scanner.
SecurityScanner — Core class from @harness-engineering/core that executes the rule engine. Its injection rule set (SEC-INJ-*) is the load-bearing enforcement of the owasp-injection-prevention domain skill's concrete anti-patterns — eval/Function, SQL string concatenation, command injection, and Prisma $queryRawUnsafe/$executeRawUnsafe called with interpolated input. Deep injection classes that need data-flow (NoSQL operator injection, second-order injection) are intentionally out of scope for this mechanical scan and belong to /harness:security-review.
harness.config.json — Security section configures severity threshold and file exclusions.
- codebase-health-analyst persona — Invokes this skill as part of its sweep.
Evidence Requirements
When this skill makes claims about existing code, architecture, or behavior,
it MUST cite evidence using one of:
- File reference:
file:line format (e.g., src/auth.ts:42)
- Code pattern reference:
file with description (e.g., src/utils/hash.ts —
"existing bcrypt wrapper")
- Test/command output: Inline or referenced output from a test run or CLI command
- Session evidence: Write to the
evidence session section via manage_state
Uncited claims: Technical assertions without citations MUST be prefixed with
[UNVERIFIED]. Example: [UNVERIFIED] The auth middleware supports refresh tokens.
Red Flags
Universal
These apply to ALL skills. If you catch yourself doing any of these, STOP.
- "I believe the codebase does X" — Stop. Read the code and cite a file:line
reference. Belief is not evidence.
- "Let me recommend [pattern] for this" without checking existing patterns — Stop.
Search the codebase first. The project may already have a convention.
- "While we're here, we should also [unrelated improvement]" — Stop. Flag the idea
but do not expand scope beyond the stated task.
Domain-Specific
- "This finding is in test code, so it's not a real issue" — Stop. Test code can leak secrets, establish bad patterns, and be copy-pasted to production.
- "This dependency is widely used, so it's safe" — Stop. Popularity is not a security guarantee. Check CVE databases and advisory feeds.
- "This is a low-severity finding, skipping" — Stop. Low-severity findings compound. Document why you are deprioritizing, do not silently skip.
- "The scanner didn't flag it, so it's clean" — Stop. Scanners have false negatives. A clean scan is not proof of security — it is absence of evidence.
Rationalizations to Reject
Universal
These reasoning patterns sound plausible but lead to bad outcomes. Reject them.
- "It's probably fine" — "Probably" is not evidence. Verify before asserting.
- "This is best practice" — Best practice in what context? Cite the source and
confirm it applies to this codebase.
- "We can fix it later" — If it is worth flagging, it is worth documenting now
with a concrete follow-up plan.
Domain-Specific
| Rationalization |
Reality |
| "No attacker would find this" |
Security by obscurity. If the code is wrong, flag it regardless of discoverability. |
| "We're behind a firewall" |
Network boundaries change. Code should be secure at every layer regardless of deployment topology. |
| "The framework handles this for us" |
Verify the framework's actual behavior. Misuse of a secure framework is still insecure. |
Escalation
- When error-severity findings are disputed: The scanner is mechanical — it may flag false positives. If a finding is a false positive, add a
// harness-ignore SEC-XXX comment on the line and document the rationale. Do not suppress without explanation.
- When the scanner misses a known vulnerability: This skill runs pattern-based rules only. For semantic analysis (taint tracking, control flow), use
/harness:security-review instead.
- When scan is too slow on large codebases: Use
--changed-only to scope to recently changed files. Full scans can run on a scheduled cron instead.
Success Criteria
- Scanner ran and produced findings (or confirmed clean)
- Findings are filtered by the configured severity threshold
- Report follows the structured format
- Exit code reflects pass/fail status
Examples
Example: Clean Scan
Security Scan: PASS
Scanned: 42 files, 12 rules applied
Errors: 0 | Warnings: 0 | Info: 0
Example: Findings Detected
Security Scan: FAIL
Scanned: 42 files, 12 rules applied
Errors: 1 | Warnings: 2 | Info: 0
[SEC-SECRET-001] src/config.ts:15 (error)
Hardcoded API key detected: `const API_KEY = "sk-..."`
Remediation: Move to environment variable, use dotenv or secrets manager.
[SEC-NET-001] src/cors.ts:5 (warning)
CORS wildcard origin: `origin: "*"`
Remediation: Restrict to specific allowed origins.
[SEC-CRYPTO-001] src/auth.ts:22 (warning)
Weak hash algorithm: `crypto.createHash("md5")`
Remediation: Use SHA-256 or stronger.
1---2name: harness-security-scan3description: Harness Security Scan4---5# Harness Security Scan67> Lightweight mechanical security scan. Fast triage, not deep review.89## When to Use1011- As part of the codebase-health-analyst sweep12- For quick security triage on a project or changed files13- On scheduled cron runs for continuous security coverage14- NOT for deep security review (use harness-security-review)15- NOT for threat modeling (use harness-security-review --deep)1617## Process1819### Phase 1: SCAN — Run Mechanical Scanner20211. **Resolve project root.** Use provided path or cwd.22232. **Load security config.** Read `harness.config.json` and extract `security`24 section. Fall back to defaults if absent.25263. **Determine file scope.**27 - If `--changed-only` or triggered by PR: run `git diff --name-only HEAD~1`28 to get changed files. Filter to source files only (exclude node_modules,29 dist, test files per config).30 - Otherwise: scan all source files in the project.31324. **Run SecurityScanner.** Call `SecurityScanner.scanFiles()` from33 `@harness-engineering/core`.34355. **Filter by severity threshold.** Remove findings below the configured36 threshold:37 - `error`: only errors38 - `warning`: errors and warnings (default)39 - `info`: all findings40416. **Check security trends.** Check `get_security_trends` to compare current scan results against the project's security posture history and identify trajectory changes.42437. **Output report.** Present findings grouped by severity:4445 ```46 Security Scan: [PASS/FAIL]47 Scanned: N files, M rules applied48 Errors: N | Warnings: N | Info: N4950 [List findings with rule ID, file:line, severity, message, remediation]51 ```5253## Gates5455- **Error-severity findings are blocking.** Report is FAIL if any error-severity56 finding exists after filtering.57- **No AI review.** This skill is mechanical only. Do not perform OWASP analysis58 or threat modeling.5960## Harness Integration6162- **`harness check-security`** — CLI command that invokes this skill's scanner.63- **`SecurityScanner`** — Core class from `@harness-engineering/core` that executes the rule engine. Its injection rule set (`SEC-INJ-*`) is the load-bearing enforcement of the `owasp-injection-prevention` domain skill's concrete anti-patterns — `eval`/`Function`, SQL string concatenation, command injection, and Prisma `$queryRawUnsafe`/`$executeRawUnsafe` called with interpolated input. Deep injection classes that need data-flow (NoSQL operator injection, second-order injection) are intentionally out of scope for this mechanical scan and belong to `/harness:security-review`.64- **`harness.config.json`** — Security section configures severity threshold and file exclusions.65- **codebase-health-analyst persona** — Invokes this skill as part of its sweep.6667## Evidence Requirements6869When this skill makes claims about existing code, architecture, or behavior,70it MUST cite evidence using one of:71721. **File reference:** `file:line` format (e.g., `src/auth.ts:42`)732. **Code pattern reference:** `file` with description (e.g., `src/utils/hash.ts` —74 "existing bcrypt wrapper")753. **Test/command output:** Inline or referenced output from a test run or CLI command764. **Session evidence:** Write to the `evidence` session section via `manage_state`7778**Uncited claims:** Technical assertions without citations MUST be prefixed with79`[UNVERIFIED]`. Example: `[UNVERIFIED] The auth middleware supports refresh tokens`.8081## Red Flags8283### Universal8485These apply to ALL skills. If you catch yourself doing any of these, STOP.8687- **"I believe the codebase does X"** — Stop. Read the code and cite a file:line88 reference. Belief is not evidence.89- **"Let me recommend [pattern] for this"** without checking existing patterns — Stop.90 Search the codebase first. The project may already have a convention.91- **"While we're here, we should also [unrelated improvement]"** — Stop. Flag the idea92 but do not expand scope beyond the stated task.9394### Domain-Specific9596- **"This finding is in test code, so it's not a real issue"** — Stop. Test code can leak secrets, establish bad patterns, and be copy-pasted to production.97- **"This dependency is widely used, so it's safe"** — Stop. Popularity is not a security guarantee. Check CVE databases and advisory feeds.98- **"This is a low-severity finding, skipping"** — Stop. Low-severity findings compound. Document why you are deprioritizing, do not silently skip.99- **"The scanner didn't flag it, so it's clean"** — Stop. Scanners have false negatives. A clean scan is not proof of security — it is absence of evidence.100101## Rationalizations to Reject102103### Universal104105These reasoning patterns sound plausible but lead to bad outcomes. Reject them.106107- **"It's probably fine"** — "Probably" is not evidence. Verify before asserting.108- **"This is best practice"** — Best practice in what context? Cite the source and109 confirm it applies to this codebase.110- **"We can fix it later"** — If it is worth flagging, it is worth documenting now111 with a concrete follow-up plan.112113### Domain-Specific114115| Rationalization | Reality |116| ----------------------------------- | -------------------------------------------------------------------------------------------------- |117| "No attacker would find this" | Security by obscurity. If the code is wrong, flag it regardless of discoverability. |118| "We're behind a firewall" | Network boundaries change. Code should be secure at every layer regardless of deployment topology. |119| "The framework handles this for us" | Verify the framework's actual behavior. Misuse of a secure framework is still insecure. |120121## Escalation122123- **When error-severity findings are disputed:** The scanner is mechanical — it may flag false positives. If a finding is a false positive, add a `// harness-ignore SEC-XXX` comment on the line and document the rationale. Do not suppress without explanation.124- **When the scanner misses a known vulnerability:** This skill runs pattern-based rules only. For semantic analysis (taint tracking, control flow), use `/harness:security-review` instead.125- **When scan is too slow on large codebases:** Use `--changed-only` to scope to recently changed files. Full scans can run on a scheduled cron instead.126127## Success Criteria128129- Scanner ran and produced findings (or confirmed clean)130- Findings are filtered by the configured severity threshold131- Report follows the structured format132- Exit code reflects pass/fail status133134## Examples135136### Example: Clean Scan137138```139Security Scan: PASS140Scanned: 42 files, 12 rules applied141Errors: 0 | Warnings: 0 | Info: 0142```143144### Example: Findings Detected145146```147Security Scan: FAIL148Scanned: 42 files, 12 rules applied149Errors: 1 | Warnings: 2 | Info: 0150151[SEC-SECRET-001] src/config.ts:15 (error)152 Hardcoded API key detected: `const API_KEY = "sk-..."`153 Remediation: Move to environment variable, use dotenv or secrets manager.154155[SEC-NET-001] src/cors.ts:5 (warning)156 CORS wildcard origin: `origin: "*"`157 Remediation: Restrict to specific allowed origins.158159[SEC-CRYPTO-001] src/auth.ts:22 (warning)160 Weak hash algorithm: `crypto.createHash("md5")`161 Remediation: Use SHA-256 or stronger.162```