ci: add ThreatCrush PR scanner - #894
Merged
Merged
Conversation
Runs the ThreatCrush CLI against pull requests, alongside vu1nz-scan.yml.
The two are complementary: vu1nz is AI-backed and reviews the diff, this is a
local static/secrets scan.
The CLI runs inside the runner container — installed with npm and executed
locally. No scanning API is called and no code leaves the container, which
matches packages/scanners/threatcrush ('scans run locally against the host;
no account is required').
Node 22 matches mise.toml, and is required for a second reason: the CLI
depends on better-sqlite3 ^11.7.0, which ships prebuilds for ABI 127 (Node 22)
but not ABI 137 (Node 24). On Node 24 the install falls back to a node-gyp
source build and fails.
Scanning happens from the repository root so reported paths are already
repository-relative. Findings are then filtered to the files the PR actually
changed; pre-existing findings elsewhere are counted but not attributed, so
the gate reflects the PR rather than the repository's history. Dependencies
are deliberately not installed, keeping node_modules out of the scan.
Output is parsed from the CLI's text blocks because 'threatcrush scan' has no
machine-readable mode — only 'threatcrush harden' accepts --json, verified
against the published bundle where scan is declared as:
.command("scan").argument("[path]", "Path to scan", ".")
Follows vu1nz-scan.yml throughout: job summary always written, PR comment
upserted best-effort and skipped for forks and Dependabot, and the pass/fail
decision owned by the report step. Fails on critical or high findings in
changed files.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
vu1nz Security Review0 finding(s) in PR #? No security issues found. |
ThreatCrush security scan0 finding(s) in files changed by this PR (scanned 1 changed file(s); 88 further finding(s) elsewhere in the repository are not attributed to this PR). No new findings in the files this PR changes. ThreatCrush CLI ran locally in the runner ( |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds
threatcrush-scan.yml, a PR scanner running the ThreatCrush CLI. Companion tovu1nz-scan.yml— that one is AI-backed and reviews the diff, this is a local static/secrets scan.CLI runs in the container, nothing hits the web
The CLI is installed with
npm i -g @profullstack/threatcrushand executed inside the runner. No scanning API is called and no code leaves the container — matching whatpackages/scanners/threatcrushalready documents: "scans run locally against the host; no account is required." No secrets or API keys needed.Design notes
mise.toml, and is required for a second reason: the CLI depends onbetter-sqlite3 ^11.7.0, which ships prebuilds for ABI 127 (Node 22) but not ABI 137 (Node 24). On Node 24 the install falls through to a node-gyp source build and fails.node_modulesout of the scan.vu1nz-scan.ymlthroughout: job summary always written, PR comment upserted best-effort, skipped for forks and Dependabot.Heads-up:
packages/scanners/threatcrushis brokenThe adapter calls
threatcrush scan <path> --json, and its own comment flags--jsonas assumed. It does not exist. Verified against the published bundle:scantakes a path and nothing else — onlyhardenaccepts--json. SoscanArgs()produces a command that errors withunknown option --json, andparseJson()never sees JSON. This workflow parses the CLI's text output instead, so it works today. Fixing the adapter is a separate change (it has tests) — happy to do it if you want.Verified
Parser exercised against real captured CLI output across four cases: PR touching files with critical findings (fails), medium-only (correctly still fails — that file also has a CRITICAL), unrelated file (passes, 0 findings), and a clean scan (passes). YAML validated.
🤖 Generated with Claude Code