common

package
v0.9.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 2, 2026 License: MIT Imports: 7 Imported by: 0

Documentation

Overview

Package common provides shared types and utilities for all attack modules. This package consolidates duplicated definitions that previously existed independently in injection, jailbreak, orchestration, multimodal, and other attack packages.

Index

Constants

View Source
const (
	DefaultMaxQueries          = 100
	DefaultMaxWallClockSeconds = 180
	DefaultMaxGenerations      = 25
	HardMaxQueries             = 5000
	HardMaxWallClockSeconds    = 1800 // 30 min
	HardMaxGenerations         = 200
)

Default and hard-ceiling budgets for evolutionary engines. Operator config is clamped to the hard ceilings at Execute() entry; clamping logs a warning.

View Source
const MaxImagePayloadBytes = 5 * 1024 * 1024

MaxImagePayloadBytes caps the in-memory size of an inline image. Larger payloads should be uploaded out-of-band and referenced by URL. The cap matches Anthropic's 5 MiB-per-image limit; OpenAI's effective limit is similar after base64 expansion.

Variables

This section is empty.

Functions

func ContainsAnyInsensitive

func ContainsAnyInsensitive(text string, keywords []string) bool

ContainsAnyInsensitive checks if text contains any of the keywords (case-insensitive).

func ContainsInsensitive

func ContainsInsensitive(text, substr string) bool

ContainsInsensitive checks if text contains substr (case-insensitive).

func GenerateAttackID

func GenerateAttackID() string

GenerateAttackID generates a unique identifier for an attack.

func RandInt

func RandInt(max int) int

RandInt returns a cryptographically secure random integer in [0, max). Falls back to a timestamp-based value if crypto/rand fails.

Types

type AttackCategory

type AttackCategory string

AttackCategory categorizes attack modules by domain.

const (
	CategoryInjection     AttackCategory = "injection"
	CategoryJailbreak     AttackCategory = "jailbreak"
	CategoryOrchestration AttackCategory = "orchestration"
	CategoryEvasion       AttackCategory = "evasion"
	CategoryExtraction    AttackCategory = "extraction"
	CategoryMultimodal    AttackCategory = "multimodal"
	CategoryPersistence   AttackCategory = "persistence"
	CategoryExfiltration  AttackCategory = "exfiltration"
	CategorySupplyChain   AttackCategory = "supply_chain"
	CategoryRAG           AttackCategory = "rag"
	CategoryAgentic       AttackCategory = "agentic"
	CategoryAudio         AttackCategory = "audio"
	CategoryReasoning     AttackCategory = "reasoning"
	CategoryAdaptive      AttackCategory = "adaptive"
	CategoryMemory        AttackCategory = "memory"
)

type AttackConfig

type AttackConfig struct {
	// Target configuration
	Technique   string        `json:"technique"`
	Payload     string        `json:"payload"`
	Objective   string        `json:"objective"`
	MaxAttempts int           `json:"max_attempts"`
	Timeout     time.Duration `json:"timeout"`

	// Provider settings
	ProviderName string `json:"provider_name"`
	Model        string `json:"model"`

	// Context
	SystemPrompt string    `json:"system_prompt"`
	History      []Message `json:"history"`

	// Success criteria
	SuccessIndicators []string `json:"success_indicators"`

	// Advanced options
	UseMutation    bool    `json:"use_mutation"`
	MutationRate   float64 `json:"mutation_rate"`
	UseObfuscation bool    `json:"use_obfuscation"`

	// Cost control
	MaxCostUSD float64 `json:"max_cost_usd"`

	// Metadata
	Context  map[string]interface{} `json:"context,omitempty"`
	Metadata map[string]string      `json:"metadata,omitempty"`
}

AttackConfig configures an attack execution.

func (AttackConfig) CostExceeded

func (c AttackConfig) CostExceeded(accumulatedCost float64) bool

CostExceeded reports whether accumulatedCost has reached the configured ceiling. Returns false if no ceiling is set (MaxCostUSD <= 0).

type AttackOutcome added in v0.9.0

type AttackOutcome string

AttackOutcome categorizes how an attack run ended. Introduced in v0.9.0 to disambiguate "ran fully and target resisted" from "did not run to completion" (capability missing, gate blocked, budget out, provider error).

Bandit reward attribution should filter on outcome:

WHERE outcome IN ('success', 'refused')

Skipped runs do not enter the reward signal.

const (
	OutcomeSuccess AttackOutcome = "success" // attack landed (target produced harmful content)
	OutcomeRefused AttackOutcome = "refused" // ran fully; target resisted
	OutcomeSkipped AttackOutcome = "skipped" // did not run to completion; see SkipReason
)

type AttackResult

type AttackResult struct {
	// Identification
	ID        string    `json:"id"`
	Timestamp time.Time `json:"timestamp"`

	// Attack details
	Technique string `json:"technique"`
	Payload   string `json:"payload"`

	// Results
	Success    bool    `json:"success"`
	Confidence float64 `json:"confidence"`
	Response   string  `json:"response"`

	// v0.9.0: typed outcome and skip reason. Outcome is the source of truth;
	// Success is kept as a derived field for backward compatibility.
	Outcome    AttackOutcome `json:"outcome,omitempty"`
	SkipReason SkipReason    `json:"skip_reason,omitempty"`
	SkipDetail string        `json:"skip_detail,omitempty"`

	// CleanupHint is set by attack modules that perform persistent state
	// changes (e.g., memory poisoning). It contains operator-facing
	// instructions for purging injected records. v0.9.0 does not auto-purge;
	// the v0.10.0 Purger interface will close that loop.
	CleanupHint string `json:"cleanup_hint,omitempty"`

	// Metrics
	AttemptCount int           `json:"attempt_count"`
	Duration     time.Duration `json:"duration"`
	TokensUsed   int           `json:"tokens_used"`
	CostUSD      float64       `json:"cost_usd"`

	// Analysis
	SuccessFactors    []string `json:"success_factors,omitempty"`
	FailureReasons    []string `json:"failure_reasons,omitempty"`
	SuggestedFollowup string   `json:"suggested_followup,omitempty"`

	// Metadata
	Metadata map[string]interface{} `json:"metadata,omitempty"`
}

AttackResult contains the outcome of an attack execution.

In v0.9.0, the typed fields Outcome/SkipReason/SkipDetail/CleanupHint were added alongside the existing Success bool. The two are kept in sync by the NewAttackResult constructor and the WithSkip helper:

r := NewAttackResult("minja", OutcomeSuccess)        // Success=true,  Outcome=success
r := NewAttackResult("h_cot", OutcomeSkipped).WithSkip(SkipSignatureGated, "...")

Direct struct literals on AttackResult are still permitted for backward compatibility with v0.8.0 modules, but new code should prefer the constructor to avoid Success/Outcome desync. See TestAttackResultInvariants.

func NewAttackResult added in v0.9.0

func NewAttackResult(technique string, outcome AttackOutcome) *AttackResult

NewAttackResult constructs an AttackResult with Outcome and Success kept consistent. Prefer this over struct literals in v0.9.0+ code.

func (*AttackResult) IsSkipped added in v0.9.0

func (r *AttackResult) IsSkipped() bool

IsSkipped reports whether the result was skipped (capability missing, gate blocked, budget out, or provider error). Convenience for bandit reward filters and report generators.

func (*AttackResult) WithSkip added in v0.9.0

func (r *AttackResult) WithSkip(reason SkipReason, detail string) *AttackResult

WithSkip annotates a skipped result with reason and human-readable detail. Returns the receiver for fluent chaining. Panics if Outcome != OutcomeSkipped (attaching a skip reason to a non-skipped result would mask the actual outcome) or if reason is empty/unknown (we want skip taxonomy integrity for the bandit reward filter).

type Cleaner added in v0.9.0

type Cleaner interface {
	Cleanup(ctx context.Context, recordIDs []string) error
}

Cleaner is an OPTIONAL interface implemented by attack modules (not providers) that perform persistent state changes. The CLI invokes Cleanup with the injected record IDs reported by a previous run's CleanupHint.

v0.9.0 ships memory-poisoning modules that emit CleanupHint but do not implement Cleanup. The v0.10.0 Purger interface on providers will close the loop by enabling automated cleanup.

This is a separate interface, not a default-no-op method on AttackModule, because Go has no default methods and existing v0.8.0 modules should not be forced to add stub implementations.

type EngineBudget added in v0.9.0

type EngineBudget struct {
	MaxQueries          int  `json:"max_queries"`
	MaxWallClockSeconds int  `json:"max_wall_clock_seconds"`
	MaxGenerations      int  `json:"max_generations"`
	EarlyStopOnSuccess  bool `json:"early_stop_on_success"`
}

EngineBudget bounds the runtime of evolutionary attack engines (jbfuzz, persona_evolve). All four knobs are honored independently. Introduced in v0.9.0.

func DefaultEngineBudget added in v0.9.0

func DefaultEngineBudget() EngineBudget

DefaultEngineBudget returns the v0.9.0 default budget for adaptive engines.

func (*EngineBudget) Clamp added in v0.9.0

func (b *EngineBudget) Clamp() []string

Clamp reduces budget knobs to the hard ceilings, returning a summary of any fields that were clamped. The returned slice is empty when no clamping occurred.

type ImageDetail added in v0.9.0

type ImageDetail string

ImageDetail is an advisory hint to the provider about image processing detail. Providers that don't accept this hint silently ignore it.

Documented behavior:

  • OpenAI: ImageDetailLow ≈ 85 tokens fixed; ImageDetailHigh tiles at 768px (~170 tok/tile).
  • Anthropic: hint is currently ignored.
const (
	ImageDetailLow  ImageDetail = "low"
	ImageDetailHigh ImageDetail = "high"
	ImageDetailAuto ImageDetail = "auto"
)

type ImageMimeType added in v0.9.0

type ImageMimeType string

ImageMimeType enumerates the image MIME types supported by ImageProvider implementations. Each major provider supports a slightly different set; see the provider adapter docs for specifics.

const (
	ImageMimeJPEG ImageMimeType = "image/jpeg"
	ImageMimePNG  ImageMimeType = "image/png"
	ImageMimeGIF  ImageMimeType = "image/gif"
	ImageMimeWebP ImageMimeType = "image/webp"
)

type ImagePayload added in v0.9.0

type ImagePayload struct {
	// contains filtered or unexported fields
}

ImagePayload carries a single image to QueryWithImages. Construct via NewImagePayloadBytes or NewImagePayloadURL — direct struct literals are disallowed (fields are unexported) so the constructor can validate invariants (mutual exclusion of bytes vs URL, MIME-type membership, non-empty data, size limits).

func NewImagePayloadBytes added in v0.9.0

func NewImagePayloadBytes(b []byte, mt ImageMimeType, d ImageDetail) (ImagePayload, error)

NewImagePayloadBytes constructs an inline-bytes ImagePayload after validating the MIME type, non-empty data, and size cap.

The constructor takes a defensive copy of b so post-construction mutations by the caller cannot violate the validated invariants.

func NewImagePayloadURL added in v0.9.0

func NewImagePayloadURL(url string, mt ImageMimeType, d ImageDetail) (ImagePayload, error)

NewImagePayloadURL constructs a URL-referenced ImagePayload. The URL is not fetched at construction time; it is sent verbatim to the provider, which fetches it server-side.

func (ImagePayload) Bytes added in v0.9.0

func (p ImagePayload) Bytes() []byte

Bytes returns a defensive copy of the inline image bytes (nil for URL-referenced payloads). Callers cannot mutate the payload's internal state through the returned slice.

func (ImagePayload) Detail added in v0.9.0

func (p ImagePayload) Detail() ImageDetail

Detail returns the advisory detail hint.

func (ImagePayload) IsURL added in v0.9.0

func (p ImagePayload) IsURL() bool

IsURL reports whether the payload is a URL reference (vs inline bytes).

func (ImagePayload) MimeType added in v0.9.0

func (p ImagePayload) MimeType() ImageMimeType

MimeType returns the image MIME type.

func (ImagePayload) URL added in v0.9.0

func (p ImagePayload) URL() string

URL returns the image URL ("" for inline-bytes payloads).

type ImageProvider added in v0.9.0

type ImageProvider interface {
	Provider
	// QueryWithImages sends a prompt with one or more images. The response is
	// returned as text; structured response fields (token counts, finish reason)
	// are not surfaced through this minimal interface — modules needing them
	// should type-assert against the underlying core.Provider.
	QueryWithImages(ctx context.Context, prompt string, images []ImagePayload, options map[string]interface{}) (string, error)
}

ImageProvider is implemented by providers that accept image inputs alongside text prompts (e.g., GPT-4o, Claude 4.x with vision, Gemini multimodal).

Used by SIVA (split-image jailbreak) and VSH (virtual scenario hypnosis) attack modules in v0.9.0.

type Logger

type Logger interface {
	Debug(msg string, keysAndValues ...interface{})
	Info(msg string, keysAndValues ...interface{})
	Warn(msg string, keysAndValues ...interface{})
	Error(msg string, keysAndValues ...interface{})
}

Logger defines the structured logging interface used by attack modules.

type MemoryProbe added in v0.9.0

type MemoryProbe interface {
	Provider
	ProbeMemory(ctx context.Context) (retains bool, err error)
}

MemoryProbe is implemented by providers that can report whether the target retains state across calls (e.g., a memory-augmented agent endpoint).

Memory-poisoning modules call ProbeMemory before injection to fail fast on stateless targets. The error contract is strict:

(true, nil)   → target retains memory; proceed with injection.
(false, nil)  → target is stateless; emit OutcomeSkipped + SkipMemoryNotRetained.
(_, err)      → probe failed; emit OutcomeSkipped + SkipProviderError.
                A failed probe is NOT the same as known-no-memory.

type Message

type Message struct {
	Role      string                 `json:"role"`
	Content   string                 `json:"content"`
	Timestamp time.Time              `json:"timestamp,omitempty"`
	Metadata  map[string]interface{} `json:"metadata,omitempty"`
}

Message represents a conversation message exchanged with an LLM.

type NopLogger

type NopLogger struct{}

NopLogger is a Logger that discards all output. Useful for testing.

func (*NopLogger) Debug

func (l *NopLogger) Debug(_ string, _ ...interface{})

func (*NopLogger) Error

func (l *NopLogger) Error(_ string, _ ...interface{})

func (*NopLogger) Info

func (l *NopLogger) Info(_ string, _ ...interface{})

func (*NopLogger) Warn

func (l *NopLogger) Warn(_ string, _ ...interface{})

type Provider

type Provider interface {
	// Query sends messages to the LLM and returns the response text.
	Query(ctx context.Context, messages []Message, options map[string]interface{}) (string, error)
	// GetName returns the provider name (e.g., "openai", "anthropic").
	GetName() string
	// GetModel returns the model identifier (e.g., "gpt-4", "claude-3").
	GetModel() string
	// GetTokenCount returns the approximate token count for the given text.
	GetTokenCount(text string) int
}

Provider is the interface for LLM providers used by attack modules. This is a simplified facade over the full core.Provider interface, providing only the methods that attack modules need.

type ReasoningProvider added in v0.9.0

type ReasoningProvider interface {
	Provider
	// QueryWithReasoning sends a chat request and returns the final response
	// plus the model's reasoning trace. Providers that do not return a
	// trace for the given request (e.g., model class doesn't reason, or
	// request didn't trigger reasoning) return an empty trace; callers
	// distinguish via len(trace.Steps) == 0.
	QueryWithReasoning(ctx context.Context, messages []Message, options map[string]interface{}) (response string, trace ReasoningTrace, err error)
}

ReasoningProvider is implemented by providers that expose the model's reasoning trace alongside the final response (e.g., DeepSeek-R1, Gemini 2.5 "Deep Think", o3, Claude 4.x extended thinking).

Used by the H-CoT (chain-of-thought hijacking) attack module in v0.9.0.

The interface is intentionally minimal — the heavier core.ReasoningProvider exposes structured reasoning steps, token counts, and timing for use inside provider adapters. Attack modules only need the per-step text and a "is this trace cryptographically signed (and therefore unmodifiable)?" boolean to gate the mutation path.

type ReasoningTrace added in v0.9.0

type ReasoningTrace struct {
	// Steps is the ordered list of reasoning-step text. Empty when the
	// provider returned no trace for this query.
	Steps []string
	// Signed reports whether the trace is cryptographically signed and
	// therefore not safely modifiable on round-trip.
	Signed bool
}

ReasoningTrace is the minimal reasoning-trace shape consumed by attack modules. The Signed field reports whether the provider returned a cryptographically-signed trace whose text cannot be modified on round-trip (Anthropic's thinking-block signature). Modules detecting Signed=true emit OutcomeSkipped + SkipSignatureGated rather than attempting mutation that would be silently discarded.

type SessionProvider added in v0.9.0

type SessionProvider interface {
	Provider
	// SessionID returns a stable identifier for the current session.
	// Empty string indicates no session abstraction (single-shot calls).
	SessionID() string
	// NewSession returns a sibling provider bound to a fresh session. The
	// returned provider may also implement MemoryProbe and ImageProvider; the
	// caller should re-assert as needed.
	NewSession(ctx context.Context) (Provider, error)
}

SessionProvider is implemented by providers that expose session lifecycle controls. Memory-poisoning modules use NewSession to verify that injected records persist across fresh sessions.

type SimpleLogger

type SimpleLogger struct{}

SimpleLogger provides a basic fmt-based Logger implementation.

func (*SimpleLogger) Debug

func (l *SimpleLogger) Debug(msg string, keysAndValues ...interface{})

func (*SimpleLogger) Error

func (l *SimpleLogger) Error(msg string, keysAndValues ...interface{})

func (*SimpleLogger) Info

func (l *SimpleLogger) Info(msg string, keysAndValues ...interface{})

func (*SimpleLogger) Warn

func (l *SimpleLogger) Warn(msg string, keysAndValues ...interface{})

type SkipReason added in v0.9.0

type SkipReason string

SkipReason enumerates the reasons an attack run can end with Outcome=OutcomeSkipped. Introduced in v0.9.0.

const (
	SkipMissingCapability   SkipReason = "missing_capability"
	SkipGateBlocked         SkipReason = "gate_blocked"
	SkipBudgetExceeded      SkipReason = "budget_exceeded"
	SkipProviderError       SkipReason = "provider_error"
	SkipPreconditionFailed  SkipReason = "precondition_failed"
	SkipModelRefusedImage   SkipReason = "model_declined_image_input"
	SkipReasoningTraceEmpty SkipReason = "reasoning_trace_empty"
	SkipSignatureGated      SkipReason = "anthropic_signature_blocks_mutation"
	SkipNoMutationTarget    SkipReason = "no_safety_step_to_hijack"
	SkipMemoryNotRetained   SkipReason = "provider_reports_no_memory_retention"
)

type TechniqueInfo

type TechniqueInfo struct {
	ID          string  `json:"id"`
	Name        string  `json:"name"`
	Description string  `json:"description"`
	Category    string  `json:"category"`
	Risk        string  `json:"risk"`
	SuccessRate float64 `json:"success_rate"`
	Examples    []string
	// OWASP mappings
	OWASPLLMCategories     []string `json:"owasp_llm_categories,omitempty"`
	OWASPAgenticCategories []string `json:"owasp_agentic_categories,omitempty"`
}

TechniqueInfo provides metadata about an attack technique.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL