GeezerVison is showing github.com — Python VEX statements for the agent image no longer apply (subcomponent pinned to a superseded interpreter) · Issue #34 · StackVista/vexhub
Python VEX statements for the agent image no longer apply (subcomponent pinned to a superseded interpreter) #34Description
VEX44's approved disposition and actual internal-hub scanner consumption are independently verified.
Human merge c5d9faa preserved reviewed ff6655e; index-check35438359126 passed. Independent post-merge review downloaded the actual internal hub, matched the approved tree, and verified StringPrep consumption for the published Quay agent tag, index and both architecture digests. Grype consumes it as fixed; unpatched/source-only controls remain active. All six controlled Trivy tests pass, with native StringPrep detection still outside that claim. All32 other statements/dispositions are unchanged; Python CVE-2026-82049 remains active.
PR44 is removed from the human-review queue. Rancher migration/parity remains unverified and tracked through existing vexhub#34 / cve-reporter#29 and the established agent Python VEX audit plan. Current gh and fallback credentials cannot resolve rancher/image-scanning; this is a visibility limitation, not proof of absence. No duplicate migration issue or new scan wave. GO and Agent511 holds remain unchanged; this is not whole-image clearance or ticket closure.
Two reviewed not_affected statements for stackstate-k8s-agent no longer apply,
so the gating chart scan still reports findings they were written to cover.
Reproducing the gate exactly (image-pipeline passes --by-cve) against
quay.io/stackstate/stackstate-k8s-agent:ff38da51, digest
sha256:4ebe6280d7c28e07ab1447e1497fbe855ee1229e9ef38b3e9945145cb0367616:
grype --by-cve --vex pkg/oci/stackstate-k8s-agent/scan.openvex.json \
--vex pkg/golang/github.com/containerd/containerd/scan.openvex.json \
quay.io/stackstate/stackstate-k8s-agent:ff38da51
→ active 10, ignored 3
CVE-2025-15367 and CVE-2026-4360 are among the active findings despite both
carrying reviewed not_affected statements.
Cause: the subcomponent is pinned to a superseded interpreter
Those statements pin subcomponents to pkg:generic/[email protected] (and
@3.13.14 on CVE-2025-15367). The image now reports
pkg:generic/[email protected], and Grype requires the subcomponent to match, so the
statements no longer apply.
Isolated with a single-variable test under the same --by-cve invocation:
appending pkg:generic/[email protected] to CVE-2025-15367's subcomponents and
changing nothing else moves it to ignoredMatches, while CVE-2026-4360 — left
pinned at 3.13.13 as a control — stays active.
The general hazard is that any routine patch bump of an embedded runtime silently
voids every statement written against the previous version, with no error anywhere.
What this needs
Extending these statements to 3.13.15 widens a reachability claim to an
interpreter revision nobody has reviewed, so it needs security review rather than a
mechanical bump. The reviewed premises are about the agent's own code paths (for
CVE-2026-4360, that the sole shipped tar-extraction path excludes hardlinks
before calling tarfile.extract()), so the question for review is whether those
premises still hold on the current default branch — not whether the interpreter
changed.
Four further Python findings on the image have no statement and no exception at
all: CVE-2026-15806, CVE-2026-17084, CVE-2026-19672 and CVE-2026-15310.
None has an upstream fix. Together with the two above, these six are what the chart
gate will still report on the agent once the chart picks up the merged OpenSSL fix.
The interim deferral for CVE-2025-15367 and CVE-2026-4360 lives in the agent
repo with a 2026-09-04 review date, and StackVista/stackstate-agent#501 makes
that date fail closed. Note that a repo-local exception does not affect the
chart gate — the chart scan does not read consumer exception trees — so VEX is the
only artifact that can clear these from the gate.
Correction to the original report
This issue previously claimed that all 23 agent statements were inert, that the
containerd statements were missing the GO- advisory IDs Grype reports, and that
OSV contradicted their rationale. All three were wrong:
- The containerd statements do apply.
image-pipeline runs Grype with
--by-cve, which maps GO- IDs onto their CVE aliases, so the CVE-named
statements match. CVE-2026-50195, CVE-2026-53489 and CVE-2026-53492 are the
three suppressed findings in the run above. The original "0 ignored" measurement
came from omitting --by-cve, which is not how the pipeline runs.
- Their rationale is supported. The upstream advisory
(GHSA-33vj-92qq-66hc and siblings) lists only
github.com/containerd/containerd/v2 in the 2.1, 2.2 and 2.3 lines, with no v1
range — matching the statements, which assert the agent's v1.7.33 is out of
scope. The contradicting v1 entry appears only in the Go vulnerability database,
whose record is marked review_status: UNREVIEWED and carries introduced: 0
with no fixed version and empty ecosystem_specific — the signature of an
uncurated import rather than a curated finding.
- No alias change is needed for our gates. Adding the
GO- IDs to
vulnerability.aliases would still be worthwhile for consumers that do not pass
--by-cve, but it is hygiene, not a fix.
CONTRIBUTING.md guidance has been corrected accordingly in
#35, which also handles all four krb5 findings on this image.
Related coordination ticket: https://github.com/StackVista/cve-reporter/issues/29 Activitychanged the title [-]Agent VEX statements are inert against the current image (stale subcomponent pins, missing scanner advisory IDs)[/-] [+]Python VEX statements for the agent image no longer apply (subcomponent pinned to a superseded interpreter)[/+] on Aug 29, 2026ai-collaboration-app commented on Aug 29, 2026 ContributorAuthor More actions Corrected the report above. The containerd part of the original was wrong: our
pipeline runs Grype with --by-cve, so the CVE-named containerd statements do match
and are suppressing — the earlier "0 ignored" figure came from omitting that flag.
Their rationale also holds; the upstream advisory lists only the /v2 module, and
the contradicting v1 entry exists only as an UNREVIEWED Go-database record.
Do not act on the earlier recommendation to hold off on containerd — there is
nothing to fix there. The live defect is narrower: the two Python statements are
pinned to [email protected]/3.13.14 while the image ships 3.13.15, which is why
CVE-2025-15367 and CVE-2026-4360 are still reported. ai-collaboration-app commented on Sep 6, 2026 ContributorAuthor More actions
Workstream checkpoint — dev scan 34027081656 (attempt 1)
Addressed by PR #39, branch vex/agent-krb5-and-python-3.13.15, head 9124b60473f433102bb72b9cd8536135a8db30ea. CI index-check success. Full checkpoint lives on #38; this note covers the Python half.
Diagnosis confirmed. The image ships CPython 3.13.15 — probed directly via sys.version in the running container on both published architectures — while the statements pinned subcomponents to [email protected]/@3.13.14. Grype requires the subcomponent to match, so CVE-2025-15367 and CVE-2026-4360 did not apply. Both are reported in this run's aggregate.
The review question this ticket posed was answered, not sidestepped. You asked whether the reviewed premises still hold on the current default branch rather than whether the interpreter changed. Checked against the shipped image, which is what the statements are scoped to:
-
CVE-2025-15367 — premise holds unchanged. A recursive search of the entire shipped tree (/opt/stackstate-agent including every stackstate_checks integration, python-scripts/, /etc/stackstate-agent) for poplib and POP3 yields exactly one hit — pydoc_data/module_docs.py, inert documentation data. No import, no POP3 construction, no POP3 port exposed, and /etc/stackstate-agent/checks.d is empty. Also worth noting: fixed is reported as 3.15.0a6, an alpha of a future minor line, so there is no compatible upgrade for the 3.13 series.
-
CVE-2026-4360 — the recorded premise had gone stale. The statement rested on the sole shipped tar-extraction path excluding hardlinks before tarfile.extract() by filtering on isfile(), renaming to bpftool. That path is not in this image at all — bpftool appears nowhere in either architecture's filesystem. So the statement was resting on something no longer true, even though its conclusion survives. The impact statement is restated on current evidence: excluding the stdlib and packaging tooling, the shipped tree contains no first-party tarfile.extract() call. The one remaining call, site-packages/dateutil/zoneinfo/rebuild.py:24, is unreachable three independent ways — nothing imports or calls dateutil.zoneinfo.rebuild; it requires an explicit IANA tarball path plus a zonegroups list and has no caller; and it shells out to zic, absent from both architectures. pyproject_hooks uses zipfile.extractall, not tarfile. pynag's SshConfig uses extractfile()/addfile(), which never create filesystem links, and is only re-exported, never instantiated.
Grype consumption verified, reproducing the gate's --by-cve on ff38da51: both CVEs move to ignoredMatches, nothing becomes newly active, and the result is identical on linux/arm64.
On the general hazard you flagged. You are right that a routine patch bump silently voids every statement pinned to the previous version, with no error anywhere — and #39 hits exactly that, since it pins the new krb5 statements too. #39 records the trade-off explicitly rather than resolving it silently: this repo already contains both conventions, since the merged collector statement (#33) deliberately left its subcomponent unversioned for the opposite reason. Choosing between them across the hub is a policy call worth making deliberately, and it is not made in that PR.
Also corrected here: this ticket's note that the containerd part of the original report was wrong is confirmed — the three containerd statements suppress correctly under --by-cve and stay suppressed across every scan run in this session.
Remaining on this ticket after #39: the four Python findings with no statement and no fix — CVE-2026-15806, CVE-2026-17084, CVE-2026-19672, CVE-2026-15310. Each needs its own reachability analysis and none was written by analogy. This ticket should stay open until they are dispositioned or a later clean dev scan shows them gone. ai-collaboration-app commented on Sep 6, 2026 ContributorAuthor More actions
Round 2 correction — one of the two Python statements should not have been extended
Head is now 44419e79299cfb8c994321fec15b77537f0080ec on PR #39 (CI green). Full checkpoint on #38; this note covers the Python half, because review found my round-1 handling of one CVE wrong.
CVE-2026-4360 should never have been extended to 3.13.15. I treated the inert pin as purely a matching problem and re-derived the reachability argument. The right question was whether 3.13.15 is affected at all — and it is not. The PSF CNA record marks CPython 3.13.0 up to but not including 3.13.15 affected, the 3.13 backport (PR 152610, merge commit eee3ddf0) is an ancestor of tag v3.13.15, and the shipped interpreter's own TarFile.extract source contains the patched filter_function=filter_function call. So the finding is a version-matching false positive, [email protected] now carries status: fixed with that evidence, and the reachability statement is scoped back to [email protected] — which the same record does place inside the affected range.
CVE-2025-15367 is different and its pin is correct. Its CNA record marks everything below 3.15.0a6 affected, so the shipped 3.13.15 genuinely is affected and a reachability statement is the right instrument. The poplib premise was re-established unchanged.
This sharpens the hazard this ticket is about. Version-pinned subcomponents do not just go silently inert — the bump can also change the answer, turning a correct reachability statement into a claim that contradicts the vendor. Re-pinning is therefore not a mechanical edit: it needs a fresh check of the vendor's affected range first, then reachability only if the version is still in range. Both directions of that check now have a worked example in this file.
Still open on this ticket: the four Python findings with no statement and no fix — CVE-2026-15806, CVE-2026-17084, CVE-2026-19672, CVE-2026-15310. Each needs its own vendor-range check followed by reachability analysis; none was written by analogy. ai-collaboration-app commented on Sep 8, 2026 ContributorAuthor More actions
vexhub workstream checkpoint — dev scan 34191503812
Source 3cd8097, artifact chart-scan-aggregate sha256:5a385f54. Repository refreshed to origin/main c7c72a9.
Candidate: PR #40 — three no-fix Python statements, one deliberately left reporting
- branch
agent-python-no-fix-vex, head f6ed36ba3d8f83d65910c136032104b7c7e9c058, signed
- CI
index.json in sync with pkg/ SUCCESS (run 34241880835), mergeable: MERGEABLE, REVIEW_REQUIRED
index.json unchanged — all three statements reuse product PURLs already indexed for this image
Grype --by-cve against the exact gated image, 13 active / 0 ignored without VEX → 1 active / 12 ignored with this file plus the containerd statements. The single remaining active finding is CVE-2026-17084, exactly the one intended to stay visible.
| CVE |
Disposition |
Basis |
CVE-2026-15806 |
not_affected / vulnerable_code_not_in_execute_path |
zero .add_password() call sites in the shipped tree, so no credential is ever registered |
CVE-2026-19672 |
not_affected / vulnerable_code_not_in_execute_path |
extraction_filter is None so the affected filters are never default; the only filter='data' is in the PEP 517 build frontend, which no entrypoint invokes |
CVE-2026-15310 |
not_affected / vulnerable_code_not_in_execute_path |
affected compressors never selected; the only runtime-reachable ZipFile site returns at its os.path.exists guard. Weakest of the three — flagged for separate reviewer judgement |
CVE-2026-17084 |
no statement, stays gating |
reachable: instrumenting the shipped interpreter shows 'straße.Example.COM'.encode('idna') calling stringprep.map_table_b2 six times, with live sites in asn1crypto and pydantic |
All four re-derived 2026-09-08 against stackstate-k8s-agent:158e1098, digest sha256:35e66696a1bdc0d470e0d11d7711e426548a09d31190bdd94cd1350b464dc839 (matches the aggregate's image_digest), counting stdlib modules that define an API separately from code that calls it.
Also brought current: PR #31
It had sat CONFLICTING since 2026-08-19 with CI last run against a three-commit-stale base. origin/main was merged in — not rebased, to preserve the two human-authored signed commits — and the sole conflict (index.json) was resolved by regenerating with tools/build_index.py, verified to add exactly one entry (pkg:golang/github.com/docker/buildx) and drop none of main's 69. Head 9c1adb4b6c50230dbb1c98a776356c9d425e13e8, signed, mergeable: MERGEABLE, CI SUCCESS (run 34240271658), still REVIEW_REQUIRED.
This ticket's original subject is resolved and verified live
The interpreter-pin defect no longer reproduces. In this run's own agent artifact, Grype ignores 9 findings via VEX with CVE-2025-15367 and CVE-2026-4360 both matched against python 3.13.15; the four krb5 statements from #38 and the three containerd statements are live in the same run.
CVE-2025-15367's extension to 3.13.15 was sound rather than a mechanical bump: PSF-2026-4 shows the defect is poplib newline command injection, so the reviewed premise is a property of the agent's code, not of the interpreter revision.
The libopenssl3 CVE-2025-15468 gap must NOT be closed with a statement
The gap is real and measured — on zookeeper:3.9.5-so21 this CVE is VEX-suppressed on openssl and libopenssl-3-fips-provider but stays active HIGH on libopenssl3 and openssl-3, across 15–16 images. No honest justification is available, and the rationale recorded in #36 is a misreading:
#36 records "affects 3.3–3.6, and SUSE lists 3.0 and earlier as unaffected". The upstream advisory actually states: "The vulnerable code was introduced in the 3.2 version with the addition of the QUIC protocol support." It lists 3.6/3.5/3.4/3.3 as vulnerable and 3.0/1.1.1/1.0.2 as not affected — 3.2 appears in neither list, because 3.2 went EOL before the 2026-01-27 advisory. Absence from the vulnerable list is an artefact of 3.2 being unsupported, not evidence of safety.
vulnerable_code_not_present is false for the 3.2.3 stream — the advisory places the vulnerable code in 3.2.
component_not_present cannot be transferred from the openssl sibling: libopenssl3 is precisely the package shipping libssl.so.3, which contains SSL_CIPHER_find().
- The two existing suppressions are independently sound and should stay: the advisory says "the FIPS modules ... are not affected ... as the QUIC implementation is outside the OpenSSL FIPS module boundary", and the
openssl package does not ship libssl.
The only remaining route would be vulnerable_code_not_in_execute_path across every affected image, and it should not be taken, because a fix already exists and is published. Grype names 3.5.0-150700.5.45.2; the live SLE_BCI 15-SP7 probe in suse-observability-mcp-server#62 confirms that version is in the channel and that every rebuild from 2026-08-31 onward installs it. Per CONTRIBUTING.md the correct option is to fix the CVE, not attest around it. The dev-scan residue is a stale chart pin, not a missing patch. The same applies to the 8 unstatemented MEDIUMs on libopenssl3 (CVE-2025-15469, CVE-2025-4575, CVE-2025-66199, CVE-2025-9231, CVE-2025-9232, CVE-2026-2673, CVE-2026-34182, CVE-2026-42764) — all carry the same available fix and all stay visible.
New finding: every rpm statement in this hub is inert under Trivy
Two independent identifier mismatches, both verified against this run's artifacts and a local trivy vex repo download:
- PURL namespace. Trivy emits
pkg:rpm/suse/[email protected]?arch=x86_64&distro=sles-15.7. Every statement and every index.json rpm id in this hub uses pkg:rpm/sles/.... The lookup can never hit. Grype uses sles, which is why these statements work there and only there.
- Vulnerability ID. Trivy's only SLES rows are
SUSE-SU-2026:3835-1 (source suse-cvrf), a rolled-up advisory rather than a CVE, so CVE-keyed statements cannot match it. ExperimentalModifiedFindings is empty on both zookeeper and suse-observability-mcp, i.e. Trivy applied zero VEX suppressions.
Leaving SUSE-SU-2026:3835-1 visible is correct — it bundles the genuinely-unfixed-in-3.2.3 CVEs, so suppressing it would hide real remediation work. But README.md's claim that statements are "consumed by Trivy directly via --vex repo" is currently false for every rpm statement, and openssl gate relief comes from Grype alone. Recording rather than changing: adding pkg:rpm/suse/... products is a reviewed scope decision, not something to fold into an unrelated PR.
Verified, not asserted
- Trivy cache layout is correct, contrary to the nested-layout hazard. A local
trivy vex repo download lands index.json and all 13 OpenVEX documents at the version root (.../vex/repositories/suse-observability/0.1/index.json), with no vexhub-main/ directory anywhere; the CI document list resolves the same way. The tarball's sole top-level directory is vexhub-main/, so the //vexhub-main suffix in vex-repository.json is stripping it as intended — removing it would break the layout. The cache survived a forced refresh with all 13 documents intact, so it is populated rather than gutted.
- Statement effects were read from the run's own
grype.json/trivy.json artifacts and from direct scanner invocations, never inferred from file contents.
- 1138 OpenVEX documents were fed to Grype in this run, consistent with #62.
Separately noted: a lapsed review commitment
pkg/oci/opentelemetry-target-allocator/scan.openvex.json carries five statements whose status_notes promise "Review by 2026-07-29" — 6 weeks overdue. The retirement condition is not met: github.com/docker/docker v28.5.2+incompatible is still in that image. Only 2 of the 5 (CVE-2026-33997, CVE-2026-34040) suppress anything; CVE-2026-41567, CVE-2026-41568 and CVE-2026-42306 are inert. Flagged for human re-review rather than renewed or removed unilaterally — the premise (the target allocator is not a Moby daemon) is structurally stable, so this is housekeeping, not a broken claim.
Also uncovered and out of this workstream's scope: Trivy reports GO-2026-5932 on golang.org/x/[email protected] for the agent image; the existing GO-2026-5932 statement covers the collector, not the agent.
Remaining work
- Human review of PR VEX three no-fix Python findings on the agent image, leave the reachable one visible #40 and PR Document ai-collaboration Moby server CVEs as not affected #31. Approval and merge are outside agent authority; VEX approval is explicitly a human decision.
- Publication obligation open: a merged statement must be downloadable from the hub and confirmed in a scan before it suppresses anything.
- Rancher mirror obligation open —
rancher/image-scanning migration issue per CONTRIBUTING.md step 6; no internal statement to be removed before that entry is published and both scanners verified against it.
CVE-2026-17084 stays an open, visible, gating finding on the agent image. It needs an embedded-CPython bump once upstream ships a fix; it must not be VEXed.
- Advance the chart pin / rebuild for the openssl cluster to pick up
libopenssl3 3.5.0-150700.5.45.2. Owners: docker-images (managed base stackstate-base), stackstate-ailab (spotlight), suse-observability-mcp-server. Not this repository's source.
- Decide whether to add
pkg:rpm/suse/... products so rpm statements apply under Trivy, and correct the CVE-2025-15468 rationale recorded in VEX the SLE 15 SP7 openssl 3.2.3 findings Grype resolves to the 3.5.0 rebase #36.
- Human re-review of the five lapsed target-allocator statements.
Next action: hold for human review of PR #40 and PR #31. This ticket stays open — a merged PR is not closure evidence, and closure requires a later complete clean dev scan plus a clean review of exact no-change evidence.
MetadataMetadataDevelopmentNo branches or pull requestsIssue actions
|