Skip to content

The supply chain: releases, pipelines, history

The October 2026 campaigns did not break into anyone's cloud. They got committed, built and published, then spent the trust of the pipeline to reach the cloud.

software supply chain securitypoisoned package detectionCI workflow tampering

The problem

A supply chain attack does not need a vulnerability in your code. It needs one of three things: a release you install, a pipeline that builds you, or a credential that was committed once and deleted.

Those are three different failures with three different owners, which is why they are usually three tools. A code scanner sees the repository. A package scanner sees the manifest. Nothing sees the sequence, and the sequence is the attack.

The campaigns documented in October 2026 share one shape. Reach a trusted artefact, use that trust to get execution inside a build or a developer's machine, then use the credentials found there against the cloud. LiteLLM 1.107.0 was a lookalike repository publishing cook.pth and sitecustomize.py; GhostAction injected security-audit.yml through pull_request_target abuse and mined 3,325 secrets out of git history; the clients were quarantined in about two hours, which is roughly the same order as the time it took to be consumed.

How Hanu approaches it

Releases are judged by freshness and provenance together

A dependency published twenty hours ago is treated differently from one that has been stable for a year, because a compromise window is short and an attacker gains nothing by waiting. Freshness gates are 24 hours for dependencies and 72 hours for your own packages.

A missing provenance attestation on its own is common and mostly benign — plenty of legitimate packages have none. A provenance gap escalates only when it sits beside another anomaly: a fresh release, an unfamiliar publisher, or the artefact being invoked from a cloud account for the first time. SUSPICIOUS_PACKAGE_RELEASE records which of those conditions were met, so the reason is in the finding.

The pipeline is treated as an untrusted environment

CI_WORKFLOW_TAMPER fires on a change to a workflow file in a repository that holds credentials, recording the commit, the path and the actor. Alone it is not worth blocking a merge — workflow edits are routine maintenance. It becomes CRITICAL when the same workflow later makes a secret readable, which is the correlation behind RULE-T2-014.

History is part of the surface

A secret deleted from a branch two years ago is still in the history an attacker clones in seconds. Exposure is evaluated against history rather than against the current tree, and the finding names the ref and the commit so rotation can be scoped to the credential that was actually exposed instead of the whole account.

Three supply-chain signalseach one insufficient on its own
SignalWhat it recordsWhy it is not enough alone
SUSPICIOUS_PACKAGE_RELEASEpublisher, version age, provenance status, first seen in estatemost fresh releases are legitimate
CI_WORKFLOW_TAMPERcommit, workflow path, actor, repository sensitivityworkflow files change constantly
SECRET_LEAKEDcredential type, path, ref, commit agemany exposed keys were already revoked

What you get

SC-01Release admission, recorded per artefact
Every release you consume is recorded with its age, publisher, provenance status and the first time it was seen in your estate — so a patch published overnight is visible as exactly that rather than as another line in a lockfile diff.
SC-02Pipeline integrity with repository sensitivity
Workflow changes, unpinned third-party actions and actor identity are tracked per repository, and repositories holding deploy credentials are marked sensitive. The same edit is a different severity in two places, which is the correct behaviour.
SC-03Credential exposure that includes history
Committed secrets are found in history, not just in the working tree, and the finding carries the ref and the commit. Rotation scoped to one credential is a five-minute job; rotation scoped to an account is a fortnight.
SC-04The join nobody else makes
A compromised release, a tampered workflow and a cloud credential used from a new location inside one window produce one CRITICAL risk instead of three medium findings that each get triaged away.

Limits

This is not a sandbox and it does not detonate packages. Judgements come from metadata, provenance, freshness and the observed behaviour of the things that consume a release — not from executing it in a container and watching what it does.

The unpinned-action check is deliberately opt-in (opts.includeHygiene). Referencing an action by tag rather than by commit SHA is extremely common; leaving that rule on for a full organisation scan would produce thousands of findings and teach your team to ignore the queue entirely. It is on for the pull-request gate, where the same finding is a five-minute fix.

Package coverage depends on what you connect. The forges and registries you attach are the ones whose releases, publishers and provenance can be reasoned about; anything outside that set is invisible to this view.

We do not republish other people's vulnerability research. Where a campaign has been documented publicly we describe the mechanism and what our own detections would have observed, and we cite the reporting rather than restating it as our own finding.

Questions

Will this block a pull request because a workflow changed?
Not by default. The correlation gate is opt-in per repository and you choose which repositories gate. A workflow change in a repository that holds deploy credentials is what raises the severity, and that threshold is yours to set.
How current is the release-freshness check?
Freshness is evaluated when the release is observed, using the publish timestamp from the registry. There is no nightly batch that would make a 24-hour window meaningless by the time it runs.
What do you mean by provenance?
An attestation tying a published artefact to the build that produced it — SLSA-style. Hanu records whether one exists and whether it verifies, and treats its absence as context that contributes to a score rather than as a finding by itself.
After a compromise, can you tell us which services are affected?
Yes, and that is the reason dependency relationships live in a graph rather than in a scanner report. When an advisory lands you can ask which services resolve to the affected version, and which of those are reachable from the internet.

Run it in your own account

One Docker Compose stack, your datastores, read-only credentials into your clouds. The Community edition is free to run in production.