github robintra/perf-sentinel v0.5.18

latest releases: chart-v0.2.62, chart-v0.2.61, v0.8.13...
one month ago

What's new in v0.5.18

v0.5.18 closes a cross-format gap that surfaced in the simulation-lab CI/CD validation work: the SARIF emitter now exposes the canonical finding signature so SARIF-aware tools (GitHub Code Scanning, GitLab SAST, Sonar) can match findings against .perf-sentinel-acknowledgments.toml without parsing the JSON output separately. The signature appears in two places per result, properties.signature for parity with the existing ack metadata in properties and fingerprints["perfsentinel/v1"] for SARIF v2.1.0 native deduplication. Both fields hold the same value, pick whichever one matches the ingestion model of the tool consuming the SARIF.

The release also tightens the canonical signature against Trojan Source spoofing (CVE-2021-42574). compute_signature now strips Unicode BiDi-override and invisible-format characters from service and source_endpoint before constructing the signature, so a hostile span attribute like service = "alice<RLO>@evil.com" cannot fork ack matching from a visually identical legitimate entry. The same sanitizer was already applied to ack metadata at SARIF emission time in 0.5.17, this release pulls it down to the signature construction site so the entire matching chain (TOML file, JSON output, SARIF output) shares the canonical form.

Finally, the docs/ci-templates/ reference templates (GitLab CI, GitHub Actions, Jenkins) had their PERF_SENTINEL_VERSION pin bumped from 0.5.8 to 0.5.17 after the 0.5.17 tag was cut. This release matches the published binary version to the templates so a fresh curl https://raw.githubusercontent.com/.../docs/ci-templates/github-actions.yml no longer pulls a stale pin.

Added

  • SarifProperties.signature: Option<String> field on the SARIF result properties bag, populated from Finding.signature when non-empty. Skipped via serde(skip_serializing_if = "Option::is_none") on legacy baselines (pre-0.5.17 reports without the field).
  • SarifResult.fingerprints: Option<BTreeMap<&'static str, String>> field on the SARIF result, single-entry map keyed by "perfsentinel/v1", value is the canonical signature. SARIF v2.1.0 section 3.27.17 fingerprint, used by GitHub Code Scanning and GitLab SAST for deduplication across runs. BTreeMap over HashMap for stable JSON ordering, &'static str key over owned String to skip one allocation per finding.
  • Signature emission for acknowledged findings. When --show-acknowledged is set, each acked SARIF result carries the same properties.signature and fingerprints["perfsentinel/v1"] so a tool that round-trips the SARIF output back into the ack file can copy-paste the value directly.
  • docs/SARIF.md and docs/FR/SARIF-FR.md new dedicated reference for the SARIF format emitted by perf-sentinel: per-result fields, tool driver, schema URL, with cross-link to ACKNOWLEDGMENTS.md for the cross-format ack matching workflow.
  • "SARIF integration" section in docs/ACKNOWLEDGMENTS.md and docs/FR/ACKNOWLEDGMENTS-FR.md explaining the two emission sites and when to pick properties.signature vs fingerprints["perfsentinel/v1"] based on the consumer.
  • 5 new tests: 4 unit tests in crates/sentinel-core/src/report/sarif.rs (signature in properties, signature in fingerprints, both omitted when empty, acked finding carries both), 1 e2e test in crates/sentinel-cli/tests/e2e.rs (cli_signature_consistent_across_json_and_sarif) that runs analyze twice on the same fixture in JSON and SARIF mode and asserts JSON.findings[i].signature == SARIF.results[i].properties.signature == SARIF.results[i].fingerprints["perfsentinel/v1"]. The e2e test guards against future format drift between the two emit paths.
  • 1 unit test in crates/sentinel-core/src/acknowledgments.rs (compute_signature_strips_bidi_and_invisible_from_service_and_endpoint) verifying that service = "alice\u{202E}@evil.com" and service = "alice@evil.com" produce the same canonical signature so a hostile span attribute cannot fork ack matching.

Changed

  • compute_signature strips BiDi and invisible-format characters from service and source_endpoint before formatting the canonical signature. Reuses the existing strip_bidi_and_invisible helper from the SARIF emitter, now exposed as pub(crate) so the discipline stays consistent across the matching chain. The hash component (template SHA-256 prefix) is unchanged. In practice no production service has BiDi characters in its name, the change is defense in depth.
  • acknowledged_finding_to_result mutates SarifProperties in place instead of rebuilding the struct after the call to finding_to_result. Saves one allocation per acknowledged finding and removes the duplicate signature-capture guard that would have drifted as new fields are added to SarifProperties over time.
  • docs/ci-templates/ PERF_SENTINEL_VERSION pin bumped from 0.5.8 to 0.5.17 across gitlab-ci.yml, github-actions.yml, github-actions-baseline.yml, and jenkinsfile.groovy. Already merged in commit e75166b after the 0.5.17 tag was cut, materialized in this release so users curling the templates pull a recent binary by default.

Behavior

  • Default behavior preserved. Active findings continue to render the same way in JSON, HTML, and terminal output. The new SARIF fields are additive and skipped when the source signature is empty, so existing SARIF consumers parse the output unchanged. The signature value itself is identical to 0.5.17 for any finding whose service and source_endpoint are pure ASCII (the overwhelming majority of production setups). Acks created in 0.5.17 against ASCII-named services continue to match in 0.5.18 byte-for-byte.
  • Edge case for non-ASCII service names with BiDi characters. If a .perf-sentinel-acknowledgments.toml entry was created in 0.5.17 against a service whose name carried BiDi or zero-width format characters (extremely rare), the entry will not match in 0.5.18 because the new signature strips those characters. Re-run analyze --format json | jq '.findings[].signature' to capture the new signature and update the TOML.

Documentation

  • docs/SARIF.md and docs/FR/SARIF-FR.md document the per-result fields emitted by perf-sentinel, including the new properties.signature and fingerprints["perfsentinel/v1"]. Reference for downstream tooling that consumes the SARIF output.
  • docs/ACKNOWLEDGMENTS.md and docs/FR/ACKNOWLEDGMENTS-FR.md gain a "SARIF integration" section explaining the two emission sites and the cross-format matching workflow. The doc clarifies that the signature value is identical between JSON and SARIF, so tools can pick whichever surface fits their ingestion path.
  • README.md and README-FR.md simplified the global-integration diagram to drop the dark-variant <picture> block in favor of a single ![](...) rendering. Cosmetic, no scope change.

Install

Prebuilt binaries (Linux amd64 / arm64, macOS arm64, Windows amd64):

curl -LO https://github.com/robintra/perf-sentinel/releases/download/v0.5.18/perf-sentinel-linux-amd64
chmod +x perf-sentinel-linux-amd64
sudo mv perf-sentinel-linux-amd64 /usr/local/bin/perf-sentinel

Linux binaries are statically linked against musl and run on any distribution (Alpine, Debian, RHEL, Ubuntu any version) regardless of glibc version, and inside FROM scratch images.

From crates.io:

cargo install perf-sentinel --version 0.5.18

Docker:

docker run --rm -p 4317:4317 -p 4318:4318 \
  ghcr.io/robintra/perf-sentinel:0.5.18 watch --listen-address 0.0.0.0

Also available on Docker Hub: robintrassard/perf-sentinel:0.5.18.

Helm (chart 0.2.21 ships 0.5.18 as its appVersion default):

helm install perf-sentinel oci://ghcr.io/robintra/charts/perf-sentinel \
  --version 0.2.21 \
  --namespace observability --create-namespace

Verify the binary against SHA256SUMS.txt:

curl -LO https://github.com/robintra/perf-sentinel/releases/download/v0.5.18/SHA256SUMS.txt
sha256sum -c SHA256SUMS.txt --ignore-missing

Full diff: v0.5.17...v0.5.18

Don't miss a new perf-sentinel release

NewReleases is sending notifications on new releases.