Summary
The fleet's security gate is cargo audit (sovereign-ci.yml:1191, job security).
cargo audit and cargo deny check advisories both read the RustSec advisory DB.
GitHub's Dependabot reads the GitHub Advisory Database (GHSA). These are different
databases, and RustSec is not a superset.
Where GHSA has an entry and RustSec does not, our required security check reports
green over a live, GitHub-confirmed vulnerability.
Witness (reproducible today)
pmat, release/3.32.0, commit 419360b6f:
$ gh api repos/paiml/paiml-mcp-agent-toolkit/dependabot/alerts/66 \
--jq '[.state,.security_advisory.severity,.security_advisory.ghsa_id,.dependency.package.name]'
["open","medium","GHSA-2f9f-gq7v-9h6m","thrift"]
CVE-2026-43868 — Apache Thrift: Memory Allocation with Excessive Size Value
vulnerable: thrift < 0.23.0 present: thrift 0.17.0
$ cargo deny check advisories
advisories ok # <-- the gate
$ git -C ~/.cargo/advisory-db log -1 --format='%h %ci'
69f93e1d 2026-08-12 12:42:29 +0200 # DB is fresh, not stale
$ git -C ~/.cargo/advisory-db grep -il thrift -- crates
# <-- no output. No thrift advisory exists in RustSec at all.
$ git -C ~/.cargo/advisory-db grep -rl CVE-2026-43868
# <-- no output.
So this is not a stale-DB problem and not a misconfigured-ignore problem
(deny.toml's ignore list does not mention thrift). RustSec simply has no entry.
cargo audit uses the same DB, so the CI gate is blind by construction.
Open Dependabot alerts on pmat: 1. Advisories reported by the gate: 0.
Five whys
- Why did a live medium CVE pass the security gate? —
cargo audit reported clean.
- Why did
cargo audit report clean? — the RustSec DB has no advisory for thrift.
- Why does RustSec have no advisory? — CVE-2026-43868 was filed against Apache Thrift
upstream; GitHub maps it onto the thrift crate via its ecosystem mapping, RustSec
has no such automatic mapping and depends on a volunteer filing a per-crate advisory.
- Why does the gate depend on a single DB? — the gate was specified as a tool
(cargo audit) rather than as a property ("no known-vulnerable dependency"),
so its coverage was never stated and therefore never checked.
- Root cause — the gate reports the result of one query and we read it as the
answer to a broader question. There is no denominator: advisories ok looks
identical whether the DB has 700 relevant advisories or none for your tree.
Same family as #1016 (cargo deny licenses+sources suppressed fleet-wide) —
absence rendered as success.
Proposed fix
Add a second, independent source to the security job so the two DBs cover each
other. GitHub's own alerts are the cheapest option — zero new tooling, no new
dependency, and it is the DB that already caught this:
- name: Dependabot alerts (GHSA — covers what RustSec lacks)
env: { GH_TOKEN: "${{ secrets.GITHUB_TOKEN }}" }
run: |
# cargo audit reads RustSec; this reads GHSA. Neither is a superset of the
# other — see paiml/.github#<this issue> for a live case (thrift/CVE-2026-43868).
alerts=$(gh api --paginate \
"repos/${GITHUB_REPOSITORY}/dependabot/alerts?state=open&severity=high,critical" \
--jq '.[] | [.security_advisory.ghsa_id, .dependency.package.name] | @tsv')
if [ -n "$alerts" ]; then
echo "::error::open high/critical Dependabot alerts:"; echo "$alerts"; exit 1
fi
echo "no open high/critical Dependabot alerts"
Needs security-events: read (or contents: read + repo scope) on the job.
Threshold set at high/critical so it can be turned on fleet-wide without
immediately reddening every repo; medium stays advisory-only for now.
Verify the gate is real before merging (per the dogfood protocol): confirm it
goes RED on a repo with a known open high alert and GREEN on one without, and
record both in the PR. A security gate nobody has watched fail is exactly the
thing this issue is about.
Separate, downstream fix for the thrift exposure itself
thrift 0.17.0 reaches us as parquet 57.3.1 -> aprender-db -> {aprender-graph, aprender-rag}.
parquet 59.2.0 removed the thrift dependency entirely (arrow-rs replaced it with an
in-tree codec) — verified against the crates.io dependency API. So the fix is an
arrow/parquet 57 -> 59 bump in aprender-db, not anything in pmat. Filed separately.
Risk to pmat specifically is low (the vuln is oversized-allocation on parsing attacker-
controlled parquet metadata; pmat parses no untrusted parquet), but the gate being blind
is the finding, not this particular crate.
Summary
The fleet's security gate is
cargo audit(sovereign-ci.yml:1191, jobsecurity).cargo auditandcargo deny check advisoriesboth read the RustSec advisory DB.GitHub's Dependabot reads the GitHub Advisory Database (GHSA). These are different
databases, and RustSec is not a superset.
Where GHSA has an entry and RustSec does not, our required security check reports
green over a live, GitHub-confirmed vulnerability.
Witness (reproducible today)
pmat,
release/3.32.0, commit419360b6f:So this is not a stale-DB problem and not a misconfigured-ignore problem
(
deny.toml's ignore list does not mention thrift). RustSec simply has no entry.cargo audituses the same DB, so the CI gate is blind by construction.Open Dependabot alerts on pmat: 1. Advisories reported by the gate: 0.
Five whys
cargo auditreported clean.cargo auditreport clean? — the RustSec DB has no advisory forthrift.upstream; GitHub maps it onto the
thriftcrate via its ecosystem mapping, RustSechas no such automatic mapping and depends on a volunteer filing a per-crate advisory.
(
cargo audit) rather than as a property ("no known-vulnerable dependency"),so its coverage was never stated and therefore never checked.
answer to a broader question. There is no denominator:
advisories oklooksidentical whether the DB has 700 relevant advisories or none for your tree.
Same family as #1016 (
cargo denylicenses+sources suppressed fleet-wide) —absence rendered as success.
Proposed fix
Add a second, independent source to the
securityjob so the two DBs cover eachother. GitHub's own alerts are the cheapest option — zero new tooling, no new
dependency, and it is the DB that already caught this:
Needs
security-events: read(orcontents: read+ repo scope) on the job.Threshold set at high/critical so it can be turned on fleet-wide without
immediately reddening every repo; medium stays advisory-only for now.
Verify the gate is real before merging (per the dogfood protocol): confirm it
goes RED on a repo with a known open high alert and GREEN on one without, and
record both in the PR. A security gate nobody has watched fail is exactly the
thing this issue is about.
Separate, downstream fix for the thrift exposure itself
thrift 0.17.0reaches us asparquet 57.3.1 -> aprender-db -> {aprender-graph, aprender-rag}.parquet 59.2.0removed the thrift dependency entirely (arrow-rs replaced it with anin-tree codec) — verified against the crates.io dependency API. So the fix is an
arrow/parquet
57 -> 59bump inaprender-db, not anything in pmat. Filed separately.Risk to pmat specifically is low (the vuln is oversized-allocation on parsing attacker-
controlled parquet metadata; pmat parses no untrusted parquet), but the gate being blind
is the finding, not this particular crate.