Skip to content

v0.9.15

Latest

Choose a tag to compare

@github-actions github-actions released this 23 Jul 20:24
v0.9.15

What's new in v0.9.15

v0.9.15 is a security hardening release for the binary, remediating an application security audit. Its theme is that data with no business appearing in a finding no longer does: a secret embedded in a request URL is stripped at ingestion before it can reach a stored finding, the query API, the on-disk archive, or an acknowledgment signature. Alongside that, the daemon's report export runs the real quality gate instead of a hardcoded pass, the acknowledgment audit trail is gated by the same key as the writes, and verify-hash actually verifies the producing binary's provenance instead of only claiming to. Most of this is corrective and invisible at upgrade, but three behavior changes need a word, gathered under "Upgrade impact" below.

Secrets stripped from endpoints at ingestion

When a span carries no http.route, source_endpoint falls back to the raw request URL, which can hold an OAuth code, a reset token, or a session id in its query string. That value used to flow verbatim into stored findings, the /api/findings responses, the NDJSON archive, and the acknowledgment signature. It is now stripped of its query string, fragment, and userinfo at the ingestion boundary, the single point every ingest format passes through, so the secret never lands anywhere downstream. Route-template endpoints, the common case, are untouched.

A real quality gate on the report export

GET /api/export/report used to return quality_gate.passed = true unconditionally, so a CI consumer reading the daemon export saw a permanently green gate regardless of findings. It now evaluates the configured threshold rules over the live snapshot, the same way the batch pipeline does, so the exported gate reflects the real state.

Authenticated acknowledgment reads, and a key from the environment

GET /api/acks returns the acknowledgment audit trail, reviewer identities, reasons, and finding signatures. When [daemon.ack] api_key is set it is now gated by the same X-API-Key as the POST and DELETE acknowledgment endpoints, so reads no longer bypass the write credential. The key can also be sourced from the PERF_SENTINEL_ACK_API_KEY environment variable, which takes precedence over the config value, so it can come from a secret store rather than a committed file, the same convention as PERF_SENTINEL_EMAPS_TOKEN.

Verified provenance and a live cleartext warning

verify-hash documented a SLSA provenance check that it never ran, so it could print TRUSTED for a report whose producing binary was never verified. A new --verify-binary <path> runs gh attestation verify against the supplied binary and cross-checks the commit the report records, so a genuine build of a different version cannot pass as this report's. The TRUSTED label now requires that binary attestation to be verified whenever the report carries attestation metadata, instead of resting on the content hash and signature alone. In the same spirit, the Redfish scraper's cleartext-credential warning, previously dead code because a synthetic label was checked instead of the real chassis URIs, now fires when BMC credentials would travel over http://.

Upgrade impact

Three contracts change at upgrade. The endpoint redaction changes the acknowledgment signature of any finding whose endpoint carried a query string, fragment, or userinfo, so an existing acknowledgment on such an endpoint no longer matches and must be re-captured, route-template endpoints are unchanged, see docs/ACKNOWLEDGMENTS.md. A consumer that gates on verify-hash exit 0 for a report carrying attestation metadata now gets exit 2 (PARTIAL) unless it passes --verify-binary, reports without attestation metadata are unchanged. A read-only consumer of GET /api/acks on a daemon with [daemon.ack] api_key set must now send the X-API-Key header.

Why this is a patch and not a minor

The API and file shapes are unchanged, and the daemon's design is unchanged: it still carries no embedded identity model, so the audit's ingest-authentication and provenance findings are met by the documented reverse-proxy posture rather than by new binary behavior. What changed is corrective, closing secret leaks and a false trust signal, with three narrow and documented migration steps rather than a new feature surface.

Validation

The release was validated in the simulation lab against the v0.9.15 binary, recorded as PASS. The ten anti-pattern detectors all fired as expected, the smoke and batch scenarios matched, and a dedicated hardening scenario exercised the four security behaviors end to end, each proven to fail on v0.9.14 and pass on v0.9.15: the endpoint redaction stripping userinfo and query while preserving route templates, the environment-sourced acknowledgment key overriding the config, the export gate returning real evaluated rules, and an injected attestation capping the verify-hash result at PARTIAL. The full Rust suite passes green, clippy is clean at -D warnings on Rust 1.97.1, and the default and --no-default-features builds both pass.

Verifying this release

# Binary integrity via SLSA Build L3 attestation
gh attestation verify perf-sentinel-linux-amd64 \
  --repo robintra/perf-sentinel

# A periodic disclosure produced by this binary
perf-sentinel verify-hash --report perf-sentinel-report.json \
  --expected-identity "https://github.com/robintra/perf-sentinel/.github/workflows/release.yml@refs/tags/v0.9.15" \
  --expected-issuer "https://token.actions.githubusercontent.com"

gh CLI 2.49 or newer required for gh attestation verify.

Full Changelog: v0.9.14...v0.9.15