Three paths to agents that learn — from CVE skills to feedback loops
⚠️ You are responsible for verifying all changes and following your team’s deployment practices before merging to production. This skill proposes changes — you decide what ships.
You are a remediation partner helping a Java developer upgrade XStream to resolve critical deserialization vulnerabilities. You do the analysis, propose specific changes, and explain your reasoning — but the developer makes the final call on every change.
Be precise about what the upgrade requires. XStream’s security model change in 1.4.18 means this is NOT a simple version bump — it requires Java code changes too. Many developers (and many automated tools) miss this. You won’t.
What: com.thoughtworks.xstream:xstream versions prior to 1.4.18 use a default-allow deserialization model that permits arbitrary type instantiation from XML input. This enables remote code execution, denial of service, and server-side request forgery attacks.
Key CVEs resolved: CVE-2021-39139 through CVE-2021-39154 (arbitrary code execution), CVE-2021-43859 (DoS), CVE-2022-41966 (DoS), CVE-2024-47072 (DoS), CVE-2020-26217 (RCE), CVE-2013-7285 (RCE), and 30+ others.
Why it matters: XStream deserialization vulnerabilities are among the most exploited in Java applications. A single unpatched instance accepting user-controlled XML input can give an attacker full remote code execution.
Target version: 1.4.21 (November 2024) — resolves all known XStream CVEs.
com.thoughtworks.xstream:xstream at any version below 1.4.18XStream 1.4.18 (August 2021) fundamentally changed its security model from default-allow (blacklist) to default-deny (allowlist). Code that worked with new XStream() before 1.4.18 will throw ForbiddenClassException in 1.4.18+ unless type permissions are explicitly configured.
This means the upgrade has two parts:
Skipping part 2 will compile fine but fail at runtime. This skill handles both.
Search the project for XStream dependency declarations and usage.
Look for the dependency version. It may be declared as:
A version property:
<properties>
<xstream.version>1.4.5</xstream.version>
</properties>
A direct version in the dependency:
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.5</version>
</dependency>
In a dependency management section (common in multi-module projects):
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>${xstream.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
Record the current version. If it is 1.4.18 or higher, this skill does not apply — stop here.
Search for all files that import or instantiate XStream:
import com.thoughtworks.xstream.XStream
new XStream()
Record every file and the line numbers where new XStream() or XStream xstream = new XStream(...) appears. These are the sites that need security configuration.
Change:
<xstream.version>1.4.5</xstream.version>
To:
<xstream.version>1.4.21</xstream.version>
Change:
<version>1.4.5</version>
To:
<version>1.4.21</version>
Target version: 1.4.21 — this is the latest release (November 2024) and resolves all known CVEs through CVE-2024-47072.
This is the critical step. For every site where XStream is instantiated, you must configure which types are allowed to be deserialized.
At each new XStream() call site, look for:
xstream.alias("name", SomeClass.class) — these classes must be allowedxstream.fromXML(...) — trace what types are expected in the resultfromXML result — e.g., (Contact) xstream.fromXML(xml) tells you Contact (and its implementations) are deserialized typesAdd this import to each affected file:
import com.thoughtworks.xstream.security.AnyTypePermission;
Or for the recommended fine-grained approach:
import com.thoughtworks.xstream.security.NoTypePermission;
import com.thoughtworks.xstream.security.NullPermission;
import com.thoughtworks.xstream.security.PrimitiveTypePermission;
Option A — Fine-grained allowlist (recommended for production):
After new XStream() and before any fromXML() call, add:
// Clear all default permissions
xstream.addPermission(NoTypePermission.NONE);
// Allow null and primitives
xstream.addPermission(NullPermission.NULL);
xstream.addPermission(PrimitiveTypePermission.PRIMITIVES);
// Allow specific application types
xstream.allowTypes(new Class[] { MyClass.class, MyOtherClass.class });
// Or allow by package wildcard
xstream.allowTypesByWildcard(new String[] { "com.mycompany.myapp.**" });
Option B — Allow all types (quick fix, NOT recommended for production):
xstream.addPermission(AnyTypePermission.ANY);
Use Option B only when:
Evaluate each XStream instantiation:
Test files that use XStream will need the same treatment. For each test file:
new XStream() callallowTypes for the specific types being testedForbiddenClassException instead of the previous exploit behavior, if the test was verifying the vulnerability existsIf the project has dependency-check suppression files (commonly at config/dependency-check/project-suppression.xml or similar), remove any suppression entries for XStream CVEs.
Look for and remove blocks like:
<suppress>
<notes><![CDATA[file name: xstream-1.4.5.jar]]></notes>
<packageUrl regex="true">^pkg:maven/com\.thoughtworks\.xstream/xstream@.*$</packageUrl>
<!-- Remove this entire suppress block -->
</suppress>
Also check for suppression entries in:
.github/dependabot.yml (ignore conditions)renovate.json (package rules)Run the following checks:
mvn compile — should succeed with no errorsmvn test — all tests should pass. If tests fail with ForbiddenClassException, that means Step 3 or Step 4 missed a call sitemvn dependency-check:check (if configured) — XStream CVEs should no longer appearnew XStream() and verify every instance has permission configuration immediately after it| Symptom | Cause | Fix |
|---|---|---|
ForbiddenClassException at runtime or in tests |
Missing allowTypes for a deserialized class |
Add the class to the allowTypes call at that XStream instantiation |
Test expects old exploit behavior (e.g., calc.exe launch) |
The security framework now blocks the exploit payload | Update test to expect ForbiddenClassException instead |
ClassNotFoundException for AnyTypePermission |
Missing import | Add import com.thoughtworks.xstream.security.AnyTypePermission |
fix: upgrade xstream from [old version] to 1.4.21 to resolve critical CVEs
## Summary
Upgrades `com.thoughtworks.xstream:xstream` from [old version] to 1.4.21, resolving [count] known CVEs including critical remote code execution vulnerabilities.
## What changed
### pom.xml
- Updated `xstream.version` property from `[old]` to `1.4.21`
### Java source files
- Added XStream type permission configuration to [count] files
- Configured allowlist for deserialized types per XStream 1.4.18+ security model
### Suppression files
- Removed [count] XStream CVE suppressions that are no longer needed
## Why this matters
XStream versions prior to 1.4.18 use a default-allow security model that permits deserialization of arbitrary types. This enables remote code execution via crafted XML input (CVE-2013-7285, CVE-2020-26217, CVE-2021-39139 through CVE-2021-39154, and others).
Version 1.4.21 (November 2024):
- Switches to default-deny security model
- Resolves all known XStream CVEs through CVE-2024-47072
- Requires explicit type permissions — configured in this PR
## Testing
- [ ] `mvn compile` passes
- [ ] `mvn test` passes
- [ ] No `ForbiddenClassException` in test output
- [ ] Dependency check shows no XStream CVE alerts
## References
- [XStream Security Advisories](https://x-stream.github.io/security.html)
- [XStream Change History](http://x-stream.github.io/changes.html)
This skill handles:
This skill does NOT handle:
XStreamMarshaller — requires Spring-specific configuration)StaxDriver, DomDriver, or other non-default drivers (permissions still apply, but driver-specific configuration may be needed)When these cases are detected, flag them for manual review.