All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
1.2.0 — 2026-05-18
check.sh --verify-self— the script now fetches its own SHA-256 manifest from the matching GitHub Release and compares it against the hash of the local copy. Exits 0 on match, 4 on mismatch, 5 on network/parse error. Lets users verify the script hasn't been tampered with locally without having to re-download.- Sigstore keyless signing of
check.shandcheck.sh.sha256on every release. Each release ships an additional.sigstore.jsonbundle that anyone can verify withcosign verify-blob --bundle … --certificate-identity-regexp 'https://github.com/.../\.github/workflows/release\.yml@.*' --certificate-oidc-issuer https://token.actions.githubusercontent.com. Bound to this workflow path via OIDC; no key management on either side. - Trojan-Source linter in the
testsworkflow. Refuses to land bidi-override / zero-width / BOM characters incheck.sh,entrypoint.sh,action.yml,Dockerfile,tests/smoke.sh, or any.github/workflows/*.yml. Defends against CVE-2021-42574-style invisible-malware PRs. - Structured issue templates under
.github/ISSUE_TEMPLATE/: bug reports require version + entrypoint + reproducer + confirmations; new IOC requests require a public source URL + false-positive-risk assessment. Blank issues disabled. - PR template with a mandatory security checklist (no new runtime deps, every regex change tested, no non-ASCII in security-critical files, pinned SHAs, attribution for new IOCs).
docs/THREAT-MODEL.md— public threat model with attacker profiles, vector × control matrix, trust-boundary statement, and end-to-end verification recipe for outside auditors.
CONTRIBUTING.mdcodifies six mandatory PR rules (test required for regex/IOC changes, no non-ASCII, ≤100 LOC forcheck.shchanges without a prior issue, public attribution for IOCs, no third-party bundling, no new runtime deps).dependabot.yml:open-pull-requests-limitlowered from 5 to 3 to reduce review-fatigue risk on Dependabot PRs (the load-bearing defence against tag-rewrite attacks upstream).
1.1.2 — 2026-05-18
- Additional Mini Shai-Hulud IOCs cross-checked with
nkopylov/tanscript-exploit-check:- 3 known payload SHA-256 hashes — computed when a payload-shaped file is
found in
node_modulesand reported alongside the filename match. opensearch_init.jsandvite_setup.mjsadded toPAYLOAD_FILES.opensearch_initadded to the active-payload-process pgrep regex.- Known malicious commit SHA
79ac49ee…cfe5885cflagged when referenced in anypackage.jsonundernode_modules. - C2 IP literal
83.142.209.194added toC2_DOMAINS_RE. - Dune-themed Mini Shai-Hulud branch pattern (
dependabot/github_actions/format/<atreides|fremen|harkonnen|…>) — 22 codewords. - Additional pinned bad versions:
@tanstack/react-start@1.167.68,@1.167.71,@tanstack/router-plugin@1.167.38,@1.167.41. - GitHub Actions Check 7 now flags
codeql_analysis.ymlworkflows that containtoJSON(secrets)— the signature exfiltration pattern.
- 3 known payload SHA-256 hashes — computed when a payload-shaped file is
found in
SECURITY.md: new section "Recognising follow-on social-engineering attempts" documenting a phishing pattern observed against detector authors in this niche.
1.1.1 — 2026-05-16
- Check 8 C2-domain and disposable-host grep now excludes documentation
files (
*.md,*.markdown,*.rst,*.txt), the project's own root docs (CHANGELOG*,README*,SECURITY*,FAQ*,CONTRIBUTING*), andcheck.shitself. The v1.1.0 self-test failed because the checker was flagging the IOC list inside its own CHANGELOG as a C2 reference.
1.1.0 — 2026-05-16
- New Check 8 — Mini Shai-Hulud payload + auxiliary IOCs. Covers payload
files in
node_modules(router_init.js,tanstack_runner.js,router_runtime.js), the@tanstack/setupoptionalDependency infection vector, payload artefacts on host and in repo (~/.claude/router_runtime.js,.claude/setup.mjs,.vscode/setup.mjs), AI-tool config tampering (Claude Codesettings.json,mcp.json, Kiromcp.json, VSCodetasks.json), C2 / exfiltration domain references in source (api.masscan.cloud,git-tanstack.com,getsession.org,litter.catbox.moe), attacker commit author (claude@users.noreply.github.com), suspicious branch patterns (dependabout/*/setup-formatter— the typo is the attacker fingerprint), ransom-marked npm tokens, and active payload processes. - Worm-propagated secondary victim packages added to the known-bad list and
detected by family-name in
node_modules:@mistralai/mistralai,@mistralai/mistralai-azure,@mistralai/mistralai-gcp,@opensearch-project/opensearch,@draftlab/auth,@draftlab/auth-router,@draftlab/db,safe-action. - Heuristic / zero-day-style flagging (info severity, never fails the
build): suspicious payload-shaped filenames in
node_modulesoutside the exact known list, disposable-endpoint hosts (webhook.site,ngrok,requestbin.net, etc.) referenced in source, coercion-language in npm token descriptions, non-empty global gitcore.hooksPath. - Tests now ship in
tests/: a smoke suite withclean-projectandcompromised-projectfixtures, exercised by a newtestsCI workflow that also runsshellcheckoncheck.sh/entrypoint.sh/smoke.sh.
scorecard.ymlpins ofossf/scorecard-actionandgithub/codeql-actionresolved through their annotated-tag SHAs to the underlying commit SHAs (the tag-object SHA was being rejected by Scorecard's webapp verification as an imposter commit).check.shadd_finding: splitlocal+assignment to stop masking command-substitution exit codes (shellcheck SC2155).
Dockerfiledeclares a non-roottccuser (UID 1001, matching the GitHub Actions runner UID) so the container no longer runs as root.
- Added LICENSE (MIT),
.gitignore,CONTRIBUTING.md,CODE_OF_CONDUCT.md(Contributor Covenant 2.1, official text),CHANGELOG.md.
1.0.0 — 2026-05-16
- Seven-stage detection script (
check.sh) for the TanStack npm supply-chain attack (CVE-2026-45321 / GHSA-g7cv-rxg3-hmpx): dead-man's switch artefacts, persistence vectors, credential exposure, network IOCs,package.json+ lockfile scanning, installednode_modulesverification, and GitHub Actions hardening hints. --onlinemode: fetches the GHSA advisory and confirms compromise via the npm registry'stime[<version>]field instead of relying solely on a hard-coded version list.--jsonoutput for SIEM and CI integration.- Multi-arch Docker image published to
ghcr.ioon every tagged release, with signed SLSA build provenance verifiable viagh attestation verify. - GitHub Action wrapper with explicit inputs, outputs, and a hardened self-test workflow that runs the action against its own repository.
- Release workflow that ships
check.sh+check.sh.sha256on every tag, letting users verify the script before running it. - Repo-level hardening: every
uses:pinned to a 40-character commit SHA,permissions: {}at workflow root,persist-credentials: falseon every checkout,step-security/harden-runneras the first step, OpenSSF Scorecard analysis weekly, Dependabot for github-actions and Docker pins.