Skip to content

FEAT Restructuring Attacks#1059

Merged
bashirpartovi merged 8 commits intomicrosoft:mainfrom
bashirpartovi:dev/bashirpartovi/executor-module
Aug 8, 2025
Merged

FEAT Restructuring Attacks#1059
bashirpartovi merged 8 commits intomicrosoft:mainfrom
bashirpartovi:dev/bashirpartovi/executor-module

Conversation

@bashirpartovi
Copy link
Copy Markdown
Contributor

Major Refactor: Extracting Strategy Pattern and Creating Prompt Generator Module

Overview

This is a significant architectural refactor that addresses design inconsistencies in our attack system and introduces a new module for generators that don't follow the traditional attack pattern.

Background and Motivation

Problem Statement

The original pyrit.attacks module contained several components that didn't align with the core attack pattern:

  • FuzzerAttack and AnecdoctorAttack were technically generators, not attacks
  • These components didn't have a clear "objective" that attacks are designed to achieve
  • Forcing them into the attack pattern led to poor design decisions and anti-patterns
  • The code became convoluted as we tried to make generators fit the attack model

Design Philosophy

True attacks have a specific target and objective they're trying to achieve, while generators create variations or new content based on input. This fundamental difference warranted separate architectural patterns.

Solution Architecture

1. Strategy Pattern Extraction

We extracted the core execution logic from AttackStrategy into a generic Strategy pattern:

  • Strategy: Base abstract class for all execution strategies
  • StrategyContext: Base context for strategy execution
  • StrategyResult: Base result type for all strategies
  • Event system: Comprehensive lifecycle event handling for extensibility

This extraction follows the principle of composition over inheritance and makes the codebase more modular.

2. AttackStrategy Refactoring

AttackStrategy now extends Strategy, inheriting the core execution pattern while adding attack-specific functionality:

  • Maintains attack-specific context (AttackContext) with objectives, memory labels, and conversation references
  • Preserves all existing attack functionality
  • Benefits from the event system for result persistence and lifecycle management

3. New Prompt Generator Module

Created pyrit.executor.promptgen module containing:

  • PromptGeneratorStrategy: Base class for generators extending Strategy
  • FuzzerGenerator: Refactored from FuzzerAttack, properly designed as a generator
  • AnecdoctorGenerator: Refactored from AnecdoctorAttack, following generator patterns

These components now have clean, purpose-built APIs that reflect their true nature as content generators.

Key Technical Improvements

Enhanced execute_async Overloading

The new pattern provides better execute_async method overloading:

# Context-based execution (internal)
async def execute_with_context_async(self, *, context: StrategyContextT) -> StrategyResultT

# Parameter-based execution (public API)
async def execute_async(self, **kwargs) -> StrategyResultT

This design:

  • Separates internal execution logic from public API
  • Provides type safety through context objects
  • Enables flexible parameter passing while maintaining structure
  • Supports both explicit context passing and parameter-based factory patterns

Event System Architecture

The new event system provides:

  • Lifecycle hooks: Pre/post validation, setup, execution, and teardown
  • Extensible handlers: Custom event handling for logging, persistence, metrics
  • Async support: Full async/await pattern throughout the event system
  • Memory integration: Automatic result persistence through event handlers

Robust Parameter Handling with get_kwarg_param

The use of get_kwarg_param utility function is a safety mechanism, not an anti-pattern:

  • Runtime type checking: Ensures parameters match expected types even when passed as **kwargs
  • Clear error messages: Provides descriptive errors for parameter mismatches
  • Flexibility: Allows dynamic parameter passing while maintaining type safety
  • Documentation: Serves as implicit documentation of expected parameter types

This approach is necessary because Python's dynamic nature allows any type to be passed at runtime, and we need to validate parameters that come through the generic **kwargs interface.

Migration Impact

Backward Compatibility

  • All existing attacks continue to work unchanged
  • Public APIs remain stable
  • Attack results and behavior are preserved

New Capabilities

  • Generators now have proper, clean APIs
  • Event system enables advanced customization
  • Strategy pattern allows new execution patterns beyond attacks
  • Better separation of concerns between attacks and generators

Code Organization

Before

pyrit/
  attacks/
    attack_strategy.py      # Mixed concerns
    fuzzer_attack.py       # Misnamed - actually a generator
    anecdoctor_attack.py   # Misnamed - actually a generator

After

pyrit/
  executor/
    core/
      strategy.py          # Generic execution pattern
    attack/
      core/
        attack_strategy.py # Attack-specific logic
    promptgen/
      core/
        prompt_generator_strategy.py  # Generator-specific logic
      fuzzer.py           # Properly named generator
      anecdoctor.py       # Properly named generator

Benefits

  1. Architectural Clarity: Clear separation between attacks (which have objectives) and generators (which create content)

  2. Code Maintainability: Each component follows its natural design patterns instead of being forced into inappropriate abstractions

  3. Extensibility: The Strategy pattern and event system make it easy to add new execution patterns and custom behaviors

  4. Type Safety: Better type checking and parameter validation throughout the system

  5. Testing: More focused, testable components with clear responsibilities

Future Implications

This refactor establishes a solid foundation for:

  • Adding new types of strategies beyond attacks and generators
  • Enhanced monitoring and observability through the event system
  • Better integration with external systems through event handlers
  • More sophisticated execution patterns and workflows

The Strategy pattern provides a clean extension point for future execution paradigms while maintaining backward compatibility with existing attack infrastructure.

Example Screenshots

New Fuzzer example and its new printer:

fuzzer-code fuzzer-output

@rlundeen2
Copy link
Copy Markdown
Contributor

Can you change this PR description slightly and publish as a blog?

Copy link
Copy Markdown
Contributor

@rlundeen2 rlundeen2 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really like these changes. It's also a lot of code and a lot I could have missed. But signing off on the structure, pattern, and approach.

I don't mind merging and then fixing bugs.

Comment thread pyrit/orchestrator/multi_turn/red_teaming_orchestrator.py
@bashirpartovi bashirpartovi merged commit 55dfddb into microsoft:main Aug 8, 2025
20 checks passed
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.

3 participants