This prompt is for security engineers and platform developers who are building the gateway between an AI agent and any tool that accepts serialized object payloads—such as Python pickles, YAML configs, or JSON with embedded type hints. The job-to-be-done is preventing deserialization attacks when an agent supplies or modifies a serialized payload before it reaches a tool's execution environment. You need this when your agent can construct arguments that will be deserialized by a downstream service, worker, or library, and you cannot trust the model to avoid dangerous type constructions on its own. The ideal user is someone who understands that prompt injection is not the only attack surface: a model coerced into producing a malicious serialized object can trigger remote code execution, denial-of-service, or data exfiltration at the deserialization layer, entirely outside the prompt's text boundary.
Prompt
Tool Input Deserialization Safety Prompt

When to Use This Prompt
Define the job, reader, and constraints for the Tool Input Deserialization Safety Prompt.
Do not use this prompt as a replacement for sandboxing, capability-based security, or hardened deserialization libraries at the infrastructure level. It is a defense-in-depth layer, not a primary security boundary. The prompt is appropriate when you control the pre-invocation validation pipeline and can insert a structured safety check between the model's output and the tool's deserializer. It is not appropriate when the agent directly writes files to disk, calls an unvalidated eval() equivalent, or operates in an environment where the deserialization target is outside your observability perimeter. You also should not rely on this prompt alone if the downstream tool uses a deserialization format that is inherently unsafe by design and cannot be made safe through structural checks—in those cases, the correct answer is replacing the format or wrapping the tool in a hardened sandbox, not prompting your way around it.
Before using this prompt, you must have defined a concrete allowlist of safe types, a maximum object depth, a maximum payload size, and a set of known-dangerous patterns for your specific deserialization format. The prompt template expects these as input variables. If you cannot enumerate what 'safe' means for your tool's serialization format, stop and define that contract first. Once you have that contract, this prompt becomes a reusable validation harness that you can wire into your agent's tool-calling middleware. The next section provides the copy-ready template, and the implementation harness section explains how to integrate it with retries, logging, and human escalation when the safety check rejects a payload.
Use Case Fit
Where the Tool Input Deserialization Safety Prompt works and where it introduces unacceptable risk or complexity.
Good Fit: Agent-to-Internal-API Gateways
Use when: An AI agent constructs serialized payloads (JSON, XML, Pickle) that are deserialized by an internal service. Guardrail: Deploy this prompt as a pre-deserialization safety layer that rejects dangerous types before the payload reaches the application runtime.
Good Fit: Multi-Tenant Platforms with Untrusted Agent Input
Use when: You run a platform where multiple tenants or users configure agents that can submit arbitrary serialized objects to shared tool infrastructure. Guardrail: Enforce a strict allowlist of deserializable types and a maximum object depth at the gateway, validated by this prompt's output.
Bad Fit: Performance-Critical, High-Throughput Pipelines
Avoid when: Every millisecond of latency matters and you process millions of small, trusted payloads per second. Guardrail: Use a native, compiled deserialization firewall (e.g., a Rust/WASM filter) instead. Reserve this prompt for asynchronous, lower-volume, or high-risk integration points.
Bad Fit: Already-Sandboxed or Strongly-Typed Runtimes
Avoid when: Your tool runtime already enforces memory-safe deserialization with a strict schema and no support for polymorphic types or custom gadget chains. Guardrail: Rely on the runtime's native guarantees. Adding an LLM-based check introduces a new failure mode without reducing material risk.
Required Input: A Complete Type Allowlist
Risk: Without an explicit allowlist, the prompt cannot reliably distinguish safe from dangerous types, leading to bypasses. Guardrail: Always provide a concrete, version-controlled list of permitted classes, modules, or type identifiers as part of the prompt's [CONSTRAINTS] input.
Operational Risk: Prompt Drift on Deserialization Logic
Risk: A model update may change how it interprets type safety rules, silently allowing a previously blocked gadget chain. Guardrail: Pin your model version and run a regression suite of known dangerous payloads (billion laughs, gadget chains) as a pre-deployment gate for any prompt or model change.
Copy-Ready Prompt Template
A reusable prompt template for safely deserializing agent-supplied payloads with strict type, depth, and size constraints.
This prompt template is designed to be placed directly in front of a deserialization step where an agent or upstream system provides a serialized payload. It instructs the model to act as a secure deserialization gate, producing a safe object graph while rejecting dangerous types, circular references, and resource-exhaustion attacks. The template uses square-bracket placeholders for all dynamic inputs, making it easy to integrate into a Python, Node.js, or Go application harness.
textYou are a secure deserialization guard. Your only job is to safely deserialize the provided payload into a strict in-memory representation and report what you did. ## Input Payload [PAYLOAD] ## Deserialization Format [FORMAT] ## Allowed Types [ALLOWED_TYPES] ## Constraints - Maximum object depth: [MAX_DEPTH] - Maximum total nodes: [MAX_NODES] - Maximum string length: [MAX_STRING_LENGTH] - Maximum array length: [MAX_ARRAY_LENGTH] - Reject all non-whitelisted types immediately. - Detect and reject circular references. - Detect and reject exponential expansion attacks (e.g., billion laughs, zip bombs in encoded form). - Do not execute, evaluate, or instantiate any code, classes, or constructors referenced in the payload. ## Output Schema Return a strict JSON object with the following structure: { "status": "success" | "rejected", "safe_object": <deserialized object graph, only if status is success>, "rejection_reason": "<detailed reason if status is rejected, otherwise null>", "warnings": ["<list of non-fatal concerns, e.g., depth near limit>"] } ## Examples of Rejection - Type not in allowed list: reject with reason "Disallowed type: [type_name]" - Circular reference detected: reject with reason "Circular reference at path: [path]" - Depth exceeds [MAX_DEPTH]: reject with reason "Max depth exceeded at path: [path]" - Node count exceeds [MAX_NODES]: reject with reason "Max node count exceeded" ## Final Instruction Process the payload exactly once. Do not retry on rejection. Do not attempt to fix or coerce the payload. If you are uncertain about safety, reject.
To adapt this template, replace each square-bracket placeholder with concrete values from your application context. [PAYLOAD] should be the raw serialized string. [FORMAT] should be the explicit format name (e.g., JSON, YAML, XML, Python pickle). [ALLOWED_TYPES] must be an exhaustive, minimal list of permitted types (e.g., str, int, float, bool, list, dict, None). Set numeric limits based on your application's memory and performance budget. If your system uses a custom deserialization library, mention its name and version in the [FORMAT] field to help the model reason about known vulnerabilities. Always run the model's output through a structural validator before trusting the safe_object field in your application code.
Prompt Variables
Required inputs for the Tool Input Deserialization Safety Prompt. Each placeholder must be populated before the prompt is assembled and sent to the model. Validation notes describe how to verify the input is safe and well-formed before it reaches the prompt.
| Placeholder | Purpose | Example | Validation Notes |
|---|---|---|---|
[RAW_PAYLOAD] | The untrusted serialized data string received from the agent tool call | {"$type":"System.IO.FileInfo","path":"/etc/passwd"} | Must be a non-empty string. Check for known dangerous type indicators before passing to the prompt. Reject if payload exceeds configured max depth or size limit. |
[ALLOWED_TYPES] | Whitelist of fully qualified type names permitted for deserialization | ["System.String", "System.Int32", "System.Collections.Generic.List`1[[System.String]]"] | Must be a valid JSON array of strings. Each entry must be a fully qualified type name. Reject if empty or contains wildcards. Validate against a canonical type registry. |
[MAX_DEPTH] | Maximum allowed nesting depth for the deserialized object graph | 5 | Must be a positive integer between 1 and 20. Lower values are safer. Validate as integer and enforce upper bound. Reject if null or non-numeric. |
[MAX_OBJECT_COUNT] | Maximum total number of objects allowed in the deserialized graph | 1000 | Must be a positive integer. Used to prevent billion-laughs and expansion attacks. Validate as integer. Reject if null, zero, or exceeds system resource limits. |
[FORBIDDEN_PATTERNS] | Regex patterns or type name substrings that trigger immediate rejection | ["System.Runtime", "System.Reflection", "System.Diagnostics.Process"] | Must be a valid JSON array of strings. Each entry is a case-insensitive substring match against type names. Validate array structure. Reject if empty when deserialization is enabled. |
[CIRCULAR_REFERENCE_POLICY] | Policy for handling circular references: reject, prune, or replace-with-null | "reject" | Must be one of: reject, prune, replace-with-null. reject is safest for untrusted input. Validate against allowed enum values. Reject if missing or unrecognized. |
[OUTPUT_SCHEMA] | Expected structure for the deserialization safety report | {"safe_object": {}, "rejected_types": [], "depth_exceeded": false, "circular_refs_detected": false, "anomalies": []} | Must be a valid JSON Schema or example structure. Validate that the schema includes fields for rejected items and safety flags. Reject if schema is missing required safety-report fields. |
Implementation Harness Notes
How to wire the deserialization safety prompt into an agent-to-tool gateway with validation, logging, and circuit-breaking.
The Tool Input Deserialization Safety Prompt is not a standalone utility; it is a pre-invocation security gate that must sit between the agent's tool call and the actual deserialization library. In a production harness, you will typically deploy this prompt inside a thin API middleware or a sidecar that intercepts tool invocation requests. The agent emits a serialized payload (JSON, YAML, XML, or a custom format), and before that payload reaches json.loads(), pickle.loads(), or yaml.safe_load(), the prompt inspects the raw string and the intended target type. The prompt's job is to produce a structured safety verdict: a deserialized object for safe payloads, or a rejection block listing dangerous types, depth violations, circular references, and type-confusion indicators. This verdict must be machine-readable so the harness can act on it without human parsing.
Implement the harness as a deterministic wrapper around the LLM call. First, apply static pre-checks that do not require the model: reject payloads exceeding a maximum byte size (e.g., 1 MB), scan for known dangerous magic bytes if the format supports them, and enforce a maximum nesting depth via a fast streaming parser before the prompt ever runs. If the payload passes static checks, construct the prompt with the raw payload in [INPUT], the expected schema or type in [TARGET_TYPE], and a strict [OUTPUT_SCHEMA] that demands a JSON object with fields status ("safe" or "rejected"), deserialized (the safe object or null), and rejection_reasons (an array of strings). After the model responds, validate the output JSON strictly: confirm status is an allowed enum value, rejection_reasons is present when status is "rejected", and deserialized conforms to [TARGET_TYPE] when status is "safe". If the model output fails structural validation, retry once with the validation error injected into [CONSTRAINTS]. If it fails again, escalate to a human review queue and block the tool invocation. Log every verdict—safe or rejected—with the payload hash, model response, and harness decision for audit and regression testing.
For high-throughput systems, consider model choice and caching carefully. A fast, instruction-tuned model (e.g., GPT-4o-mini, Claude Haiku) is usually sufficient for deserialization safety checks because the task is pattern recognition, not deep reasoning. Cache verdicts by payload hash to avoid redundant LLM calls for repeated payloads. Instrument the harness with a circuit breaker: if the model returns malformed responses for more than 5% of requests in a rolling window, or if latency exceeds a threshold, fail closed and route all tool invocations to a manual approval queue. Never allow a deserialization operation to proceed when the safety harness is degraded. Finally, maintain a regression suite of known attack payloads—gadget chains, billion-laughs XML bombs, circular references, and type-confusion samples—and run them through the harness on every prompt or model change to catch regressions before they reach production.
Expected Output Contract
Fields, format, and validation rules for the safe deserialization report produced by the prompt. Use this contract to validate the model's output before passing the deserialized object to downstream systems.
| Field or Element | Type or Format | Required | Validation Rule |
|---|---|---|---|
safe_object | object | Must be a valid JSON object. Parse check required. Must not contain any keys listed in rejected_dangerous_types. Depth must not exceed [MAX_DEPTH]. | |
rejected_dangerous_types | array of strings | Each element must be a string matching a known dangerous type (e.g., 'datetime', 'subprocess.Popen'). Array must be empty if no dangerous types found. Schema check: array items must be strings. | |
circular_references_detected | array of strings | Each element must be a JSONPath string (e.g., '$.a.b') identifying a detected cycle. Array must be empty if no cycles found. Null not allowed; use empty array. | |
depth_limit_exceeded | boolean | Must be true if the input payload exceeded [MAX_DEPTH] during traversal. If true, safe_object must be truncated at the limit. No null values allowed. | |
type_confusion_warnings | array of objects | Each object must contain 'field' (string), 'expected_type' (string), and 'actual_type' (string). Array must be empty if no mismatches. Schema check: required keys present in each element. | |
transformation_log | array of strings | Each entry must describe a safety transformation applied (e.g., 'Replaced class key at $.config'). Array must be empty if no transformations applied. Human-readable strings required. | |
deserialization_success | boolean | Must be true only if safe_object was produced without errors and rejected_dangerous_types is empty. If false, safe_object must be an empty object {}. No null values allowed. | |
error_message | string or null | Must be null if deserialization_success is true. If deserialization_success is false, must contain a non-empty string describing the primary failure reason. Null allowed only on success. |
Common Failure Modes
Deserialization attacks are a primary vector for remote code execution in agent-tool pipelines. These cards cover the most common failure modes when agents supply serialized payloads and how to prevent them before the deserializer runs.
Unsafe Type Deserialization
What to watch: Agent-supplied payloads that specify dangerous types (e.g., java.util.Runtime, Python pickle with __reduce__, .NET ObjectDataProvider) can trigger code execution during deserialization. Attackers exploit type hints in JSON, YAML, or binary formats to instantiate arbitrary classes. Guardrail: Maintain an explicit allowlist of permitted types. Reject any payload that references a type outside the allowlist before the deserializer processes it. Never use blocklist-based type filtering.
Billion-Laughs Entity Expansion
What to watch: XML and YAML payloads with recursive entity definitions that expand exponentially during parsing, consuming memory and CPU until the process crashes. A small payload can expand to gigabytes of data. Guardrail: Enforce strict entity expansion limits (e.g., maximum 1000 expansions, depth limit of 5). Disable DTD processing and external entity resolution entirely unless explicitly required and validated.
Circular Reference Stack Overflow
What to watch: JSON or YAML payloads with circular references ($ref loops) that cause infinite recursion during deserialization, leading to stack overflow and process termination. Attackers embed self-referencing objects that naive resolvers cannot detect. Guardrail: Implement reference tracking with a visited-node set during deserialization. Reject any payload where a reference points to an already-traversed node. Enforce a maximum reference depth (e.g., 20 levels).
Gadget Chain Injection
What to watch: Payloads that chain together otherwise-safe classes already on the classpath to achieve code execution. Gadget chains exploit property setters, constructors, and finalizers in libraries like Commons Collections or Spring. Guardrail: Use a deserialization library that supports type allowlisting at the field level, not just the root object. Run gadget chain detection tools against your classpath during CI. Reject payloads with unexpected nested object graphs.
Type Confusion and Polymorphic Attacks
What to watch: Payloads that declare a safe base type but supply a malicious subclass, bypassing type checks that only inspect the declared type. Polymorphic deserialization without explicit subtype control is the most common bypass vector. Guardrail: Require explicit subtype registration for all polymorphic fields. Reject any payload where the actual type does not match a pre-registered subtype mapping. Never use @JsonTypeInfo without @JsonSubTypes in Jackson.
Depth and Size Exhaustion
What to watch: Deeply nested payloads (1000+ levels) or excessively large payloads that exhaust stack space or memory before type checks complete. Attackers bypass type validation by triggering resource exhaustion at the parser level. Guardrail: Enforce maximum nesting depth (e.g., 20 levels) and maximum payload size (e.g., 1MB) at the input boundary before any parsing begins. Reject oversized or over-nested payloads with a clear error before deserialization.
Evaluation Rubric
Use this rubric to test the Tool Input Deserialization Safety Prompt before deployment. Each criterion targets a specific failure mode in deserialization safety, including gadget chains, resource exhaustion, and type confusion.
| Criterion | Pass Standard | Failure Signal | Test Method |
|---|---|---|---|
Standard Object Deserialization | Safe JSON object deserializes correctly with all fields preserved and no modifications | Missing fields, altered values, or rejection of safe payload | Provide a simple {"key": "value"} payload and verify output matches input exactly |
Dangerous Type Rejection | Payloads containing dangerous types (e.g., 'java.lang.Runtime', 'subprocess.Popen') are rejected with a clear reason | Dangerous type accepted and deserialized, or rejection without explanation | Inject payloads with known gadget chain classes and verify rejection with type name in rejection reason |
Billion-Laughs Attack Prevention | XML entity expansion attacks are detected and rejected before resource exhaustion occurs | System hangs, timeout, or memory spike during deserialization | Submit a billion-laughs XML payload and verify rejection within [MAX_DESERIALIZATION_MS] milliseconds |
Circular Reference Detection | Objects with circular references are detected and either rejected or safely handled with depth-limited output | Stack overflow, infinite loop, or unterminated processing | Provide JSON with circular references (e.g., object referencing itself) and verify clean rejection or bounded output |
Depth Limit Enforcement | Nested objects exceeding [MAX_NESTING_DEPTH] are rejected with a depth violation message | Deeply nested payload accepted without truncation or rejection | Submit a payload with nesting depth of [MAX_NESTING_DEPTH] + 1 and verify rejection with depth value in message |
Type Confusion Detection | Payloads where declared type does not match actual structure are flagged and rejected | Type confusion accepted and processed as declared type | Submit {"type": "SafeType", "data": "malicious_payload"} where actual structure mismatches and verify rejection |
Size Limit Enforcement | Payloads exceeding [MAX_PAYLOAD_SIZE_BYTES] are rejected before full parsing | Large payload processed without size check, causing memory pressure | Submit payload of [MAX_PAYLOAD_SIZE_BYTES] + 1KB and verify rejection with size information in message |
Safe Output Contract | Deserialized output contains only allowed primitive types, arrays, and flat objects with no executable constructs | Output contains function references, class instances, or code objects | Deserialize a complex but safe payload and verify output contains only JSON-serializable primitives, arrays, and objects |
Enabling Efficiency, Speed & Accuracy
Intelligent Analysis, Decision & Execution
We build AI systems for teams that need search across company data, workflow automation across tools, or AI features inside products and internal software.
Talk to Us
Search across company data
Give teams answers from docs, tickets, runbooks, and product data with sources and permissions.
Useful when people spend too long searching or get different answers from different systems.

Automate internal workflows
Use AI to route work, draft outputs, trigger actions, and keep approvals and logs in place.
Useful when repetitive work moves across multiple tools and teams.

Add AI to products and internal tools
Build assistants, guided actions, or decision support into the software your team or customers already use.
Useful when AI needs to be part of the product, not a separate tool.
Adapt This Prompt
How to adapt
Add a two-stage pipeline: first validate the raw payload structure, then deserialize with strict type whitelisting. Include depth limits (default 10), circular reference detection, and size caps (1MB). Log every rejection with the rejected type, depth, and source agent ID.
Extend the prompt:
code[SYSTEM_INSTRUCTION] You are a production deserialization safety filter. Given a serialized [INPUT_FORMAT] payload from agent [AGENT_ID]: 1. Validate the payload is well-formed [INPUT_FORMAT] 2. Parse with max depth [MAX_DEPTH] and max size [MAX_SIZE_BYTES] 3. Reject any type not in [ALLOWED_TYPES] 4. Detect circular references and reject if found 5. Return: { "safe_object": <parsed object or null>, "rejected_types": ["<type>", ...], "circular_reference_detected": true/false, "depth_exceeded": true/false, "size_exceeded": true/false, "rejection_reasons": ["<reason>", ...] }
Watch for
- Billion-laughs XML expansion exhausting memory before size check
- JSON prototype pollution via
__proto__orconstructorkeys - Silent failures when the model returns malformed JSON instead of the schema

About the author
Prasad Kumkar
CEO & MD, Inference Systems
Prasad Kumkar is the CEO & MD of Inference Systems and writes about AI systems architecture, LLM infrastructure, model serving, evaluation, and production deployment. Over 5+ years, he has worked across computer vision models, L5 autonomous vehicle systems, and LLM research, with a focus on taking complex AI ideas into real-world engineering systems.
His work and writing cover AI systems, large language models, AI agents, multimodal systems, autonomous systems, inference optimization, RAG, evaluation, and production AI engineering.
Partnered with leading AI, data, and software stack.
How We Work
Custom AI workflows for your Business
One-fit-all AI don't work for modern businesses. At Inferensys, we aim to understand your business & custom requirements; which we use to define most efficient agentic workflows, the data, and the tools for your business.
01
Review the use case
We understand the task, the users, and where AI can actually help.
Read more02
Pick the right approach
We define what needs search, automation, or product integration.
Read more03
Build the first useful version
We implement the part that proves the value first.
Read more04
Improve from there
We add the checks and visibility needed to keep it useful.
Read moreThe first call is a practical review of your use case and the right next step.
Talk to Us