{"record":{"id":"c6275d4f688d83d6","repo":"jwtk/jjwt","slug":"malformed-or-excessively-complex-name-json-if","errorCode":null,"errorMessage":"Malformed or excessively complex ${name} JSON. If experienced in a production environment, this could reflect a potential malicious ${name}, please investigate the source further. Cause: ${e.getMessage()}","messagePattern":"Malformed or excessively complex (.+?) JSON\\. If experienced in a production environment, this could reflect a potential malicious (.+?), please investigate the source further\\. Cause: (.+?)","errorType":"validation","errorClass":"io.jsonwebtoken.io.DeserializationException","httpStatus":null,"severity":"warning","filePath":"impl/src/main/java/io/jsonwebtoken/impl/io/JsonObjectDeserializer.java","lineNumber":68,"sourceCode":"        Object value;\n        try {\n            value = this.deserializer.deserialize(in);\n            if (value == null) {\n                String msg = \"Deserialized data resulted in a null value; cannot create Map<String,?>\";\n                throw new DeserializationException(msg);\n            }\n            if (!(value instanceof Map)) {\n                String msg = \"Deserialized data is not a JSON Object; cannot create Map<String,?>\";\n                throw new DeserializationException(msg);\n            }\n            // JSON Specification requires all JSON Objects to have string-only keys.  So instead of\n            // checking that the val.keySet() has all Strings, we blindly cast to a Map<String,?>\n            // since input would rarely, if ever, have non-string keys.\n            //noinspection unchecked\n            return (Map<String, ?>) value;\n        } catch (StackOverflowError e) {\n            String msg = String.format(MALFORMED_COMPLEX_ERROR, this.name, this.name, e.getMessage());\n            throw new DeserializationException(msg, e);\n        } catch (Throwable t) {\n            throw malformed(t);\n        }\n    }\n\n    protected RuntimeException malformed(Throwable t) {\n        String msg = String.format(MALFORMED_ERROR, this.name, t.getMessage());\n        throw new MalformedJwtException(msg, t);\n    }\n}\n","sourceCodeStart":50,"sourceCodeEnd":79,"githubUrl":"https://github.com/jwtk/jjwt/blob/fb71496164c71442d08adec4571d9616ed5e1b8d/impl/src/main/java/io/jsonwebtoken/impl/io/JsonObjectDeserializer.java#L50-L79","documentation":"Thrown as a DeserializationException with a security-oriented message when deserialization causes a StackOverflowError — typically deeply nested JSON that exceeds stack depth. Because deep nesting can indicate a malicious payload, JJWT surfaces an explicit warning recommending investigation of the source.","triggerScenarios":"Deserializing JSON with extremely deep object/array nesting (e.g. thousands of nested '{' characters) that overflows the stack in the underlying parser.","commonSituations":"Malicious or fuzzed tokens submitted to a public endpoint; upstream systems generating deeply nested claim structures; unbounded recursion in attacker-controlled JWT payloads (a known DoS vector).","solutions":["Reject or rate-limit inputs whose nesting depth exceeds a sane limit before parsing.","Validate the token source — this message specifically suggests a potentially malicious payload.","Add a pre-parse check on input size and brace-nesting depth (e.g. regex or scanner counting '{').","Consider limiting maximum JWT length at the gateway/ingress layer."],"exampleFix":"// before\nJwts.parser().build().parseClaimsJws(token); // parses any depth\n// after\nif (token != null && token.length() > MAX_TOKEN_LENGTH) {\n    throw new IllegalArgumentException(\"JWT exceeds maximum allowed length\");\n}\nJwts.parser().build().parseClaimsJws(token);","handlingStrategy":"validation","validationCode":"// Java\nprivate static final int MAX_DEPTH = 64;\nstatic int nestingDepth(String json) {\n    int depth = 0, max = 0;\n    for (char c : json.toCharArray()) {\n        if (c == '{' || c == '[') max = Math.max(max, ++depth);\n        else if (c == '}' || c == ']') depth--;\n    }\n    return max;\n}\nif (nestingDepth(token) > MAX_DEPTH) throw new SecurityException(\"JWT nesting too deep\");","typeGuard":"static boolean isPlausiblySafeJson(String json) {\n    return json != null && json.length() <= 65536 && nestingDepth(json) <= 64;\n}","tryCatchPattern":"try {\n    Jws<Claims> jws = Jwts.parser().build().parseClaimsJws(token);\n} catch (DeserializationException e) {\n    if (e.getMessage().contains(\"Malformed or excessively complex\")) {\n        securityLog.warn(\"Potential malicious payload from {}\", requestSource);\n    }\n    throw new SecurityException(\"Rejected suspicious token\");\n}","preventionTips":["Enforce maximum JWT length and nesting depth at your API gateway.","Rate-limit and log sources submitting deeply nested tokens.","Keep the JJWT library updated — parser hardening improves over versions.","Treat this error as a security signal, not just a parse failure, and review the token source."],"tags":["json","deserialization","security","dos","stack-overflow"],"backgroundTag":"invalid-json-response","analyzedSha":"fb71496164c71442d08adec4571d9616ed5e1b8d","analyzedAt":"2026-09-09T00:33:09.982Z","contentChangedAt":"2026-09-09T00:33:09.982Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}