Repository navigation
v0.5.0
Cordon 0.5.0
From a repository scanner to the client side of a supply-chain platform.
┌──────────────────────────────────────────────────────────────────────────┐
│ Every addition is opt-in or offline-safe. A scan with no new flags │
│ finds what 0.4 found, plus the new detectors below, and sends nothing │
│ anywhere it did not before. No feed root key is pinned in this │
│ release, so a default scan makes no network request at all. │
└──────────────────────────────────────────────────────────────────────────┘
Map of this release
├─ Install ................ pipx · the Action · the container
├─ What a scan finds ...... the agent chain, artefacts, dependencies, install time
├─ Fewer false blocks ..... what stopped failing builds it should not
├─ New commands ........... SBOMs, notifications, intel, the cloud client
├─ Measured ............... detection and false-block rates
└─ Verify it .............. hashes, signatures, provenance
Install
pipx install cordon-scanner==0.5.0
GitHub Action uses: Threx-code/cordon/action@fd7e0d5b15c17de4cbe4eb1e298d56f0ff3e31b9
(that commit pins cordon-scanner 0.5.0 by hash in action/requirements.txt,
so pinning the Action by SHA pins what pip downloads)
Container ghcr.io/threx-code/cordon:0.5.0 pin it by digest in a pipeline
Bitbucket pipe ghcr.io/threx-code/cordon-bitbucket-pipe:0.5.0
VS Code cordon-0.5.0.vsix (attached below)
From scanner to platform client
0.4 0.5
┌──────────────────────────────────┐ ┌──────────────────────────────────────────────┐
│ scan a repository, locally, │ │ everything 0.4 did, plus, all opt-in: │
│ offline, nothing sent anywhere │──▶│ │
└──────────────────────────────────┘ │ login ······ device flow through your SSO │
│ logout ····· revokes the sign-in in the cloud│
│ --upload ··· signed results (DSSE / in-toto) │
│ --cloud-policy Ed25519-verified org policy │
│ runner ····· outbound-only job runner │
│ agent ······ MDM inventory of AI agents │
│ --judge ···· a model reads agent-facing text │
└──────────────────────────────────────────────┘
What a scan finds
THE AGENT CHAIN
├─ Agent Threat Rules ........ 815 of the 825 open ATR rules, matched the way ATR matches
│ (97.7% of 4,026 attacks found, 92.5% of benign left clean)
├─ what a config runs ........ hooks, MCP launches, autorun tasks classified by what they do:
│ fetch-and-execute, exfiltration, a reverse shell
├─ where traffic goes ........ an API base URL pointed at someone else (CVE-2026-21852)
├─ what an MCP server gets ... the Docker socket, host root, injected env, plain-http remotes,
│ lookalike packages, broad token scopes
├─ tool descriptions ......... poisoning read in an MCP server's own descriptions
├─ instruction files ......... CLAUDE.md, AGENTS.md, Cursor/Windsurf rules, skills, commands
└─ the judge (--judge) ....... cordon-cloud, anthropic, openai:<model>, ollama:<model>;
only agent-facing text is sent; a verdict must quote evidence
ARTEFACTS
├─ archives in a directory ... opened and scanned (--no-expand skips, marked incomplete)
├─ models ................... pickles importing os.system and friends, PyTorch zips; never loaded
├─ documents ................ macros that run on open, remote templates, DDE, PDF auto-actions
├─ images ................... payloads appended to images
└─ container images ......... dpkg, apk and RPM inventories from docker save / OCI tarballs
DEPENDENCIES
├─ exploited CVEs ........... on CISA KEV or ENISA EUVD: CRITICAL
├─ slopsquatting ............ hallucinated names offline; unregistered names with --online
├─ lookalikes ............... a package named like a popular one
├─ ranges ................... a range that admits a known-malicious release
└─ reachability ............. modelled at import tier; function level for Go, PyPI and npm
INSTALL TIME
├─ .pth startup files, payloads that hide their own code, code spelled as character codes
├─ persistence (systemd, written a path component at a time), miners under other names
├─ callbacks and beacons, commands held in variables and f-strings
└─ ClamAV, optional: --clamav hands each file to your own daemon
Fewer false blocks
NO LONGER FAILS A BUILD WHY
workspace members, link: entries, npm aliases ...... not registry packages
fetch-and-run a person has to ask for .............. not an install-time action
agent instructions that install a CLI .............. ordinary setup, not an attack
infrastructure in tests, examples, vendored code ... not what the project ships
a token sent to the service that issued it ......... that is how tokens work
a tool's own official installer .................... the vendor's documented path
OAuth client IDs ................................... identifiers, not secrets
withdrawn advisories ............................... no longer shipped
Go dependencies pinned to a commit ................. now match their advisories
a word in a package's directory name ............... no longer silences its install hook
New commands
sbom generate --vulnerabilities advisory matches in the CycloneDX SBOM, KEV/EUVD marked
sbom generate --ai the AI bill of materials (CycloneDX 1.6)
--notify slack,teams,webhook a failed gate posted; the webhook is a signed event
intel status | update the signed, TUF-style intel feed
login · logout · whoami Cordon Cloud sign-in; logout revokes it in the cloud
scan --upload · --cloud-policy signed results up, the organisation's policy down
runner [--git-credential] outbound-only scan jobs, private GitLab and Bitbucket clones
agent inventory | report this machine's agents and MCP servers, for MDM
schemas/ the contracts with the cloud, K1 to K9
CI templates GitLab, Bitbucket, Azure, CircleCI, Jenkins, hash-pinned
Measured
CORPUS RESULT
39,002 real malicious packages, by content alone 94.1% detected
995 of them, against GuardDog 95.4% (GuardDog 83.9%)
top 1,000 PyPI + 1,000 npm, wrongly blocked 1.6% (GuardDog 16.8%)
100 lockfiles, CVEs agreed with Trivy and OSV 98.4%, every disagreement explained
ATR attack cases / benign cases 97.7% found / 92.5% left clean
372 real agent-config repositories, never tuned on 1.1% blocked, each block read and correct
521 known-malicious pins / 940 known-vulnerable 100% reported / 100% reported
method and caveats for every number: docs/08-ACCURACY.md
Verify it
wheel and sdist ... signed, SLSA build provenance; PyPI serves exactly what was uploaded
sha256 2f484ac0109acbf258d745dd1e3eb4e9cdbf9f4b2c2598d1381440ffeda00821
sha256 736c2137dec418d10ba9572fb8d5630bb58b37dfadd3af043855c1b3bbbf5145
images ............ signed keylessly with cosign, SLSA provenance
SBOMs ............. sbom.cdx.json and sbom.spdx.json attached below
install by hash ... pip install --require-hashes -r action/requirements.txt
Every change, in full: CHANGELOG.md, 0.5.0.