Skip to content

fix(security): scan runner finishes every repository; method docs current - #62

Merged
leemour merged 3 commits into
mainfrom
fix/security-docs-scan-runner
Oct 14, 2026
Merged

leemour merged 3 commits into
mainfrom
fix/security-docs-scan-runner

Conversation

@leemour

@leemour leemour commented Oct 14, 2026

Copy link
Copy Markdown
Contributor

Task

Bring the security method, runbook and lessons up to the current facts, and make the security scan runner finish a multi-repository run and work from the published package.

Why

  • METHOD.md and RUNBOOK.md described an older setup: five repositories under pre-rename names, a high audit gate, zizmor as a gate, CodeQL through GitHub default setup, commands that no longer exist (max agent config, pino, diagnose). Runbook step 1 would have turned CodeQL default setup back on, which conflicts with the workflow CodeQL in release-checks.yml.
  • scripts/security/scan stopped at the first repository whose scanner failed, so one repository could hide every repository after it.
  • Semgrep timed out on this repository's saved third-party HTML pages, and its fallback handled only .ts/.tsx parse failures.
  • From an installed package the Semgrep stage could not run at all: Node refuses to strip types under node_modules.

What

Runner (fix(security)):

  • semgrep.ts moves to src/semgrep.ts and ships compiled as dist/semgrep.js. scan runs the source in a checkout and the compiled file from an install. files no longer lists the .ts.
  • scan records a failing tool per repository, scans the remaining repositories, writes SCOPE.md, then exits 1 and names the failed ones on stderr. A failing gh api read no longer aborts the run either.
  • The parse fallback covers .js, .jsx, .mjs, .cjs, .mts and .cts too, keeps top-level await (--supported:top-level-await=true), and refuses two sources that would compile to the same file.
  • One rule failing on one file (Internal matching error, level warn) is recorded as coverageGaps in semgrep.json and as a gap line in SCOPE.md. This is a judgement call: such an error otherwise fails the repository on every run. Every other scanner error still fails closed: non-zero exit, invalid JSON, timeouts, errors at level error, unknown types, and compile or parse failures in the fallback.
  • .semgrepignore excludes performance/**/fixtures/. The file replaces Semgrep's built-in list, so it repeats that list (taken from 1.178.0). scan writes a repository's .semgrepignore patterns into SCOPE.md.

Documents (docs(security)):

  • METHOD.md: every WireCatLabs repository, with cli-private through gitleaks only. Steps use cli-testing security scan|socket, plus a gitleaks step run from each repository root. Release gates: pnpm audit --prod --audit-level critical, CodeQL ≥ 9.0, full-history gitleaks, and zizmor as a report (--no-exit-codes). CodeQL runs in release-checks.yml with default setup off. The settings read-back now expects not-configured, plus private reporting, the attached configuration, the npm environment and rulesets. It also shows how to verify that the organisation configuration WireCat public is the default for new repositories and keeps default setup disabled. Checklist names are current (max config set permissions, max mcp --permission, max/tg doctor report create, cli-base src/logging.ts, the postinstall scripts and Windows installers, and parser dependencies by repository).
  • RUNBOOK.md: removes the default-setup step. Adds private reporting, the npm environment only where a repository publishes, the full repository list through the runner, and gitleaks per repository root.
  • LESSONS.md: CodeQL 2.27 SARIF keeps rules in tool.extensions[].rules, so a gate must resolve rule.toolComponent.index. A new repository does not inherit settings applied repository by repository. gitleaks reads .gitleaksignore from the current folder. A .semgrepignore replaces the built-in list. Default setup refuses workflow SARIF uploads.
  • CLAUDE.md: points at the security policy, names cli-core, and says this repository's tests run once on each merge to main (rule 4 and the check budget). The PR template and MONTHLY.md name cli-core.

Merge order

Testing

  • pnpm typecheck exit 0; biome check src scripts exit 0; pnpm docs:check exit 0.
  • pnpm test:coverage: all tests pass, thresholds met.
  • New src/semgrep.test.ts cases cover the .mjs fallback mapped back to source, refusal of colliding outputs, a recorded coverage gap, and fail-closed on timeout, error-level matching errors, non-JS syntax errors and a scanner exit 2.
  • New scripts/security-scan.test.ts runs scan with stub tools against two local repositories. The first fails; the second is still scanned; the exit is 1; and SCOPE.md carries the exit codes, gap and ignore lines.
  • pnpm pack, unpacked under node_modules/@wirecat/cli-testing/, then scripts/security/scan with stub tools: exit 0, semgrep.json written.
  • Semgrep 1.178.0 on an export of this repository, with and without .semgrepignore: the scanned set differs only by performance/documents/html-readers/fixtures/.

🤖 Generated with Claude Code

leemour and others added 3 commits October 15, 2026 00:17
The published package could not run its Semgrep stage, because Node refuses to
strip types under node_modules; the stage now ships as compiled dist/semgrep.js.
One failing repository stopped the whole multi-repository run; scan now records
the failure, scans the rest and exits 1 at the end. The Semgrep fallback also
covers JavaScript files the parser rejects, keeps top-level await, and records
a single rule's matching error on one file as a coverage gap. Third-party HTML
fixtures are excluded so they no longer time the scan out.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The method, runbook and lessons now name every WireCatLabs repository, the
critical-only release gate, zizmor as a report, CodeQL through release-checks
with default setup off, the organisation configuration for new repositories,
gitleaks from each repository root, and the current command names. CLAUDE.md
points at the security policy and states that full tests run on each merge
to main.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…setup off

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@leemour
leemour force-pushed the fix/security-docs-scan-runner branch from 5b4073a to 8701ace Compare October 14, 2026 22:17
@leemour
leemour merged commit b9d5ff5 into main Oct 14, 2026
2 checks passed
@leemour
leemour deleted the fix/security-docs-scan-runner branch October 14, 2026 22:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant