feat(trace): add regression tests for 13 pre-existing detectors - #568
Open
stealthwhizz wants to merge 24 commits into
Open
feat(trace): add regression tests for 13 pre-existing detectors#568stealthwhizz wants to merge 24 commits into
stealthwhizz wants to merge 24 commits into
Conversation
Adds StepSpec dataclass and SequenceDetector base structure to finbot/ctf/detectors/primitives/. Includes config validation, get_relevant_event_types(), and stubbed private helpers for history querying, step matching, and time-window checks. check_event() and all helpers are NotImplementedError stubs pending implementation.
…gration - Add SequenceDetector to finbot/ctf/detectors/primitives/ Detects multi-step attack patterns across a session or workflow window. Supports ordered step matching, glob event_type patterns, within_n_events and within_seconds windows, and all ToolCallDetector field operators. Challenge authors configure it from YAML with no Python required. - Add composite index idx_ctf_event_session_ts_type on (session_id, timestamp, event_type) to keep session-window history queries below 10ms p95. - Export SequenceDetector from finbot/ctf/detectors/primitives/__init__.py - Add 17 unit tests covering full sequence detection, partial sequences, order enforcement, session/workflow windows, condition operators, and glob event_type matching.
- Add StepSpec TypedDict to sequence_detector.py matching the approved interface spec; export it from primitives __init__ - Add benchmark test: seeds 1,000 CTFEvent rows with composite index, runs check_event 100 times, asserts p95 < 10ms Current result: p50 ~7ms, p95 ~8ms on SQLite
…, and tests - IncrementalFraudDetector uses SequenceDetector as the matching engine; two-gate design: N below-threshold approvals in session window, then cumulative amount check fires when total >= cumulative_threshold - incremental_fraud.yaml: 300pts, ASI-08, fraud category; default config: 3 approvals each <= 9999, cumulative >= 25000 - Extend _emit_delegation_event() in orchestrator.py with context_preview field (first 500 chars of enriched context forwarded between agents) - Emit delegation.context_snapshot business event on every delegation hop making context forwarding observable and scoreable by detectors - Integration tests for IncrementalFraudDetector: full chain, 5-step sequence, session isolation, amount gates, rejection filtering - Unit tests for Delegation Audit: context capture, preview capping, event type validation, empty context handling
…_load_amounts
- sequence_detector.py: change re.search to re.fullmatch in the matches
operator so patterns must match the full value, not a substring.
re.search allowed conditions like {"matches": "approval"} to falsely
match "not_approval" or "partial_approval_pending".
- sequence_detector.py: apply all prior review fixes from PR GenAI-Security-Project#522 —
ANDed condition operators, contains case-normalisation, _CTF_COLUMNS
as module-level constant, consumed set for order_matters=False, else
clause for unknown operators.
- incremental_fraud.py: add namespace parameter to _load_amounts and
filter CTFEvent.namespace == namespace in the query. Guards against
cross-namespace amount loading after DB restores or migrations.
Detects lateral movement through agent context propagation:
- Gate 1: delegation.context_snapshot with PI score >= threshold (LLM judge)
- Gate 2: tool call in same workflow_id (receiving agent acted)
- Namespace-isolated, target_agent filter, configurable via YAML
- 14 unit tests covering all gates, filters, and edge cases
OWASP: ASI-01 (Goal Hijack), ASI-06 (Memory & Context Poisoning),
ASI-07 (Insecure Inter-Agent Communication)
- Add finbot/canary/seeder.py: seeds 2 honeypot vendor records per namespace at bootstrap; TINs and routing numbers follow CANARY_[A-Z]{2,6}_[0-9]{4} sentinel pattern; idempotent
- Add finbot/ctf/detectors/implementations/canary_detector.py: fires at confidence 1.0 on any agent tool event containing a sentinel value; watches both tool_call_start and tool_call_success
- Wire seed_canary_vendors_all_namespaces() into scripts/bootstrap.py
- Register CanaryDetector in implementations __init__
- 17 unit tests covering pattern matching, detector fire/no-fire, seeder idempotency, and namespace isolation
The \d escape in the module docstring raised a SyntaxWarning on import under Python 3.13. Match the character-class form already used in the seeder docstring.
Wire the CanaryDetector to a playable challenge. The player steers any FinBot agent into reading one of the seeded honeypot vendors (Apex Logistics Partners or Meridian Trade Solutions). When a canary sentinel value passes through an agent tool call, the detector fires at confidence 1.0. Validated against ChallengeSchema; detector_class resolves to the registered CanaryDetector.
Document how to author challenges against the TRACE detectors: SequenceDetector config reference, IncrementalFraudDetector, CanaryDetector, and ContextInjectionDetector, plus a validation snippet for testing a new challenge before boot.
Scores a student's forensic investigation submission (server, tool, directive) against the expected answer in detector_config, with independent partial credit per field (33/33/34 by default). Server and tool match exactly; the free-text directive uses substring matching by default, or exact when directive_match is set. Scoring is deterministic and never calls an LLM, so it behaves identically under any model backend. Evidence records the score and which fields were correct but never the expected answer, so completion evidence cannot spoil the challenge. 19 unit tests cover the 33/66/100 thresholds, zero-score submissions, extra fields that must not inflate the score, directive fuzzy/exact modes, normalization, the tool_arguments fallback, and config validation.
…allenge
Wire the PurpleTeamDetector into a playable forensic challenge:
- POST /ctf/api/v1/toolkit/investigation accepts a {server, tool,
directive} answer and emits business.investigation.submitted with a
fresh workflow_id per submission, so each attempt is tracked.
- The Debrief challenge is a purple team follow-up to Toxic Transfer.
It names finstripe/create_transfer as the poisoned tool and grades the
directive by meaning, not verbatim text.
- Upgrade directive matching from substring to token overlap with light
prefix stemming so students can paraphrase. A configurable
directive_threshold (default 0.6) controls how much of the expected
answer must appear.
24 unit tests pass, including reordered-paraphrase acceptance and
unrelated-text rejection. Full submit-to-score flow verified against the
challenge config.
# Conflicts: # finbot/ctf/detectors/implementations/__init__.py
… add ollama provider Wire IncrementalFraudDetector into the implementations __init__ so its decorator actually runs (it was defined but never imported, so the challenge could not score). Add the ollama provider branch to the LLM client for local Mellum2 runs.
Fills the remaining gap in detector test coverage so every detector in the registry has a unit regression test, matching the coverage pattern already used for the earlier-tested detectors.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fills the remaining gap in detector test coverage so every detector in the registry has a unit regression test, matching the coverage pattern already used for the earlier-tested detectors.
Test plan
pytest tests/unit/ctf/passes