[FEATURE/BUGS]: Add Ares case confidence score & guard attack-file reads against missing files & Conduct OPA policy bypasses to generate adversarial test cases - #27
Merged
Conversation
Signed-off-by: Hailun Ding <hailun.ding@ibm.com>
Signed-off-by: Hailun Ding <hailun.ding@ibm.com>
dhl123
marked this pull request as ready for review
July 20, 2026 13:24
dhl123
marked this pull request as draft
July 21, 2026 21:12
Signed-off-by: Hailun Ding <hailun.ding@ibm.com>
dhl123
marked this pull request as ready for review
July 22, 2026 19:02
Signed-off-by: Hailun Ding <hailun.ding@ibm.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.
Summary
This PR supports generating malicious cases to bypass policy, adds confidence score for Ares generated test cases, and adds guard for attack-file reads against missing files
Closes: #24 #25 #26
Changes
New feature: policy-bypass test-case generation
A new pipeline that finds where the policy diverges from the guidance and generates additional adversarial cases for each divergence.
src/smith/policy_agent/policy_analysis/bypass/—analyze_bypass.py(detect_bypass_vectors),synthesize_cases.py(synthesize_bypass_cases),schema.py(BypassVector/BypassReport).cli.py: newgenerate_bypass_cases()function and--flag bypass_case_generation(detect → synthesize → convert), guarded against a missing/empty policy.convert_test_case.py: newconvert_bypass_case()(only) routes bypass cases intodisallow/orallow/with abypass_test_caseprefix..env_template: new varsBYPASS_CASE_FILE,BYPASS_REPORT_DIR.detect_bypass_vectorspreviously wrote a silent empty report whenever the model returned malformed JSON, indistinguishable from "no bypasses found." It now retries the model call up toMAX_BYPASS_PARSE_ATTEMPTS = 3if the returned result is not JSON (empty json is acceptable). Only after 3 failed attempts it stops, reports the failure to the user, and returns an empty report.test_generation.md: rewritten to branch up front: ask the user which cases they want, they can choose general test cases (legitimate allow, disallow, ares, promptfoo), or/and bypass test cases.Confidence score of ARES in test validation
ARES cases now inherit their parent test case's confidence score, verdict, and predicted label in the evaluation report instead of showing a blank confidence. An ARES case is a jailbreak-transformed variant of a parent
disallowcase, so it carries the parent'sValidationResult(matched by the shareduser_input) rather than being independently re-validated.Guard attack-file reads against missing files
translate_caseincli.pyalready passes None for any attack file whose tool wasn't specified inATTACK_TOOLS, andmerge_with_ares / merge_with_promptfooskip merging when the path isNone. This PR adds a second layer:merge_with_aresandmerge_with_promptfoonow also verify the file actually exists on disk before reading it, so a missing or unsaved attack file is skipped gracefully instead of crashing withFileNotFoundError.The same applies in
classify_guidance.py: even though the call site already checks whether promptfoo is in the attack settings,classify_promptfoo_casesnow double-checks the file's existence before opening it.This protects against cases where
ATTACK_TOOLSdiffers between the generation and evaluation runs, or where an attack file was expected but never written.Other refinements
cross_validate.py: For bypass and promptfoo cases, any audit verdict other than keep is collapsed to remove (rather than relabeled), with a marker appended to the reason. A failed adversarial probe is dropped instead of polluting the ordinary case set since their intentions are malicious.extract_tool_args.py: skip cases that already carry an arguments block (already translated). This makes test_case_translation re-runnable and avoids re-translating the entire corpus when only newly-added (bypass) cases need translation (the previous behavior re-invoked translation on every case, which is inefficient and slow).Checks
make cipasses (lint, Rego lint, license headers, build smoke)make testpasses (policy scorecard — needed if policy behavior changed)CHANGELOG.mdupdated under## [Unreleased](if user-facing)git commit -s)