| name | java-deserialization-and-parser-security |
| description | Use this skill when statically reviewing the JVM's untrusted-deserialization and data-parsing surface for remote-code-execution and injection risk — Java native ObjectInputStream gadget chains (and the ObjectInputFilter/JEP 290 control), SnakeYAML bare Constructor, Jackson polymorphic default typing without a PolymorphicTypeValidator, XML external-entity (XXE) exposure across every parser factory, and reflective/expression sinks fed by untrusted input. Trigger when a user provides code that deserializes bytes or parses YAML/JSON/XML from a request, message, uploaded file, or external API, or asks whether a parser is safe. Reads source and sanitized configuration only; it never executes code or deserializes a payload. |
| allowed-tools | Read Grep Glob |
| metadata | {"author":"github: Raishin","version":"0.1.0","updated":"2026-07-17","category":"security","lifecycle":"experimental"} |
Java Deserialization and Parser Security Review
Purpose
This skill statically reviews the JVM's untrusted-deserialization and data-parsing surface for remote-code-execution and injection risk. A parsing path is only safe if attacker-controllable bytes never reach Java native deserialization without a strict filter, YAML/JSON parsers cannot instantiate arbitrary types, XML parsers are hardened against external entities, and reflective/expression sinks are not driven by untrusted input. This skill owns the deserialization/parser RCE verdict for the Java board; the Spring Security agent may reference these findings but does not own them.
Trigger conditions
- A user provides code that calls
ObjectInputStream.readObject, RMI/JMX, or any native deserialization on data that can be attacker-controllable.
- A user provides code that parses YAML (SnakeYAML), JSON (Jackson polymorphic typing), or XML from a request body, message payload, uploaded file, or external API.
- A user asks whether a parser or deserializer is safe, or is triaging a suspected RCE/XXE.
When not to use
- The task is authentication/authorization or endpoint-exposure posture — route to the Spring Security agent (it references deserialization findings but does not own them).
- The task is dependency-version CVE triage or SBOM/scanning — route to the supply-chain agent (this skill names the vulnerable pattern regardless of version, but does not own version triage).
- The task is raw-SQL injection — that is a different sink and agent.
Lean operating rules
- CRITICAL — treat
ObjectInputStream.readObject/readUnshared, RMI, or JMX reading attacker-controllable bytes as a gadget-chain RCE surface. Recommend eliminating native serialization for untrusted data; if unavoidable, require a strict allow-list ObjectInputFilter (JEP 290) and treat its absence as the defect.
- CRITICAL — treat SnakeYAML
new Yaml() or a bare Constructor on untrusted input as arbitrary object instantiation / RCE (class-of CVE-2022-1471). Require SafeConstructor (or SnakeYAML 2.x LoaderOptions with a tag inspector); a version bump alone without SafeConstructor does not close it.
- CRITICAL — treat Jackson
enableDefaultTyping/activateDefaultTyping or @JsonTypeInfo(use = Id.CLASS) on attacker-controllable data without a restrictive PolymorphicTypeValidator as polymorphic-deserialization RCE. Require a whitelist validator or removing default typing.
- CRITICAL — treat XML parsing (
DocumentBuilderFactory, SAXParserFactory, XMLInputFactory, TransformerFactory, SchemaFactory, JAXB Unmarshaller) without external-entity/DTD hardening as XXE (file read, SSRF, DoS). Require disallow-doctype-decl (or disabled external general/parameter entities plus secure processing) and treat the unhardened factory as the defect.
- HIGH — treat other injection sinks fed by untrusted input: reflective
Class.forName/constructor on an attacker-supplied name, XStream without a type-permission allow-list, expression evaluation (SpEL/OGNL/MVEL) over user input, and java.beans.XMLDecoder on untrusted XML.
- HIGH — treat a parser hardened against RCE but not resource exhaustion (no entity-expansion limit / billion-laughs guard, no input-size bound) as a DoS gap.
- HIGH — distinguish the trust boundary explicitly: a finding is CRITICAL only when the data can be attacker-controllable (request body, message payload, uploaded file, external API). Provably internal/trusted data downgrades to a hardening recommendation — state the trust assumption and mark it
inference when the source does not prove the boundary.
- Never accept a blocklist of gadget classes as sufficient (blocklists are bypassable) — require allow-listing or eliminating the sink; never recommend catching the deserialization exception as a fix; never recommend disabling a failing gate.
- Anchor findings to the OWASP deserialization / XXE guidance rather than a single library version; a "this version is patched" claim is unless dependency evidence is provided (and belongs to the supply-chain agent).
References
Load these only when needed:
- Sink hardening catalog — per-sink safe vs dangerous patterns and the exact control for native serialization, SnakeYAML, Jackson polymorphic typing, XML/XXE, and reflective/expression sinks.
- Workflow and output contract — the step-by-step review (enumerate sinks → establish trust boundary → check the control → rate), the evidence checklist, and the output format.
Response minimum
Return, at minimum:
- A verdict (pass / pass-with-conditions / block) and, for each sink, the trust boundary assumed (attacker-controllable vs internal).
- Native-serialization findings (ObjectInputStream/RMI/JMX, ObjectInputFilter presence).
- YAML/JSON findings (SnakeYAML Constructor, Jackson default typing / PolymorphicTypeValidator).
- XML findings (XXE hardening per parser factory).
- Other reflective/expression/DoS findings.
- A severity-labelled finding list (critical / high / medium / low), each with an evidence-basis label.
- Safe next actions and open questions (including any trust boundary the user must confirm).