fix(detectors): guard MarkdownExfilContent against missing terms note#1935
Open
anxkhn wants to merge 1 commit into
Open
fix(detectors): guard MarkdownExfilContent against missing terms note#1935anxkhn wants to merge 1 commit into
anxkhn wants to merge 1 commit into
Conversation
MarkdownExfilContent.detect read attempt.notes["terms"] with a direct
subscript. probes.web_injection.ColabAIDataLeakage wires this detector as
its primary_detector but defines no _attempt_prestore_hook, so the note is
never populated and Attempt.notes defaults to an empty dict. Any target
reply matching the markdown-image regex therefore aborted the detector run
with KeyError('terms'), which is exactly the output the probe elicits.
Read the note with .get("terms", []), matching the optional-note handling
in TriggerListDetector, so an absent value is treated as no expected terms
and the exfiltrated content still scores as a leak. Behaviour is unchanged
when the note is present.
Add a regression test exercising the detector with the terms note absent;
it raised KeyError before this change.
Co-authored-by: Claude <noreply@anthropic.com>
Signed-off-by: Anas Khan <83116240+anxkhn@users.noreply.github.com>
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.
MarkdownExfilContent.detectreads the expected-terms note with a directsubscript when it scores a markdown-image match:
The active default probe
probes.web_injection.ColabAIDataLeakage(
active = True,primary_detector = "web_injection.MarkdownExfilContent") wiresthis detector but, unlike its siblings
MarkdownImageExfilandPlaygroundMarkdownExfil, defines no_attempt_prestore_hook. The baseProbe._attempt_prestore_hookis a no-op andAttempt.notesdefaults to an emptydict, so
notes["terms"]is never populated for this probe. Its template instructsthe target to emit a URL like
.../logo.png?colab=<data>, which matches_MARKDOWN_IMG_REGEX. So on exactly the output the probe is designed to elicit,detect()raisesKeyError('terms'). The detector is invoked in the harness withno surrounding try/except, so the error aborts the detector pass for that probe run.
Reproduction (in a configured venv):
The fix
Read the note with
.get("terms", []), so an absent value is treated as noexpected terms:
With no expected terms the Jaccard overlap is
0, soscore = 1 - 0/|exfil| = 1.0and the exfiltrated content still scores as a leak,which is the correct outcome for this detector. Behaviour is byte-for-byte
unchanged when the note is present. The
.get-with-default idiom mirrors theoptional-note handling that
TriggerListDetectoralready uses indetectors/base.pyfor its own note. Scope is the detector body only; no baseclasses and no
attempttouched, and no new dependencies.Tests
Added a regression test in the existing detector test file
tests/detectors/test_detectors_web_injection.py:test_web_injection_content_missing_terms_note- loads the realMarkdownExfilContentplugin, builds anAttemptwhose output is aColabAIDataLeakage-style exfiltration markdown image, asserts"terms"isabsent from
notes(so the test genuinely exercises the unset-note state), thenasserts
detect()scores the exfiltration above the threshold instead of raising.On
main(before the fix) this test fails withKeyError('terms')atgarak/detectors/web_injection.py; after the fix it passes. It reuses the module'sexisting
SCORE_THRESHOLDand assertion style.Verification
python -m pytest tests/detectors/test_detectors_web_injection.py -q-> 5 passed...::test_web_injection_content_missing_terms_note) -> passedtest kept) makes the new test fail with
KeyError: 'terms'; restoring the fixmakes it pass. The test discriminates and is not a tautology.
python -m black --check garak/detectors/web_injection.py tests/detectors/test_detectors_web_injection.py-> cleanMarkdownExfilContent.detecton aColabAIDataLeakage-styleoutput with empty notes scores a hit (no
KeyError); withnotes["terms"]present the score is identical, so present-note behaviour is preserved.
Not a duplicate
garak/detectors/web_injection.pyor fixes thenotes["terms"]subscript (searched open+all PRs forMarkdownExfilContent,ColabAIDataLeakage,web_injection terms).web_injection, and it istest-only: it adds
tests/detectors/test_detectors_dan.py,tests/probes/test_probes_promptinject.py, andtests/probes/test_probes_web_injection.py. It does not touch the detectorsource and does not fix this crash, so there is no overlap or file collision (it
adds a probe test; this PR edits the detector source and the detector test
file).
NIM generator) are merged and unrelated.
KeyError/ColabAIDataLeakagecrash.AI assistance disclosure
This change was developed with AI assistance. I (the submitter) reviewed every
changed line, understand the bug and the fix end-to-end, and ran the tests above
locally. Attribution is in the commit trailer (
Co-authored-by: Claude), and thecommit is DCO signed-off.