Prompt security and validation
Introduction#
Injection detection, action-plan sanitization, logging around bad inputs, and how endpoints refuse unsafe content.
Project structure#
Security-relevant components are organized across prompts, services, routers, agents, utilities, and core infrastructure:
- Prompts define the instruction templates used to detect prompt injection.
- Services orchestrate validation and agent generation, including logging and error handling.
- Routers expose endpoints for validation and agent execution.
- Agents encapsulate the reasoning graph and message normalization.
- Utilities provide sanitization for JSON action plans and legacy JS validation.
- Core modules manage LLM providers and logging configuration.
graph TB subgraph "API Layer" R1["routers/website_validator.py"] R2["routers/react_agent.py"] end subgraph "Services" S1["services/website_validator_service.py"] S2["services/react_agent_service.py"] end subgraph "Prompts" P1["prompts/prompt_injection_validator.py"] end subgraph "Agents" A1["agents/react_agent.py"] end subgraph "Utilities" U1["utils/agent_sanitizer.py"] end subgraph "Core" C1["core/llm.py"] C2["core/config.py"] end subgraph "Tools" T1["tools/website_context/html_md.py"] end R1 --> S1 R2 --> S2 S1 --> P1 S1 --> T1 S1 --> C1 S2 --> A1 S2 --> C1 A1 --> C1 U1 -.-> S2 C2 --> S1 C2 --> S2
Core components#
- Prompt Injection Validator: A dedicated prompt template instructs the LLM to classify website content as safe or unsafe for prompt injection.
- Website Validator Service: Converts HTML to Markdown, constructs a validation chain, and interprets LLM output to produce a safety decision.
- Agent Sanitizer: Validates and sanitizes JSON action plans produced by the agent to prevent unsafe browser actions and script execution.
- React Agent and Service: Orchestrate message handling, optional file processing, and context injection from client HTML, with logging and error handling.
- LLM Provider Abstraction: Centralizes provider selection, model configuration, and error handling for LLM calls.
- Logging and Configuration: Global logging level and logger factory enable consistent security event logging.
Architecture overview#
The system integrates three major security flows:
- Website Content Safety: HTML → Markdown → Prompt Injection Classification → Safety Decision
- Agent Action Safety: Agent-generated JSON → Sanitization → Execution Guardrails
- Agent Prompt Safety: System prompt and context injection guarded by normalized messages and provider configuration
sequenceDiagram
participant Client as "Client"
participant Router as "website_validator.py"
participant Service as "website_validator_service.py"
participant Prompt as "prompt_injection_validator.py"
participant HTML2MD as "html_md.py"
participant LLM as "core/llm.py"
Client->>Router : POST /validate-website
Router->>Service : validate_website(request)
Service->>HTML2MD : return_html_md(html)
HTML2MD-->>Service : markdown_text
Service->>Prompt : load prompt_template
Service->>LLM : chain.invoke({markdown_text})
LLM-->>Service : LLM response
Service->>Service : interpret "true"/"false"
Service-->>Router : WebsiteValidatorResponse(is_safe)
Router-->>Client : ResponseDetailed component analysis#
Prompt injection validator implementation#
- Purpose: Determine whether website content may contain prompt injection attempts that could manipulate LLM behavior.
- Template Design: The prompt instructs the LLM to analyze content and respond with a simple boolean classification.
- Validation Chain: The service composes a LangChain prompt with the LLM and extracts a single “true” or “false” response to decide safety.
flowchart TD
Start(["Start"]) --> Convert["Convert HTML to Markdown"]
Convert --> Compose["Compose PromptTemplate with markdown_text"]
Compose --> Invoke["Invoke LLM with prompt"]
Invoke --> Parse["Parse LLM response"]
Parse --> Decision{"Is result 'true'?"}
Decision --> |Yes| Safe["Mark as Safe"]
Decision --> |No| Unsafe["Mark as Unsafe"]
Safe --> End(["End"])
Unsafe --> EndAgent prompt safety and message normalization#
- System Prompt: A controlled system message guides the agent’s behavior and credentials handling.
- Message Normalization: Messages are normalized to ensure consistent content representation across roles.
- Graph Execution: The compiled LangGraph workflow ensures deterministic agent behavior and consistent message handling.
classDiagram
class AgentState {
+messages : Sequence[BaseMessage]
}
class AgentMessagePayload {
+role : "system"|"user"|"assistant"|"tool"
+content : str
+name : str
+tool_call_id : str
+tool_calls : list[dict]
}
class GraphBuilder {
+buildgraph()
+__call__()
}
class LargeLanguageModel {
+client
+generate_text(prompt, system_message)
}
AgentState --> AgentMessagePayload : "normalized messages"
GraphBuilder --> LargeLanguageModel : "binds tools"Agent action sanitization and mitigation strategies#
- JSON Action Plan Validation: Ensures presence of required fields, validates action types, and checks required parameters per action category.
- Script Safety Checks: Detects potentially dangerous patterns in custom scripts to prevent unsafe execution.
- Legacy JS Validation: Provides a secondary filter for legacy JS patterns.
flowchart TD
Start(["Start JSON Actions"]) --> Strip["Strip code fences and normalize"]
Strip --> Parse["Parse JSON"]
Parse --> ValidStructure{"Has 'actions' array?"}
ValidStructure --> |No| Error["Return problems and None"]
ValidStructure --> |Yes| Iterate["Iterate actions"]
Iterate --> TypeCheck{"Type in VALID_ACTIONS?"}
TypeCheck --> |No| RecordType["Record invalid type problem"]
TypeCheck --> |Yes| DOMCheck{"DOM action?"}
DOMCheck --> |Yes| DOMFields{"Has required fields?"}
DOMFields --> |No| RecordDOM["Record missing fields problem"]
DOMFields --> |Yes| Next1["Next"]
DOMCheck --> |No| ExecCheck{"EXECUTE_SCRIPT?"}
ExecCheck --> |Yes| ScriptCheck["Scan for dangerous patterns"]
ScriptCheck --> PatternFound{"Dangerous pattern found?"}
PatternFound --> |Yes| RecordScript["Record dangerous pattern problem"]
PatternFound --> |No| Next2["Next"]
ExecCheck --> |No| TabCheck{"Tab control action?"}
TabCheck --> |Yes| TabFields{"Has required fields?"}
TabFields --> |No| RecordTab["Record missing fields problem"]
TabFields --> |Yes| Next3["Next"]
TabCheck --> |No| Next4["Next"]
RecordType --> Next1
RecordDOM --> Next1
RecordScript --> Next2
RecordTab --> Next3
Next1 --> End(["Return data, problems"])
Next2 --> End
Next3 --> End
Next4 --> End
Error --> EndEndpoint security and error handling#
- Website Validation Endpoint: Exposes a POST endpoint that delegates to the validator service and returns a safety decision.
- Agent Endpoint: Validates request fields, invokes the agent service, and handles exceptions with logging and HTTP error responses.
sequenceDiagram participant Client as "Client" participant Router as "react_agent.py" participant Service as "react_agent_service.py" participant Agent as "react_agent.py" participant LLM as "core/llm.py" Client->>Router : POST / Router->>Router : validate required fields Router->>Service : generate_answer(...) Service->>Agent : GraphBuilder()(state) Agent->>LLM : bound_llm.ainvoke(messages) LLM-->>Agent : AIMessage Agent-->>Service : final messages Service-->>Router : answer text Router-->>Client : CrawllerResponse Note over Router,Service : Exceptions are logged and surfaced as HTTP 500
Dependency analysis#
- Website Validator depends on:
- HTML-to-Markdown conversion
- Prompt template for injection detection
- LLM client for classification
- Agent Service depends on:
- GraphBuilder for workflow compilation
- LLM client for generation
- Logging for security event capture
- Agent Sanitizer is independent but integrates with agent action outputs.
- LLM Provider abstraction centralizes provider selection and error handling.
graph LR WVS["website_validator_service.py"] --> PIV["prompt_injection_validator.py"] WVS --> HTML2MD["html_md.py"] WVS --> LLM["core/llm.py"] RAS["react_agent_service.py"] --> RA["react_agent.py"] RAS --> LLM SAN["agent_sanitizer.py"] -.-> RAS CFG["core/config.py"] --> WVS CFG --> RAS
Performance considerations#
- Prompt Injection Detection: The validation chain performs a single LLM invocation per request; keep prompt concise and avoid excessive context to minimize latency.
- Agent Workflows: Graph caching via LRU reduces repeated compilation overhead; ensure message normalization avoids unnecessary conversions.
- Sanitization: Regex-based checks are linear in input size; keep action plans minimal and avoid overly complex scripts.
- Logging: Configure appropriate log levels to balance observability and performance.
Troubleshooting guide#
Common issues and remediation steps:
- Validation returns unexpected results:
- Verify HTML input is well-formed and not empty.
- Confirm the LLM provider is configured and reachable.
- Check that the prompt template remains unchanged and the response format matches expectations.
- Agent action plan errors:
- Ensure required fields are present for each action type.
- Review dangerous script patterns flagged by sanitization.
- Validate that action types are part of the allowed set.
- Endpoint failures:
- Inspect router-level HTTP exceptions and service logs.
- Confirm environment variables for API keys and base URLs are set.
- Logging:
- Adjust logging level via configuration and review logs for security events.
Conclusion#
Markdown conversion plus LLM classification catches many injections. JSON plan checks catch bad scripts. Neither replaces the other.
Appendices#
Validation rules and threat modeling#
- Prompt Injection Detection:
- Input: Website HTML
- Transformation: HTML → Markdown
- Output: Boolean classification indicating safety
- Agent Action Validation:
- Required fields per action type
- Allowed action categories
- Script pattern scanning for dangerous constructs
- Threat Modeling Approaches:
- Principle of least privilege for actions
- Separation of concerns between content parsing and safety decisions
- Defensive logging and HTTP error surfacing
Secure prompt construction guidelines#
- Keep system prompts concise and explicit about prohibited behaviors.
- Avoid exposing internal instructions or model internals in user-facing prompts.
- Use structured outputs (e.g., single-word classifications) to reduce ambiguity.
- Inject only sanitized context and avoid raw user-provided HTML or scripts.
Integration with the broader security framework#
- Logging: Centralized logger factory and environment-based log levels.
- Providers: Unified LLM provider configuration with explicit error handling.
- Endpoints: Clear separation of validation and agent execution routes.