MAINT: Standardize garak.encoding defaults and fix atomic-attack name collisions#2190
Open
varunj-msft wants to merge 2 commits into
Open
Conversation
… collisions Re-migrated onto current main (post technique rename microsoft#2153, technique organization microsoft#2155, PromptConverter->Converter microsoft#2161, seed-group rename microsoft#2165). garak.encoding was already seam/Technique-migrated on main; this layers the remaining #8380 standardization on top. Add an EncodingTechnique.DEFAULT aggregate (curated 13-of-17-scheme spread across base-N, byte-encoding, cipher, and symbolic families) with a get_aggregate_tags() override, and make it the default technique (was the exhaustive ALL). The niche/ lossy schemes (braille, ecoji, zalgo, ascii_smuggler) stay ALL-only. Follows the hand-written enum DEFAULT pattern used by scam/web_injection (not the factory default_technique_names path, which applies only to the core catalog). Fix atomic-attack name collisions: previously every converter variant and decode config shared atomic_attack_name=encoding_name, so base64's variants collided and their result buckets (keyed by atomic_attack_name) collapsed. Each variant now gets a unique variant_slug -> atomic_attack_name=f"{variant_slug}_{config_suffix}", with display_group=encoding_name so variants still group per encoding in output. Trim near-duplicate base64 variants (standard_b64encode is byte-identical to the default; b2a_base64 only appends a newline). Bump VERSION 1->2. Make the default run meatier per Rich's microsoft#2058 asks (06-20 'target of 10-20 minutes ... may finish too quickly'; 07-08 'change the dataset size a bit and adding more defaults'): raise per-dataset max_dataset_size 3->10 and expand DEFAULT from 8 to 13 schemes. ALL remains the exhaustive ceiling (adds the 4 niche/lossy schemes).
rlundeen2
approved these changes
Jul 14, 2026
rlundeen2
left a comment
Contributor
There was a problem hiding this comment.
Looks great! Only nit comments
rlundeen2
reviewed
Jul 14, 2026
| display_group=encoding_name, | ||
| attack_technique=AttackTechnique(attack=attack), | ||
| seed_groups=seed_groups, | ||
| memory_labels=self._memory_labels, |
Contributor
There was a problem hiding this comment.
Rich agrees with this comment but it is copilot generated:
Nit / convention: this reads self._memory_labels (and the method also uses self._objective_target / self._scenario_techniques), but the scenarios guideline is to read runtime inputs from the immutable context snapshot passed into _build_atomic_attacks_async. It's functionally fine here since state is fully resolved by the time this runs, but context.memory_labels is right there — threading context down into _get_converter_attacks/_get_prompt_attacks would match the documented "read from context, not self._*" convention. Non-blocking.
Thread the ScenarioContext into _get_converter_attacks/_get_prompt_attacks rather than reading self._scenario_techniques / self._objective_target / self._memory_labels. Atomic-attack builders should read resolved runtime state from the context per the scenario convention. Behavioral no-op; tests updated to build the context via _build_scenario_context.
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.
Description
Curates the
garak.encodingscenario's default run and fixes atomic-attack name collisions. The largest change is to the defaults: the previous default finished too quickly to be a meaningful scan, so this widens the default scheme set and dataset size to land the default run inside a ~10–20 minute window.What changed
DEFAULTaggregate and made it the default technique (default_techniqueALL→DEFAULT). Previously the default wasALLat a tiny dataset size, so the default run was effectively unscoped.DEFAULTnow expands to 13 schemes spanning encoding families so the default scan is a meaningful spread:ALL-only: Braille, Ecoji, Zalgo, AsciiSmuggler.max_dataset_size3 → 10 for both default datasets (garak_slur_terms_en,garak_web_html_js).ascii85_a85/ascii85_b85) instead of colliding on the scheme name, so results/display groups no longer overwrite each other.Scale (verified by dry-init).
DEFAULT= 76 atomic attacks (incl. the baseline) × 20 objectives (size-10 × 2 datasets) = 1,520 target requests.ALL= 96 atomic attacks × 20 = 1,920 requests.Wall-clock (live measurement). Measured on the shipped
DEFAULTrun againstgpt-4o(Azuregpt-4o-unsafe, Entra ID); the objective scorer is the localDecodingScorer(no extra LLM calls):max_concurrencyDEFAULT(default concurrency = 4)DEFAULT(concurrency 12, scale probe)(1,520 requests; only 9/1,520 returned empty 204s and 0 rate-limit 429s at concurrency 4, so the numbers reflect near-clean round-trip throughput.) A real
pyrit_scan garak.encoding --target …run usesmax_concurrency=4by default (the CLI has no explicit default; the scenario applies 4 when--max-concurrencyis omitted), so 10.8 min is the user-facing number — inside the 10–20 min target window. The size-10 / 13-scheme curation moved the default from "finishes too quickly" into the target window; if a longer run is desired, the remaining levers are a furthermax_dataset_sizebump or moving more schemes intoDEFAULT.Tests and Documentation
tests/unit/scenario/garak/test_encoding.py— 30 tests, all passing. Covers: 17 total scheme names;DEFAULTis the default technique andDEFAULTexcludes the 4ALL-only schemes; Base64 trimmed to the two distinct variants (default + url-safe); atomic-attack name uniqueness per converter variant (collision fix); size-10 default dataset config. (The 76 / 96 atomic-attack counts above are from a dry-init of the scenario, not a hard-coded test assertion.)doc/scanner/garak.py+doc/scanner/garak.ipynbupdated for the new default. Synced with jupytext.ruff check,ruff format --check,ty,pytest tests/unit/scenario/garak/test_encoding.py.Note: MorseCode / NATO are lossy for XSS-style payloads in the
garak_web_html_jsdataset — this is a pre-existing default kept as-is; useful for the slur dataset. Flag if these should be scoped out ofDEFAULT.