Skip to main content

muzzle-optimizer

A superred port of MUZZLE (arXiv:2602.09222, "Adaptive Agentic Red-Teaming of Web Agents Against Indirect Prompt Injection Attacks"), an adaptive indirect-prompt-injection (IPI) attacker for tool-using agents.

Given an agentic target and an adversarial goal, MuzzleOptimizer:

  1. observes one benign run and summarizes the victim's trajectory into a playbook;
  2. ranks the in-scope content-injection surfaces (vessels) by salience;
  3. probes a vessel by planting a placeholder and checking it surfaces in the victim's context;
  4. crafts a context-aware payload with an offline PAIR loop (a simulated victim conditioned on the real system prompt and the localized context);
  5. attacks with one real run, then refines from feedback: a missed delivery moves to the next vessel, an ineffective payload is re-refined by PAIR.

Success is decided by the SecurityClaim (RunEndEvent.evaluation.success), never by the optimizer. See ASSUMPTIONS.md for the faithfulness ledger and every deliberate deviation from the upstream github.com/gsiros/muzzle (SHA ed611c0).

Install

pip install -e ./optimizers/muzzle

Depends only on superred and PyYAML. The Chao et al. PAIR core is vendored under muzzle_optimizer/pair/ (no cross-module dependency).

Usage

from muzzle_optimizer import MuzzleOptimizer
from superred.core.controller import Controller, TargetFactory

controller = Controller(
    optimizer_factory=lambda: MuzzleOptimizer(),   # zero-arg; a fresh instance per task
    target_factory=TargetFactory(create=make_agent_target, concurrency=1),
    security_claim=ipi_claim,
    scope=root_scope,
    llm_config=attacker_cfg,     # the one fixed attacker model MUZZLE's roles share
    max_runs_per_task=12,        # see "Run budget" below
)
result = await controller.run()

The optimizer adapts entirely from initialize(...); it takes no required constructor arguments. Useful keyword knobs include max_attempts, the PAIR caps (pair_n_streams, pair_n_iterations), target_controllable_name (pin a vessel for ablations), and response_observable_names.

How it maps to the framework

MUZZLE component superred
Explorer (Docker/Zoo/vLLM-proxy/red-team browser agent) the controller's run loop + the trajectory + a direct ControllableInjection
BENIGN / PROBE / ACTUAL victim runs successive target.run() calls in the multi-run loop
vessel (web UI element) an in-scope content Controllable (PostCall: tool:<name> / read__* / opi_tool_observation), with PreCall fallback
curl assertion oracle RunEndEvent.evaluation.success (the SecurityClaim)
Summarizer / Grafter / Prompter / Judge (gpt-4o agents) helper classes over the single self.llm, each with its byte-identical prompt
PAIR (offline, bare victim LLM) PairBridge: offline PAIR with self.llm as the surrogate victim

The optimizer runs a three-phase state machine over the multi-run loop: OBSERVE (passthrough recon -> playbook -> ranked vessels) -> PROBE (placeholder delivery check per vessel; a miss advances the vessel and is not scored) -> ATTACK (inject the PAIR payload; success ends the task, a UI-attributed failure tries the next vessel, an instruction-attributed failure re-refines).

Scope behavior

  • Content vessels in scope: the intended IPI setting; rank, probe, attack.
  • PreCall-only: degrade to a user_prompt (preferred) or system_prompt fallback vessel (less indirect, deprioritized).
  • No injectable surface: one OBSERVE passthrough, then done (the passthrough baseline). Never crashes.
  • include_feedback=False: steers by the trajectory presence/PROBE checks only and never self-certifies success.

Run budget

OBSERVE is a pure recon run, so a single phase cannot attack. Allow at least ~4-5 runs per goal (max_runs_per_task) so OBSERVE + PROBE + ACTUAL can complete; the offline PAIR loop consumes only the optimizer's LLM cost budget, not target runs. BudgetExhaustedError stops the task cleanly.

Tests

pip install -e "./optimizers/muzzle[test]"
pytest optimizers/muzzle/tests -q
mypy --strict optimizers/muzzle/src
ruff check optimizers/muzzle

smoke/ holds env-gated live end-to-end checks against real agentic targets (agentdojo, inspect_agent); they need an LLM proxy (LITELLM_API_KEY / LITELLM_API_BASE).

Credits / upstream

This module ports the MUZZLE red-teaming method to superred and vendors the PAIR attacker core. Our integration code is MIT (see LICENSE); upstream components keep their original licenses (see NOTICE and LICENSES/).

  • MUZZLE — Syros et al., "MUZZLE: Adaptive Agentic Red-Teaming of Web Agents Against Indirect Prompt Injection Attacks", arXiv:2602.09222 (2026). Source: https://github.com/gsiros/muzzle (Apache-2.0). The five agent prompt YAMLs, the four injection templates, the judge payload-presence heuristic, and the OBSERVE/PROBE/ATTACK control logic derive from this repo. Deviations from upstream are logged in ASSUMPTIONS.md.
  • PAIR — Chao et al., "Jailbreaking Black Box Large Language Models in Twenty Queries" (2023). Source: https://github.com/patrickrchao/JailbreakingLLMs (MIT, Copyright (c) 2023 PAIR Team). Vendored under muzzle_optimizer/pair/.

Please cite both papers when reporting results produced with this module.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

superred_optimizer_muzzle-0.1.0.tar.gz (82.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

superred_optimizer_muzzle-0.1.0-py3-none-any.whl (67.2 kB view details)

Uploaded Python 3

File details

Details for the file superred_optimizer_muzzle-0.1.0.tar.gz.

File metadata

File hashes

Hashes for superred_optimizer_muzzle-0.1.0.tar.gz
Algorithm Hash digest
SHA256 2452ddfd97d9a82c0db8198e9c715daaca9b1e7a7af375edb3da61acf881b904
MD5 f3d3d08ff0e6d9c67edbde692758a70a
BLAKE2b-256 525aa3a49e60bc620b5b4902fee8821e239c03c2aed1cf13c4c5c382c689a177

See more details on using hashes here.

Provenance

The following attestation bundles were made for superred_optimizer_muzzle-0.1.0.tar.gz:

Publisher: release.yml on RoldSI/superred-modules

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file superred_optimizer_muzzle-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for superred_optimizer_muzzle-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 75c3e411449bb31f20ef5e77117cd6932f61bcc12aec0c931313654faf6b052c
MD5 eab55bad513fad8c657a4be6ccc2b23d
BLAKE2b-256 f23b1963f179081d6e49d7027c3db1b65aded93d586a74d8346faba2429b3e0e

See more details on using hashes here.

Provenance

The following attestation bundles were made for superred_optimizer_muzzle-0.1.0-py3-none-any.whl:

Publisher: release.yml on RoldSI/superred-modules

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page