Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

BUG: multimodal router drops media metadata when forwarding seeds and responses

Aperta
#3,346 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 2 giorni

@Shizoqua ci sta già lavorando.

Dal 19/10/2026.

  • #3357 di @Shizoqua — aperta

Valutazione

Difficoltà
3/5
Tempo stimato
1-2 giorni
Idoneità per principianti
35/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Ferma
Stack tecnologico
python

Direzione di ricerca

Start with pyrit/executor/attack/component/modality_router.py, especially _ModalityFeedbackRouter._build_multimodal_message(), and inspect how it creates media pieces from converted values. Read the message formatting helper and existing modality router tests, then run the focused tests. Done means all three forwarding paths retain the agreed media metadata, transient metadata is handled as specified, and tests confirm source metadata is unchanged and copied metadata is independently owned.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Bug: triage
Describe the bug

_ModalityFeedbackRouter._build_multimodal_message() creates fresh media pieces from each source piece's converted_value and converted_value_data_type, but discards its prompt_metadata entirely.

This affects media forwarded from a seed to the adversarial chat, from an objective response to the adversarial chat, and from an objective response into the next objective request. For example, a media piece's context_description is lost. format_message_piece_for_context() reads this metadata when formatting non-text content, so the copied piece produces only a generic modality placeholder instead of retaining its description.

Related: #3301 and #3302 concern fill_adversarial_placeholders(). This is a separate follow-up for the shared multimodal builder; that builder is unchanged by #3302. The router was introduced in #1377.

The converted media payload is already forwarded correctly. This issue is not asking to change that behavior or make the builder preserve the previous turn's original/converted lineage wholesale.

Steps/Code to Reproduce

Run in a PyRIT environment. No files, providers, credentials, or database initialization are needed.

from unittest.mock import MagicMock

from pyrit.executor.attack.component.modality_router import _ModalityFeedbackRouter
from pyrit.message_normalizer._helpers import format_message_piece_for_context
from pyrit.models import Message, MessagePiece
from pyrit.prompt_target import PromptTarget
from pyrit.prompt_target.common.target_capabilities import TargetCapabilities
from pyrit.prompt_target.common.target_configuration import TargetConfiguration


def target():
    mocked = MagicMock(spec=PromptTarget)
    mocked.configuration = TargetConfiguration(
        capabilities=TargetCapabilities(
            input_modalities=frozenset({
                frozenset({"text"}),
                frozenset({"text", "image_path"}),
            })
        )
    )
    return mocked


router = _ModalityFeedbackRouter(
    adversarial_chat=target(), objective_target=target()
)
media = MessagePiece(
    role="assistant",
    original_value="source.png",
    original_value_data_type="image_path",
    converted_value="resized.png",
    converted_value_data_type="image_path",
    prompt_metadata={"context_description": "A blue square"},
)
response = media.to_message()
seed = Message(message_pieces=[
    MessagePiece.adversarial_placeholder(),
    media.model_copy(update={"role": "user"}),
])

print("source:", format_message_piece_for_context(piece=media))
forwarded_messages = {
    "adversarial response": router.build_adversarial_input_message(
        text="feedback", last_response=response
    ),
    "adversarial seed": router.build_adversarial_input_message(
        text="feedback", last_response=None, seed_message=seed
    ),
    "objective response": router.build_objective_input_message(
        text="edit", last_response=response, turn_index=1
    ),
}
for direction, message in forwarded_messages.items():
    copied = message.get_piece(1)
    print(direction, copied.converted_value, copied.prompt_metadata,
          format_message_piece_for_context(piece=copied))
Expected Results

Media-scoped metadata that is still meaningful for the forwarded payload, such as context_description, survives forwarding. The copied media still points to resized.png, and formatting it retains [Image_path - A blue square].

Define the metadata-copying contract explicitly rather than blindly carrying previous-request or response-only state into a fresh request. Preserve independent ownership of mutable metadata and fresh message-piece/conversation IDs.

Add regression coverage for seed-to-adversarial forwarding and response forwarding in both directions, including source immutability and the treatment of transient metadata.

Actual Results
source: [Image_path - A blue square]
adversarial response resized.png {} [Image_path]
adversarial seed resized.png {} [Image_path]
objective response resized.png {} [Image_path]

The converted value survives, but the media copy's metadata is empty in all three paths. The source piece's metadata is unchanged.

Screenshots

N/A. This is an SDK/message-construction issue.

Versions
  • OS: Windows 11.
  • Browser: N/A.
  • Python: 3.14.4.
  • PyRIT: 1.2.0.dev0, editable checkout at 5343d3075e5b0a0abc91ee90413d6833e4e0ab26 (PR #3302). The affected builder is unchanged from its base f4fb86808c41210a164b2c8983c10919c051e7a1.
  • Reproduced offline through all three public routing paths.

pyrit.show_versions() output, with the local executable path omitted:

System:
    python: 3.14.4 (main, Apr 14 2026, 14:30:57) [MSC v.1944 64 bit (AMD64)]
   machine: Windows-11-10.0.26300-SP0

Python dependencies:
        pyrit: 1.2.0.dev0
       Cython: None
        numpy: 2.4.6
       openai: 2.54.0
    packaging: 25.0
          pip: None
        scipy: 1.17.1
   setuptools: 84.0.0
      sqlite3: None
        torch: None
 transformers: 5.19.0
Lingua principale
Python
Stelle
4.6k
Fork
962
Merge medio
2g 16h
PR unite (30g)
354

Preparare l'ambiente

Apri in Codespaces

Avvia il container di sviluppo del progetto nel browser, con il tuo account GitHub.

  • Nessun Dockerfile né file Docker Compose
  • Ha un modello di pull request
  • Nessuna guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di microsoft/PyRIT

Tutte le issue di microsoft/PyRIT

Issue simili

Altre issue su Python

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.