Skip to content

ci: build the self-scan from source instead of installing @latest - #100

Merged
ralyodio merged 1 commit into
masterfrom
fix/self-scan-from-source
Aug 11, 2026
Merged

ci: build the self-scan from source instead of installing @latest#100
ralyodio merged 1 commit into
masterfrom
fix/self-scan-from-source

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

Fixes the unpinned-@latest fragility for the one scan workflow that lives in this repo — the self-scan.

The problem

This repository is ThreatCrush, and its own scan workflow installed @profullstack/threatcrush@latest from npm to scan itself. Wrong two ways:

  1. It tested the wrong code. A PR that broke the scanner still passed its own gate, because the gate ran the previously published version, not the diff.
  2. A broken publish took the gate down. workspace:* shipped in the 0.7.0/0.7.1 manifests, so npm install failed with EUNSUPPORTEDPROTOCOL — every PR's scan errored on a registry problem unrelated to its diff. That's the failure this surfaced through.

The fix

Build the CLI from the checkout and put it on PATH as threatcrush via a one-line shim, so every step below runs unchanged:

- uses: pnpm/action-setup@v6
- uses: actions/setup-node@v7
  with: { node-version: "22", cache: "pnpm" }
- name: Build ThreatCrush from this checkout
  run: |
    pnpm install --frozen-lockfile
    pnpm --filter @profullstack/threatcrush build
    printf '#!/usr/bin/env bash\nexec node "%s/apps/cli/dist/index.js" "$@"\n' "$PWD" > "$HOME/.local/bin/threatcrush"
    chmod +x "$HOME/.local/bin/threatcrush"
    echo "$HOME/.local/bin" >> "$GITHUB_PATH"

The registry is out of the path entirely: no version to pin, nothing to install, and the scan tests the code in the PR — which is what a self-scan is for. Everything downstream (interface detection, SARIF handling, fail-closed logic, reporting) is unchanged from the pack.

The fleet-management hash header is dropped deliberately, so a drift check doesn't revert a customisation that is specific to the repo owning the tool.

Effect

This turns the self-scan check from red (install error on the broken publish) to green (advisory scan, job passes). Verified locally: the built CLI reports --version and the native --format interface, and scan . --format sarif produces a non-empty SARIF and exits 0.

Heads-up, separate from this PR: the self-scan reports ~141 advisory findings on the monorepo, and the bulk are the scanner detecting its own rule definitions and test fixtures (packages/scan, modules) — vulnerable-by-design example code. Worth a path exclusion or .threatcrush.yml ignore later so the Security tab isn't dominated by the tool flagging its own examples. Not blocking: it's advisory and the job passes.

This repository IS ThreatCrush, and its own scan workflow was installing
`@profullstack/threatcrush@latest` from npm to scan itself. That was wrong two
ways: a pull request that broke the scanner still passed its own gate, because
the gate ran the previously-published code; and a broken *publish* took the
gate down entirely — `workspace:*` shipped in the 0.7.0/0.7.1 manifests made
`npm install` fail with EUNSUPPORTEDPROTOCOL, so every PR's scan errored on a
registry problem unrelated to the diff.

Build the CLI from the checkout and put it on PATH as `threatcrush` via a
one-line shim, so every step below runs unchanged. The registry is out of the
path completely: no version to pin, nothing to install, and the scan tests the
code in the pull request, which is what a self-scan is for.

The fleet hash header is dropped deliberately so a drift check does not revert
this — the customisation is specific to the repo that owns the tool. Everything
downstream of the build (interface detection, SARIF handling, fail-closed
logic, reporting) is unchanged from the pack.

Verified locally: the built CLI reports --version and the native --format
interface, and `scan . --format sarif` produces a non-empty SARIF and exits 0,
so the job passes as an advisory scan.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

ThreatCrush Security Scan

141 finding(s)

HIGH/CRITICAL: 19 | MEDIUM: 86 | LOW: 36

Severity Rule Location
HIGH js-shell-exec-interpolation modules/code-scanner/src/__tests__/sast.test.ts:31
HIGH js-shell-exec-interpolation modules/code-scanner/src/__tests__/sast.test.ts:102
HIGH js-shell-exec-interpolation modules/code-scanner/src/__tests__/sast.test.ts:108
HIGH secret-aws-access-key modules/code-scanner/src/secrets/rules.ts:74
HIGH sql-template-interpolation packages/scan/src/__tests__/code-rules.test.ts:31
HIGH secret-aws-access-key packages/scan/src/secret-rules.ts:192
HIGH secret-aws-access-key prd/0003-detect-hardcoded-secrets-before-they-are-committed-or-served.md:126
HIGH sh-eval-expansion .githooks/pre-commit:26
HIGH sh-remote-script-execution apps/web/public/install.sh:272
HIGH sh-remote-script-execution apps/web/public/install.sh:320
HIGH tls-verification-disabled modules/code-scanner/src/__tests__/sast.test.ts:67
HIGH secret-generic-credential modules/spend-guard/config/example.conf.toml:13
HIGH secret-generic-credential modules/spend-guard/README.md:84
HIGH js-unsafe-yaml-load packages/scan/src/__tests__/code-rules.test.ts:238
HIGH secret-generic-credential PRD.md:268
HIGH tls-verification-disabled prd/0004-find-dangerous-code-patterns-without-pretending-to-be-a-compiler.md:121
HIGH tls-verification-disabled prd/0004-find-dangerous-code-patterns-without-pretending-to-be-a-compiler.md:122
HIGH sh-remote-script-execution scripts/smoke-test.sh:46
HIGH sh-remote-script-execution scripts/smoke-test.sh:47
MEDIUM insecure-temp-file .githooks/commit-msg:16
MEDIUM insecure-temp-file .githooks/post-commit:20
MEDIUM js-shell-exec-interpolation apps/cli/src/commands/init.ts:70
MEDIUM js-shell-exec-interpolation apps/cli/src/commands/init.ts:79
MEDIUM js-shell-exec-interpolation apps/cli/src/commands/service.ts:88
MEDIUM js-shell-exec-interpolation apps/cli/src/commands/service.ts:111
MEDIUM sql-template-interpolation apps/cli/src/core/state.ts:121
MEDIUM sql-template-interpolation apps/cli/src/core/state.ts:125
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:31
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:33
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:34
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:35
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:36
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:43
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:49
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:56
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:63
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:82
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:84
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:85
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:93
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:98
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:105
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:112
MEDIUM js-shell-exec-interpolation apps/cli/src/index.ts:411
MEDIUM js-unescaped-html-sink apps/web/src/app/about/page.tsx:180
MEDIUM js-unescaped-html-sink apps/web/src/app/about/page.tsx:184
MEDIUM js-open-redirect apps/web/src/app/auth/login/page.tsx:50
MEDIUM js-unescaped-html-sink apps/web/src/app/blog/[slug]/page.tsx:125
MEDIUM js-unescaped-html-sink apps/web/src/app/blog/[slug]/page.tsx:153
MEDIUM js-unescaped-html-sink apps/web/src/app/blog/[slug]/page.tsx:157

…and 91 more. Full results in the Security tab.

Snippets are redacted; ThreatCrush never prints matched credential material.

@ralyodio
ralyodio merged commit bc49aeb into master Aug 11, 2026
11 checks passed
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