Skip to content

feat: CI gate — block merges until a repo passes the scan - #16

Merged
AviOfLagos merged 4 commits into
mainfrom
feat/ci-gate
Aug 26, 2026
Merged

feat: CI gate — block merges until a repo passes the scan#16
AviOfLagos merged 4 commits into
mainfrom
feat/ci-gate

Conversation

@AviOfLagos

Copy link
Copy Markdown
Owner

Closes #15.

GitHub.com has no server-side pre-receive hooks, so a push can't be rejected outright. A required status check is the practical equivalent — the merge button stays disabled until the scan passes.

  • .github/workflows/scan.yml — reusable; any repo adopts it in 3 lines
  • .github/workflows/ci.yml — snare's own CI, dogfooding it
  • snare ci install — writes the workflow into your repo, no YAML copy-paste

snare ci status warns when a workflow is installed but not required — that combination looks protected while blocking nothing.

The scan job runs selftest first: a scanner whose detection is broken must never report a green tick. That's exactly how the four false-clean defects in #2 shipped.

GitHub.com has no server-side pre-receive hooks (Enterprise only), so a push
cannot be rejected outright. A required status check is the practical
equivalent: the merge button stays disabled until the scan passes.

Three pieces:

.github/workflows/scan.yml — reusable, so any repo adopts it in three lines:
    jobs:
      snare:
        uses: AviOfLagos/snare/.github/workflows/scan.yml@main
  Inputs for full-history scanning, pinning the snare revision, and whether
  findings fail the job. Writes a job summary listing the flagged lines.

.github/workflows/ci.yml — snare's own CI. Parses every script, runs
  selftest, and scans itself with the reusable workflow.

snare ci install — writes a ready-to-commit workflow into the user's repo so
  nobody has to copy-paste YAML, and prints the one step a workflow cannot do
  for itself: ticking the check as Required in branch protection. 'snare ci
  status' reports when a workflow is installed but NOT required, because that
  combination looks protected while blocking nothing.

The scan job runs selftest FIRST. A scanner whose detection is broken must
never report a green tick — four false-clean defects shipped exactly that way.

Closes #15
Both of these were caught by the CI added in this branch, on its first run.

promo/ was missing from the self-exclusion list. Those files are write-ups
about the malware and quote every IOC verbatim, so snare reported its own
articles as findings — 13 of them — and could never go green on itself.
docs/ was already excluded; promo/ and .github/ now are too.

More seriously, the reusable workflow checked snare out to .snare-tool-checkout
INSIDE the repository being scanned, so the scan walked the scanner as well as
the target. Every third-party adopter would have seen snare's own IOC-quoting
docs reported as findings in their repo, on their first run, with no
explanation. actions/checkout can only write inside the workspace, so the
scanner is now moved to $RUNNER_TEMP before the scan runs.

Refs #15
GNU mktemp requires XXXXXX in the template; BSD mktemp on macOS does not.
Both call sites omitted it, so on Linux mktemp failed, the variable came back
empty, and every subsequent write went to the empty path:

    lib/scan.sh: line 5: : No such file or directory

$FF holds the findings for a scan, so on Linux findings were never recorded
and the scan could not report correctly. snare advertises Linux and WSL
support, and this was broken on both.

Only visible because the CI added in this branch runs on ubuntu-latest. Every
test until now had run on macOS, where BSD mktemp accepts the short template.

Refs #15
The reusable workflow defaults snare-ref to main, so snare's own CI was
checking out the published version and scanning the PR with it. Every fix in
this branch was invisible to the check that was supposed to validate it — the
job kept failing on bugs that were already fixed in the same commit.

snare's own CI now runs directly from the checkout under review, and a
separate job exercises the reusable workflow pinned to this branch so the
path other repositories depend on is still covered.

Refs #15
@AviOfLagos
AviOfLagos merged commit 1bdd052 into main Aug 26, 2026
2 checks passed
@AviOfLagos
AviOfLagos deleted the feat/ci-gate branch August 26, 2026 14:38
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.

CI gate: block the merge until a repo passes a malware scan

2 participants