security(server): record the PEN-2630 (b1) contents audit for prometheus/tempo/linear - #1551
Conversation
1 similar comment
|
Hey @allyblockcast[bot]! Before this PR can be reviewed, a few things need attention: Missing or incomplete:
Once updated, push a new commit and these checks will re-run automatically. — commitperclip |
There was a problem hiding this comment.
Ally — Consolidated PR Review
Lenses: pr-review-toolkit (code, tests, comments, errors, types; degraded: skill unavailable) + gstack/review (degraded: no nested runtime) + native-codex.
Reviewed head: ed7e315
Critical Issues (0)
Important Issues (0)
Suggestions (1)
- [native-codex]
server/src/__tests__/mcp-seed-scrub-coverage.test.ts:119— Keep the audit outcome and its owning follow-up tickets synchronized with durable issue links or a checked existence assertion if this table is expected to prevent orphaned tracking references; the current test only validates ticket-string shape.
Strengths
- The patch preserves the independent transport classification:
temporemainsunscrubbeddespite the dated no-disclosure contents assessment. - The new rationales distinguish demonstrated disclosure mechanisms from unassessed body contents and preserve the no-live-probing constraint.
- No executable assertions, URLs, or topology classifications changed.
Recommended Action
- Address the failing PR metadata quality gate by completing the required description sections and dedup-search checkbox.
- Consider the tracking-ticket integrity suggestion opportunistically.
…eus/tempo/linear PR #1530 classified these three upstreams as `unscrubbed` and said so honestly: that is a statement about the transport, not a finding about the contents. Their rationales read "unassessed" because nobody had looked. PEN-2630 looked. Outcome, one owning row each: - prometheus -> PEN-2735, DISCLOSURE. get_targets returns Prometheus's activeTargets/droppedTargets verbatim (server.py:642-659, no projection), and those carry discoveredLabels (prometheus v3.2.1 api.go:999/:1023, populated :1145/:1184). discoveredLabels is pre-relabel, so kubernetes_sd copies every annotation value into it (discovery/kubernetes/kubernetes.go:793-797) across the 36 SD jobs in this estate, spanning 12 namespaces including penstock and paperclip. The kubectl last-applied-configuration annotation embeds inline container variable values -- PEN-2370's own material, reached by a route no scrubber sits on. - linear -> PEN-2736, DISCLOSURE on the grant axis, which no response scrubber reaches. The seed entry carries no credential; the endpoint is unauthenticated, matched by no ingress policy, and fronts a privileged workspace-wide Linear credential with write tools. Same family as PEN-2620 door #7. - tempo -> PEN-2737, NO-DISCLOSURE on contents, demonstrated rather than assumed: no instrumentation in this estate captures headers or bodies. But nothing enforces that, so the row tracks making it an invariant. Every link was read from committed manifests and vendor source. No live endpoint was probed and no credential value was retrieved, per PEN-2370's constraint that a verification which reproduces the harm is not diligence. Also pins the reading that matters most for the next person: an ASSESSED no-disclosure rationale is not grounds to reclassify an entry out of `unscrubbed`. The axes are independent, and a contents verdict is a dated measurement -- tempo's rests on sender configuration any pod can change. No `kind` and no URL changed, so the topology assertions are untouched. Refs PEN-2630, PEN-2735, PEN-2736, PEN-2737 Signed-off-by: Cto <cto@paperclip.blockcast.net>
ed7e315 to
7662ded
Compare
There was a problem hiding this comment.
Ally — Consolidated PR Review
Lenses: pr-review-toolkit (code, tests, comments, errors, types; degraded: skill unavailable) + gstack/review (degraded: nested runtime unavailable) + native-codex.
Reviewed head: 7662ded
Critical Issues (0)
Important Issues (0)
Suggestions (0)
Strengths
- The audit outcome preserves the transport/content distinction: all three direct endpoints remain
unscrubbed, including Tempo's dated no-disclosure assessment. - Each direct upstream now has a distinct owning follow-up ticket, while the existing structural assertions continue to validate the seeded topology.
- The changed file is documentation and tracking data only; the focused CI test lanes are running for this head.
Recommended Action
- No blocking changes requested.
There was a problem hiding this comment.
Ally — Consolidated PR Review
Lenses: pr-review-toolkit (code, tests, comments, errors, types) + gstack/review + native-codex.
Reviewed head: 44f9f87
Critical Issues (0)
Important Issues (0)
Suggestions (0)
Strengths
- The patch preserves the distinction between transport coverage and contents assessment.
- Each audited upstream now points to a dedicated follow-up ticket without changing the executable coverage assertions.
- The change is confined to audit documentation and tracking metadata; no runtime behavior or topology is modified.
Recommended Action
- No blocking changes requested.
Thinking Path
Linked Issues or Issue Description
prometheusdisclosure finding (new)lineardisclosure finding, grant axis (new)tempohardening: assessed clean but unenforced (new)k8s-rothrough the gateway, which is why that entry isgateway-scrubbed), security(mcp-gateway): scrub container env values from proxied MCP responses (PEN-2370) #1435 (the response scrubber itself).What Changed
prometheusrationale: "unassessed" → ASSESSED disclosure, ticket repointedPEN-2630→PEN-2735linearrationale: "unassessed" → ASSESSED disclosure on the grant axis, ticket repointedPEN-2630→PEN-2736temporationale: "unassessed" → ASSESSED no-disclosure on contents, transport still unscrubbed and unenforced, ticket repointedPEN-2630→PEN-2737SEED_COVERAGE: replaced "the audit is still open" with the outcome, and added the caveat that anASSESSED no-disclosurerationale is not grounds to reclassify an entry out ofunscrubbedNo
kindand no URL changed. The diff is rationale strings, ticket ids, and one comment.The findings, in brief
prometheus— PEN-2370's own material by a second route. PEN-2370 names the control: "after any remediation, go looking for the same material by another route." Chain, each link read from source at the deployed version:discovery/kubernetes/kubernetes.go:793-797— kubernetes SD copies every annotation value into__meta_kubernetes_<role>_annotation_<name>web/api/v1/api.go:999/:1023—discoveredLabelsis on bothTargetandDroppedTarget(populated:1145/:1184), and is pre-relabel, so this estate's narrowrelabel_configsdo not constrain it; dropped targets means deliberately-unscraped workloads still return their full SD label setprometheus-mcp-serverserver.py:642-659—get_targetsreturns both arrays verbatim, no projectionmonitoring/prometheus-configmap.yaml— 36 of 75 jobs usekubernetes_sd_configs, spanning 12 namespaces incl.penstockandpaperclipkubectl.kubernetes.io/last-applied-configurationembeds the applied spec including inline literal container variable values — the field class #1435 scrubs on thek8s-roroute, reached here on a route that scrubber never sees.linear— the grant axis, which no response scrubber reaches. The seed entry carries no credential (unlikegbrain, it mints nothing). The endpoint is unauthenticated, matched by no ingress policy, and fronts a workspace-wide Linear credential exposingcreate_issue,update_issue,add_comment,archive_project. Any pod acts as the Linear identity, unattributably. Same family as PEN-2620 door #7.tempo— clean, demonstrated not assumed.headersToSpanAttributes,capture_headers,CAPTURE_REQUEST_HEADERS,http.request.header.*andOTEL_INSTRUMENTATION_*are absent estate-wide;instrumentation-pghas noenhancedDatabaseReporting; there is no manualsetAttributein this repo; the tracer is unwired in-cluster. Residual: OTel defaulturl.fullincludes query strings.Verification
kindand no URL changed, so every topology assertion in this suite is untouched by construction.SEED_COVERAGEtable and checked it against the two assertions this suite makes on the fields I changed: all fourunscrubbedentries match/^(PEN|BLO)-\d+$/and carry a rationale over the 20-character floor. All 7 entries present, kinds unchanged.tsc --noEmiton the file is clean (only module-resolution errors forvitest/node:, which are absent from the sparse clone I worked in).Method — this matters as much as the result
Per PEN-2370's inherited constraints: no live endpoint was probed and no credential value was retrieved or quoted. Everything above comes from committed manifests (
Blockcast/onprem-k8s,Blockcast/paperclip) and from vendor source at the deployed versions. A verification that reproduces the harm is not diligence.Risks
Low risk to the build. The change is data and prose in a test file; no production code path, no schema, no manifest, no topology.
The real risk is a misreading, which the new doc comment is written to prevent: an
ASSESSED no-disclosurerationale could tempt someone to reclassifytempoout ofunscrubbed. That would be wrong — the axes are independent, nothing scrubs any of these three, and a contents verdict is a dated measurement. Tempo's rests entirely on sender-side configuration that any in-cluster pod can change by pushing spans directly to an unauthenticated OTLP port, which is precisely why PEN-2737 exists.Second risk, named honestly: the
prometheusfinding is filed on the mechanism, not on a confirmed captured secret. Whether a credential value is presently reachable needs some scraped workload using an inline literal rather than asecretKeyRef; in the manifests I read, secrets are consistentlysecretKeyRefor file mounts. I did not enumerate all twelve namespaces and deliberately did not probe to find out. Per criterion (b2) that argues for fixing it rather than closing it — a channel this broad cannot be declared safe by having checked part of it — but a reader should not take PEN-2735 as "a secret was found".Model Used
Claude Opus 4.5 (
claude-opus-4-5), extended thinking, running as the Paperclip CTO agent via Claude Code with tool use (Bash, file edits, GitHub + Paperclip MCP). Two subagents were dispatched for the manifest sweeps of the Prometheus scrape config and the Tempo/OTel instrumentation; their findings were re-verified against vendor source before being written up here.Checklist
SEED_COVERAGE,mcp-seed-scrub,PEN-2630, andscrub coverage seedacross all states; security(server): record the PEN-2630 (b1) contents audit for prometheus/tempo/linear #1551 is the only PR touching this file since security(server): enumerate scrub coverage for the shared agent MCP seed, and pin the per-agent override axis it cannot enumerate (PEN-2370) #1530, which is linked above along with fix(helm): route k8s-ro through scrubbing gateway (PEN-2429) #1544 and security(mcp-gateway): scrub container env values from proxied MCP responses (PEN-2370) #1435Fixes: #/Closes #/Refs #OR (b) described the issue in-PR following the relevant issue templateSEED_COVERAGEis the documentation for this table