1
0
Files
jackson3-by-example/src/main/java/com/ankurm/jackson3/part7security/H04StreamReadConstraints.java
Ankur c438afc33b Jackson 3 series companion code
37 runnable examples covering the eight feature posts on ankurm.com, verified
against Jackson 3.2.1 on Temurin 21.0.5. Every output committed under docs/ was
produced by run-all.sh.

Also documents 11 places where the published snippets do not compile or do not
behave as printed against a real Jackson 3 build - most notably that
writeValueAsString(List<Base>) silently drops the polymorphic type discriminator,
so the post's serialised output cannot be read back.
2026-08-04 23:29:26 +05:30

58 lines
2.6 KiB
Java

package com.ankurm.jackson3.part7security;
import tools.jackson.core.StreamReadConstraints;
import tools.jackson.core.json.JsonFactory;
import tools.jackson.databind.json.JsonMapper;
/**
* BEYOND THE POST — the hardening the security post does not mention.
*
* Gadget attacks are not the only deserialisation risk. A small payload can also
* exhaust the stack or the heap: deeply nested arrays, gigantic numbers, enormous
* strings. Jackson 3 ships StreamReadConstraints with defaults for all three, and
* they are tunable. Any service accepting external JSON should know what they are.
*/
public class H04StreamReadConstraints {
public static void main(String[] args) {
StreamReadConstraints defaults = StreamReadConstraints.defaults();
System.out.println("--- Jackson 3 defaults ---");
System.out.println("max nesting depth : " + defaults.getMaxNestingDepth());
System.out.println("max number length : " + defaults.getMaxNumberLength());
System.out.println("max string length : " + defaults.getMaxStringLength());
System.out.println("max name length : " + defaults.getMaxNameLength());
System.out.println("max doc length : " + defaults.getMaxDocumentLength()
+ " (-1 = unlimited)");
System.out.println();
JsonMapper plain = JsonMapper.builder().build();
String deep = "[".repeat(1200) + "]".repeat(1200);
System.out.println("1200-deep nesting, default limits -> " + attempt(plain, deep));
// Tighten the limits for an endpoint that should never see nested data.
JsonFactory strictFactory = JsonFactory.builder()
.streamReadConstraints(StreamReadConstraints.builder()
.maxNestingDepth(10)
.maxStringLength(2_000)
.build())
.build();
JsonMapper strict = JsonMapper.builder(strictFactory).build();
System.out.println("20-deep nesting, strict limits -> "
+ attempt(strict, "[".repeat(20) + "]".repeat(20)));
System.out.println("5-deep nesting, strict limits -> "
+ attempt(strict, "[".repeat(5) + "]".repeat(5)));
System.out.println("3KB string, strict limits -> "
+ attempt(strict, "\"" + "x".repeat(3_000) + "\""));
}
private static String attempt(JsonMapper mapper, String json) {
try {
mapper.readTree(json);
return "accepted";
} catch (Exception e) {
return "rejected (" + e.getClass().getSimpleName() + ")";
}
}
}