{"record":{"id":"a7f0652ebefd682e","repo":"gchq/CyberChef","slug":"invalid-signature","errorCode":null,"errorMessage":"Invalid signature!","messagePattern":"Invalid signature!","errorType":"exception","errorClass":"OperationError","httpStatus":null,"severity":"error","filePath":"src/core/operations/FlaskSessionVerify.mjs","lineNumber":111,"sourceCode":"        const bytes = new Uint8Array(4);\n        for (let i = 0; i < 4; i++) {\n            bytes[i] = binary.charCodeAt(i);\n        }\n        const view = new DataView(bytes.buffer);\n        const timestamp = view.getInt32(0, false);\n\n        let payloadJson;\n        try {\n            payloadJson = fromBase64(padded);\n        } catch (e) {\n            throw new OperationError(\"Invalid Base64 payload\");\n        }\n\n        const signB64 = toBase64(sign.finalize());\n        const sign64 = signB64.replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=/g, \"\");\n\n        if (sign64 !== parts[2]) {\n            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);","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/operations/FlaskSessionVerify.mjs#L93-L129","documentation":"Thrown when the recomputed HMAC signature does not equal the signature segment (parts[2]) of the cookie. The operation derives an HMAC key from the secret + salt, signs 'payload.timestamp', converts the digest to URL-safe Base64 without padding, and string-compares it to the user-supplied signature. A mismatch means either the secret/salt/algorithm is wrong or the cookie was tampered with.","triggerScenarios":"Providing an incorrect secret key; using a wrong salt (Flask default is 'cookie-session'); selecting sha256 when the cookie was signed with sha1 (or vice versa); feeding a cookie from a different application; or a cookie whose payload/timestamp/signature were altered after signing.","commonSituations":"Wrong SECRET_KEY copied from config; environment mismatch (dev key vs prod key); Flask app using a custom SECURE_KEY or a signer with a non-default salt; copy-paste truncation of the signature segment; algorithm changed across Flask versions.","solutions":["Double-check the SECRET_KEY matches the Flask app's app.secret_key exactly.","Confirm the salt is 'cookie-session' (Flask default) unless the app customized it.","Match the Algorithm arg to the app: older Flask uses sha1, newer may use sha256.","Re-copy the full cookie value including the trailing signature segment to rule out truncation."],"exampleFix":"// before: wrong algorithm\nverify.run(cookie, [{string: key, option: 'UTF8'}, {string: 'cookie-session', option: 'UTF8'}, 'sha256', true])\n// after: match the app's signer\nverify.run(cookie, [{string: key, option: 'UTF8'}, {string: 'cookie-session', option: 'UTF8'}, 'sha1', true])","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  const result = flaskVerify.run(cookie, args);\n} catch (e) {\n  if (e.type === 'OperationError' && e.message === 'Invalid signature!') {\n    // signature mismatch: check key/salt/algorithm, do not treat as a crash\n  } else throw e;\n}","preventionTips":["Store the exact SECRET_KEY and salt used by the Flask app alongside the cookie.","Determine the algorithm (sha1 vs sha256) from the app's signer configuration before verifying.","Treat a signature mismatch as an expected, handled outcome rather than a fatal error."],"tags":["flask","hmac","signature","session-cookie","crypto","authentication"],"backgroundTag":null,"analyzedSha":"4290ea753912378913b1f3f54e0fc5720afeda5d","analyzedAt":"2026-08-13T06:05:50.210Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}