Skip to content

FEAT: Save techniques (part 14) - #4066

Open
varunj-msft wants to merge 203 commits into
microsoft:mainfrom
varunj-msft:varunj-msft/13178-Save-Techniques
Open

varunj-msft wants to merge 203 commits into
microsoft:mainfrom
varunj-msft:varunj-msft/13178-Save-Techniques

Conversation

@varunj-msft

@varunj-msft varunj-msft commented Nov 8, 2026 •

Copy link
Copy Markdown
Contributor

Description

Part 14 of saving Registry entries across restarts. Stacked on part 13 (#4052); part 15 (#4067) builds on it. This PR's own changes: varunj-msft/PyRIT@varunj-msft/13178-Save-Converters-From-Registry...varunj-msft/13178-Save-Techniques

Design: 4.1 What gets saved, 4.3 What a recipe holds. Where every part fits: PR map.

This is one of the changes for saving Registry entries across restarts. It builds on #4052, which saves converters from the Registry. Until the earlier PRs merge, the diff here also shows their changes.

A technique made with New technique, or through POST /api/techniques, was gone after the backend restarted. It now saves by default and comes back at every start, like saved targets and converters.

  • POST /api/techniques takes "persist": true. A saved technique's name follows the saved-name rule (lowercase letters, digits and underscores, starting with a letter, up to 64 characters), or the request gets a 422. Its recipe is the create request without the name, plus who saved it.
  • A technique that uses a Temporary converter or adversarial target can't be saved, since those are gone after a restart (typed 400, /errors/not-saveable). A name another technique has, or a tag that matches a technique's name or another spelling of a tag in use, is a 409 before anything is written, and storage that can't be written is a 503.
  • Restore rebuilds a saved technique with the call the API uses, after the converters and targets it names, and keeps who saved it out of the attack's settings. Techniques the startup scripts register are marked From configuration.
  • A scan's launch script that registers a technique under a saved technique's name or one of its tags stops the scan, even when the script catches the refusal, so the saved technique can't run in its place.
  • GET /api/techniques gives each technique an origin: saved, configuration or temporary.
  • The technique editor saves by default. When a converter or adversarial target it uses is Temporary, or the backend refuses those exact settings, the button reads Create as Temporary and a warning says why. A taken name shows on the name field.
  • The Techniques table labels each technique Saved, From configuration or Temporary. The backend README and the GUI doc cover saving techniques.

What stays the same: a technique created without persist is Temporary, as before. Settings changed for one run in the Scanner (POST /api/techniques/{name}/edit) are never saved. Startup techniques work as before; they're only labeled From configuration.

Screenshots: New technique saves by default, the saved technique in the Techniques table, and a technique that uses a Temporary converter offered as Temporary with the reason.
techniques_1_new_technique_saves_by_default
techniques_2_saved_technique_row
techniques_3_temporary_converter_offers_temporary

Not covered:

…API input

External construction now rejects a parameter whose type includes Path unless the
calling service passes the name in allowed_path_params after making the value safe.
The converter service allows its upload parameters once they are stored, and the
target service allows the server-set upload folder and the GitHubCopilotTarget
working directory. The scorer-only check is removed, and the "Valid parameters"
list leaves out path parameters callers cannot set.
The target catalog now applies the path rule to required parameters too, so a
target that needs a disallowed path is left out instead of listed without the
field, matching the scorer catalog. allowed_path_params is typed frozenset[str]
so a bare string cannot turn the allow-list into a substring match.
The target catalog still lists a target whose required path parameter is its
server-set upload folder when the server has one, and leaves it out otherwise.
# Conflicts:
#	tests/unit/backend/test_converter_service.py
The runtime becomes ready even when some saved entries fail; the
failures stay in the runtime status. Each failed entry keeps its name in
its registry: looking it up, or taking the name, raises
SavedEntryUnavailableError, which the backend answers with 409, so
nothing else stands in for it. Administrators see the full message and
everyone else a fixed explanation of the reason. A folder that can't be
listed holds every unregistered name of its kind, and each entry it left
unbuilt is reported.

While a saved technique is held, a launch or estimate that picks
techniques by all, default or a tag is refused with 409 for scenarios
whose techniques come from the registry, since the broken technique's
tags may be unknown. Naming techniques still works; naming the held one
fails with its reason. Route catch-alls let the error through instead of
turning it into a 500.
A launch script that registers a name held for a saved entry that
couldn't be restored is refused, and the refusal is recorded even when
the script catches it, so the launch stops instead of running with the
script's entry in the saved one's place. A suite entry that fails on a
held entry, or on a broad technique selection, shows the reason without
the error's details.
The OpenAI SDK adds that variable's headers to every request, so a saved
OpenAI target would send whatever the server puts there, which can be a
credential. While it's set, saving an OpenAI target is refused and a
saved one isn't restored; the message names the variable, never its
value. Targets declare such variables in server_header_variables.
Saving converters and scorers follows the same rules as saving targets now: a type that only a scan's launch script added can't be saved, a class without cached metadata is checked the way restore checks it, only a taken name is reported as a conflict, a storage failure logs its short reason, and the owner is recorded only when the entry is saved.
Saving a technique follows the same rules as the other saved entries now: an attack type that only a scan's launch script added can't be saved, a name or tag clash while registering is a conflict, and the owner is recorded only when the technique is saved. A held technique name is refused when a technique is checked before saving too.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants