feat(signature): bootstrap the TOFU baseline from Rekor + detect registry↔log divergence (JEF-266)#142
Merged
thejefflarson merged 2 commits intoJul 1, 2026
Conversation
…stry↔log divergence (JEF-266) Implements ADR-0020 §4 (the transparency-log element). Two capabilities over the public Rekor log, behind an opt-in lane that is OFF by default (zero-egress preserved): 1. History bootstrap — query Rekor for a repo/identity's prior signing entries and seed/strengthen the JEF-263 per-repo baseline from the public history, so a fresh protector inherits real provenance instead of pure local TOFU. A Rekor-corroborated baseline is marked stronger than a local-only one (signing_baseline_strength) and the JEF-262 inventory renders "log-corroborated" vs "local only". 2. Divergence detection — signature-in-Rekor but registry serves unsigned/different (or the reverse) => a "registry↔log divergence" drift finding through JEF-264's regression channel. Lane gating: PROTECTOR_REKOR_ENABLE (off => lane never constructed, no query leaves, inventory/baseline/drift all work as before); PROTECTOR_REKOR_URL for a self-hosted mirror; bounded by timeout + cache-TTL + max-response-bytes. Only image identifiers leak to the public log operator (already-public); the security graph/evidence never leave. Sanctioned-egress carve-out per the ADR-0015 amendment + ADR-0020 §4. sigstore-rs Rekor: called Rekor's REST search API directly (index/retrieve + log/entries) via a bounded reqwest client rather than the crate client. Tests: rekor client + history-seed + no-history fallback + divergence both directions + unreachable-degrade + query-cache. cargo fmt/build/clippy --all-targets/test all green (469 lib + 9 dashboard_guards + file-size guard). Closes JEF-266 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VtjoJttCvBY4dzCoE4f9vP
…o unbounded buffer) Security review (Medium): the max_response_bytes cap was checked AFTER resp.text() had already buffered the whole body, so a hostile/compromised (but TLS-verified) log endpoint could stream a multi-GB body within the timeout and OOM the engine — a DoS of the security monitor. Replace resp.text() with a chunked accumulate that bails the instant the running size would exceed the cap; memory now stays bounded by max_response_bytes. An outer timeout preserves the original total-read-time bound. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VtjoJttCvBY4dzCoE4f9vP
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements ADR-0020 §4 (the transparency-log element). Two capabilities over the public Rekor log, behind an opt-in lane that is OFF by default (zero-egress preserved).
What
(Keyless cosign verify already consults Rekor for the inclusion proof — this is the history/divergence extension on top.)
Egress posture
PROTECTOR_REKOR_ENABLEgates the whole lane — off by default: unset ⇒ the lane is never constructed, no query leaves, and inventory/baseline/drift all work exactly as before (full zero-egress).PROTECTOR_REKOR_URLfor a self-hosted mirror; bounded by timeout + cache-TTL + max-response-bytes.sigstore-rs feasibility
Called Rekor's REST search API directly (
/api/v1/index/retrieve+/api/v1/log/entries) via a boundedreqwestclient rather than the crate's Rekor client.Gates
cargo fmt/build/clippy --all-targets(warns=errors) /testall green — 469 lib + 9 dashboard_guards + file-size guard. All files under the 1000-line cap.Closes JEF-266
🤖 Generated with Claude Code