feat(giskard-checks): minimal OWASP LLM suite generator (LLM01 indirect injection)#2438
Merged
Conversation
Implement BaseLLMGenerator (abstract multi-turn LLM generator base) and LLMGenerator (configurable via inline prompt or template path), mirroring the BaseLLMCheck/LLMJudge pattern on the generator side. Register LLMGenerator under the 'llm_generator' kind discriminator and expose both classes from the generators package. Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
- Remove @OverRide from BaseLLMGenerator.__call__ (async generator protocol differs) - Align LLMGenerator validator error messages to match LLMJudge style (hyphen, no trailing period) - Remove dead second response in test_llm_generator_stops_at_max_steps - Add tests for max_steps=0 and message=None-with-goal-not-reached cases - Extract MockGenerator and LLMTrace to shared conftest.py; add __init__.py to enable relative imports Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
- Create scenarios subdirectory and llm01_indirect_injection.j2 template - Template drives LLMGenerator to simulate indirect prompt injection attacks - Support multi-turn interactions with configurable max_turns limit Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
…d scenario dataset Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
…_suite, ScenarioCategory Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
…e generic parameters - Changed the return type annotation of generate_suite() to Suite[str, Any] for improved type clarity.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
…ract.generate() Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
…ue field Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
…ype for structured output Replaces the ValueError stub with a real implementation: parameterizes LLMGeneratorOutput[T] from input_type, raises InputGenerationException on schema_issue, and adds overloads for typed return. Tests cover BaseModel output, schema_issue raising, schema inclusion, and backward-compatible str output. Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
…ctured parsing test
…nference Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
…ule shadowing Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
…mpts to enforce goal_reached and message rules on first turn
- Document schema_issue field in user_simulator.j2 and llm01_indirect_injection.j2 prompts - Fix _infer_input_type to fall back to __call__ hints for callable-class targets - Add tests for callable-class input type inference - Change generate_suite() categories param to optional (None = all categories) - Add docstring to InputGenerationException - Remove trivial test_exceptions.py (covered by test_llm_generator.py) - Add tests/scenarios/__init__.py for consistency Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
…tances in Python 3.14+ - Import inspect to facilitate type hint inspection. - Update fallback mechanism for callable instances to correctly retrieve parameter hints from __call__. - Ensure compatibility with changes in get_type_hints behavior in Python 3.14+.
henchaves
approved these changes
May 12, 2026
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
BaseLLMGenerator+LLMGenerator— a multi-turn input generator hierarchy mirroring the existingBaseLLMCheck/LLMJudgepatternUserSimulatorto extendBaseLLMGenerator(removes duplicated loop logic)ScenarioCategoryenum +generate_suite()factory that loads predefined OWASP scenarios from JSONL datasets and injects agent description as an annotationmultiple_runs=5for replay-abilityInputGenerationExceptionfor generator-side errors (e.g. schema incompatibility)input_typesupport toInputGenerator.__call__— generators can now produce structuredBaseModelinputs, not juststrLLMGeneratorOutput[T]is now generic; the LLM is asked to produce aT-typed message viawith_output(LLMGeneratorOutput[T])Interact.generate()infersinput_typeat runtime from the target callable's first parameter annotation — no API change required at the call siteLLMGeneratorgainsas_template: bool = False— whenTrue, renders the inline prompt as a Jinja2 template (enabling{{ _instr_output }}schema injection); defaultFalseguards against prompt injection from user-controlled stringsUsage (str target, no change needed):
Usage (structured BaseModel target):
Test Plan
uv run pytest libs/giskard-checks/tests/ -q— 514 passed, 4 skippedfrom giskard.checks import BaseLLMGenerator, LLMGenerator, ScenarioCategory, generate_suite, UserSimulator, Suite, InputGenerationExceptiongenerate_suite()returns aSuitewith 1 scenario,multiple_runs=5, andannotations["description"]injectedBaseModel-annotated target:input_typeinferred, LLM produces structured outputschema_issueset by LLM →InputGenerationExceptionraised with"schema issue: ..."message🤖 Generated with Claude Code