{"record":{"id":"411bc394232e6125","repo":"gchq/CyberChef","slug":"unable-to-decode-json-payload-e-message-411bc3","errorCode":null,"errorMessage":"Unable to decode JSON payload: ${e.message}","messagePattern":"Unable to decode JSON payload: (.+?)","errorType":"exception","errorClass":"OperationError","httpStatus":null,"severity":"error","filePath":"src/core/operations/FlaskSessionVerify.mjs","lineNumber":129,"sourceCode":"            throw new OperationError(\"Invalid signature!\");\n        }\n\n        try {\n            const decoded = JSON.parse(payloadJson);\n            if (!args[3]) {\n                return {\n                    valid: true,\n                    payload: decoded,\n                };\n            } else {\n                return {\n                    valid: true,\n                    payload: decoded,\n                    timestamp: timestamp\n                };\n            }\n        } catch (e) {\n            throw new OperationError(\"Unable to decode JSON payload: \" + e.message);\n        }\n\n    }\n}\n\n\nexport default FlaskSessionVerify;\n","sourceCodeStart":111,"sourceCodeEnd":137,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/operations/FlaskSessionVerify.mjs#L111-L137","documentation":"Thrown after the signature has already validated successfully, when JSON.parse(payloadJson) fails on the decoded Base64 payload. This means the cookie is authentic but its payload is not valid JSON, which can happen with non-JSON serialization, encoding issues, or (rarely) a correctly-signed but corrupt payload. The original parse error message is appended for diagnostics.","triggerScenarios":"Signature passes but the decoded payload bytes are not a JSON document; payload was serialized with a custom Flask JSON provider (e.g. compact/non-standard); the Base64 decoding produced mojibake due to a padding/encoding edge case; or an itsdangerous serializer other than the default JSON serializer was used.","commonSituations":"Flask app configured with a custom JSON serializer (e.g. TaggedJSONSerializer producing non-raw-JSON bytes); legacy itsdangerous versions with different defaults; payload containing binary that survived signing but is not UTF-8 JSON.","solutions":["Inspect the decoded payload bytes manually (decode parts[0] as URL-safe Base64) to see the actual content.","If the app uses a custom serializer, decode the payload with that serializer instead of JSON.parse.","Confirm the cookie was produced by Flask's default session interface and not a third-party signer.","Check for double-encoding or transport corruption of the cookie value."],"exampleFix":"// before: relying on JSON.parse of a custom-serialized payload\nconst decoded = JSON.parse(payloadJson); // throws\n// after: inspect raw bytes first\nconst raw = Buffer.from(parts[0].replace(/-/g,'+').replace(/_/g,'/'), 'base64').toString('utf8');\nconsole.log(raw); // determine actual format before parsing","handlingStrategy":"try-catch","validationCode":"// After signature passes, check the payload parses as JSON before relying on it\nconst raw = Buffer.from(parts[0].replace(/-/g,'+').replace(/_/g,'/'),'base64').toString('utf8');\nlet payload;\ntry { payload = JSON.parse(raw); } catch { /* not JSON; inspect raw */ }","typeGuard":"function isJsonString(s) {\n  try { JSON.parse(s); return true; } catch { return false; }\n}","tryCatchPattern":"try {\n  const result = flaskVerify.run(cookie, args);\n} catch (e) {\n  if (e.type === 'OperationError' && /Unable to decode JSON payload/.test(e.message)) {\n    // authentic cookie but non-JSON payload; decode manually with the app's serializer\n  } else throw e;\n}","preventionTips":["Know whether the source Flask app uses the default JSON serializer or a custom one.","Decode the payload bytes manually first if the serializer is non-standard."],"tags":["flask","json","session-cookie","deserialization","crypto"],"backgroundTag":null,"analyzedSha":"4290ea753912378913b1f3f54e0fc5720afeda5d","analyzedAt":"2026-08-13T06:05:50.210Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}