Every CI/CD security tool I've used answers the same question: does this artefact look bad? gitleaks scans for secret patterns. trivy checks CVEs. checkov validates policy. Run them all and you still can't answer the question that actually matters:
Where does authority go in my pipeline, and does it go further than it needs to?
Pattern scanners evaluate one thing at a time. They don't model how a secret in step 3 is in scope for the unpinned third-party action in step 5. That gap is what taudit is for.
The problem in a real workflow
Here's a GitHub Actions workflow that pattern scanners will mostly pass:
What's actually wrong:
- — GITHUB_TOKEN can push code, create releases, modify packages. The job only needs .
- — tag-pinned, not SHA-pinned. A supply chain compromise on this action runs with GITHUB_TOKEN and in scope of both secrets.
- — a long-lived static credential injected into a build step that also runs third-party code with network access.
- — passed directly to . The action author controls what points to. Today it's fine. Tomorrow it isn't.
A pattern scanner flags the tag pin (maybe). taudit shows the authority graph:
The graph is the product. The path is the proof.
The model
taudit parses pipeline YAML into a directed authority graph. Nodes are things that hold or carry authority:
- — a unit of execution (run: or uses:)
- — a credential injected from the secrets context
- — GITHUB_TOKEN, OIDC tokens, service principals
- — data passed between steps or jobs
- — the action or container a step delegates execution to
Edges model how authority flows between them:
| Edge | Meaning |
|---|---|
| HasAccessTo | A step can read this secret or identity |
| UsesImage | A step delegates execution to this action or container |
| Produces / Consumes | Artifact data flowing between steps |
| DelegatesTo | Cross-job authority boundary |
Every node carries a trust zone:
| Zone | What it covers |
|---|---|
| FirstParty | Code you own: run: steps, local actions in your repo |
| ThirdParty | SHA-pinned external actions — the code is immutable at that digest |
| Untrusted | Tag-pinned actions, fork PRs, user-controlled input |
Propagation analysis
Once the graph is built, taudit BFS-walks from every authority-bearing source — secrets and identities — following edges. When authority crosses from a higher-trust zone to a lower one, that's a finding. Every finding includes the full propagation path from source to sink.
This is the thing pattern scanners can't do. They evaluate artefacts. taudit evaluates the graph.
The parser marks AuthorityCompleteness on every graph: Complete if it resolved the full picture, Partial if it hit something it couldn't expand. No silent incompleteness — if the model is partial, the output says so.
What it catches
Six rules today:
| Rule | What it detects | Evidence |
|---|---|---|
| AuthorityPropagation | Secret or identity reaches a lower-trust zone | BFS propagation path in every finding |
| OverPrivilegedIdentity | GITHUB_TOKEN granted broader scope than it uses | IdentityScope classification on Identity nodes |
| UnpinnedAction | Third-party action without a SHA digest pin | Deduplicated across all jobs |
| UntrustedWithAuthority | Unpinned action has direct secret or identity access | Cross-referencing pinning + HasAccessTo edges |
| ArtifactBoundaryCrossing | Artifact from a privileged step crosses trust boundary | Produces/Consumes edge traversal |
| LongLivedCredential | Secret name matches static credential patterns | Name pattern matching on Secret nodes |
Severity is graduated on real signal. GITHUB_TOKEN (contents: read) reaching a SHA-pinned action with no further propagation is Medium. GITHUB_TOKEN (write-all) reaching an unpinned action that also has direct secret access is Critical.
How it compares
| Capability | gitleaks | trivy | checkov | taudit |
|---|---|---|---|---|
| Secret pattern detection | Yes | — | — | No (not our job) |
| CVE scanning | — | Yes | — | No (not our job) |
| IaC policy | — | — | Yes | No (not our job) |
| Authority graph | — | — | — | Yes |
| Propagation analysis | — | — | — | Yes |
| Trust boundary detection | — | — | — | Yes |
| Path evidence in findings | — | — | — | Yes |
| Remediation routing to right tool | — | — | — | Yes |
taudit is complementary. Run it alongside your existing tools.
Scored by Claude Code
This assessment was independently reviewed and scored by Claude Code against the taudit codebase, test suite, and documentation.
| Property | Score | Evidence |
|---|---|---|
| Path evidence on every finding | 9/10 | PropagationPath is a first-class type; every finding carries the full edge vector from source to sink |
| Parser completeness honesty | 8/10 | AuthorityCompleteness::Partial marks graphs when the parser can't fully resolve; inferred secrets in run: blocks detected |
| Zero false positives on real pipelines | 8/10 | Validated on 10 production workflows across taudit, tsafe, CellOS repos; constrained+pinned graduated to Medium |
| Remediation routing | 9/10 | TsafeRemediation and CellosRemediation are typed recommendations routing to the correct tool in the governance loop |
| Rule coverage (GHA today) | 7/10 | 6 rules covering the main failure classes; ADO/GitLab parsers are next milestone; reusable workflow expansion not yet supported |
| Test coverage | 8/10 | 62 tests, unit + integration + sink; residue and propagation engine well-covered |
The governance loop
taudit sits in a closed loop with tsafe and CellOS:
- scans pipeline YAML, builds the authority graph, flags where privilege leaks
- constrains secrets to the specific steps that need them
- enforces execution — the cell gets what the spec authorised, nothing else
Findings route to the right tool by design. The loop closes: detect over-authority, constrain secrets, isolate execution, observe again.
Current state
Six crates, 62 tests, ~3,500 LOC. taudit-core has zero I/O dependencies — pure domain, ports and adapters throughout. GitHub Actions only for now. Ships terminal, JSON, and CloudEvents JSONL output today.