fix: enforce entropy limits on quoted candidates and anchor provenance to the fetched diff - #81
Merged
Merged
Conversation
…e to the fetched diff detect-secrets' ad-hoc scan_line enables eager search, whose fallback returns unquoted charset runs without applying the entropy limit. secret_taint accepted those runs whenever they sat in quotes or Markdown backticks, so ordinary public paths such as `packages/rboto-sns/` (entropy 3.68, limit 4.5) and `crates/rboto-core/` (3.20) became redaction candidates. Redaction then rewrote `+++ ` headers in the model-visible diff, and cc_loop read that redacted copy back for provenance, so a correct file/line anchor was rejected as outside every hunk while every later mention of the path was rejected as a leaked secret. The entropy detectors now run outside scan_line: every quote- or backtick-enclosed charset run is checked against the plugin's own entropy calculation and configured limit. Scanning every run also closes a gap where a low-entropy quoted string on the same line suppressed the eager pass and hid a backticked secret. Pattern and keyword detectors are unchanged. cc_loop reads diff.patch and changed_files.json before redaction, so the verifier's hunk map is derived from the diff as fetched. The model-visible copy is still redacted and its line numbering is identical.
This branch was successfully deployed
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.
Enforce entropy limits on quoted secret candidates; anchor provenance to the fetched diff
Fixes the three post-schema rejections in
https://github.com/svozza/aceiro-redteam/actions/runs/35323035751 (Aceiro
c7559e2, public rboto fixture). Submission 1 (group_note) was a genuinemodel error and stays rejected; a regression pins that.
Root cause
secret_taint.detect_candidatesscanned every line withdetect_secrets.core.scan.scan_line(detect-secrets 1.5.0). That ad-hoc APIenables eager search. When the quoted pass finds nothing, the high-entropy
plugins return every unquoted charset run without applying the entropy
limit; the library leaves the limit to the ad-hoc caller so it can print
"why" a string was missed. Aceiro then required the run to be enclosed in
',"or a Markdown backtick, but never reapplied the limit.Result on the fixture: eight ordinary public paths became redaction
candidates, e.g.
packages/rboto-sns/(entropy 3.68, limit 4.5) andcrates/rboto-core/(3.20). Two consequences:+++ b/packages/rboto-sns/...headers into+++ b/<SECRET_4:...>python/rboto_sns/exceptions.py, andcc_loop.runread that redacted
diff.patchback for provenance. 18 changed filesvanished from the verifier's hunk map while
changed_files.jsonand thecheckout kept the real names, so the correct anchor (
exceptions.py:49)was rejected as "not inside any diff hunk".
crates/rboto-core/src/lib.rs)tripped "content reproduces a redacted input candidate" and exhausted the
submission budget.
A second latent gap fell out of the same mechanism: the eager pass only runs
when the quoted pass is empty, so a low-entropy
"..."string on the sameline suppressed detection of a genuine backticked secret.
Change
secret_taint.py: the two entropy plugins are instantiated directly withthe existing limits (4.5 base64, 3.0 hex) and no longer go through
scan_line. Every quote- or backtick-enclosed charset run on a line ischecked with the plugin's own
calculate_shannon_entropy(so the hexdetector's all-digit penalty still applies) against
entropy_limit. Thepattern and keyword detectors still run through
scan_lineunchanged.cc_loop.py:diff.patchandchanged_files.jsonare read beforeredact_review_inputs, so the verifier's hunk map is derived from the diffas fetched. The model-visible copy is still redacted; a test asserts its
line numbering is identical to the fetched diff, so annotated numbers and
verifier anchors agree.
docs/testing.md: one sentence describing the redaction boundary.No dependency upgrades, no threshold changes, no path or identifier
allowlists.
Security properties preserved
the quarantined head; taints still gate the verifier, transcript, and
stream capture.
JWT, ...) are untouched and covered by a mixed-quoting test.
still detected; unquoted high-entropy runs are still ignored as before.
mixed-quoting case, where it is a superset.
+++headers. A file whose real path contains agenuine secret-like token remains unreportable (the finding's
pathwouldreproduce the taint), which is the fail-closed behaviour that existed
before.
Regression coverage
tests/test_secret_taint.py::TestEntropyDetectors", and';redact_review_inputsleaves ordinary paths and a real diff header alone.tests/test_cc_loop.py::TestRunFailureModes::test_provenance_is_anchored_to_the_diff_as_fetched+++header does not rename the file in the verifier'shunk map; the model prompt has no plaintext; annotated line numbers of the
redacted copy equal the fetched diff.
tests/test_verify_adversarial.pygroup_noteremains an unsupported finding field;accepts a summary naming it;
reproduction is rejected.
Existing cases still cover forged paths, path traversal, out-of-hunk lines,
deleted-file lines, and exact secret reproduction.
Every new test was run against the pre-fix sources and failed there
(6 failures in
test_secret_taint/test_cc_loop, 1 in the adversarialcorpus).
Validation
Fixture replay (
/tmp/rboto-benchmark-full-work/session/context, read-only):before, 8 candidates and 18 changed files missing from the hunk map after
redaction; after, 0 candidates and 0 missing,
exceptions.py:49valid.Not included: prompt/model changes and further paid benchmark runs.