{"record":{"id":"2a3e5029063f8e12","repo":"jenkinsci/jenkins","slug":"mac-mismatch","errorCode":null,"errorMessage":"MAC mismatch","messagePattern":"MAC mismatch","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/hudson/console/ConsoleNote.java","lineNumber":274,"sourceCode":"                    }\n                } else {\n                    mac = null;\n                    sz = -macSz;\n                }\n                buf = new byte[sz];\n                decoded.readFully(buf);\n            }\n\n            byte[] postamble = new byte[POSTAMBLE.length];\n            in.readFully(postamble);\n            if (!Arrays.equals(postamble, POSTAMBLE))\n                return null;    // not a valid postamble\n\n            if (!INSECURE) {\n                if (mac == null) {\n                    throw new IOException(\"Refusing to deserialize unsigned note from an old log.\");\n                } else if (!MAC.checkMac(buf, mac)) {\n                    throw new IOException(\"MAC mismatch\");\n                }\n            }\n\n            Jenkins jenkins = Jenkins.getInstanceOrNull();\n\n            try (ObjectInputStream ois = new ObjectInputStreamEx(new GZIPInputStream(new ByteArrayInputStream(buf)),\n                    jenkins != null ? jenkins.pluginManager.uberClassLoader : ConsoleNote.class.getClassLoader(),\n                    ClassFilter.DEFAULT)) {\n                return getConsoleNote(ois);\n            }\n        } catch (Error e) {\n            // for example, bogus 'sz' can result in OutOfMemoryError.\n            // package that up as IOException so that the caller won't fatally die.\n            throw new IOException(e);\n        }\n    }\n\n    @SuppressFBWarnings(value = \"OBJECT_DESERIALIZATION\", justification = \"Deserialization is protected by logic.\")","sourceCodeStart":256,"sourceCodeEnd":292,"githubUrl":"https://github.com/jenkinsci/jenkins/blob/2e228ff40b14dbc8b14ffbc6edf0e4383cf744fc/core/src/main/java/hudson/console/ConsoleNote.java#L256-L292","documentation":"IOException from ConsoleNote.readFrom when INSECURE is false and the note's MAC does not verify against its payload (MAC.checkMac fails). This indicates the payload was tampered with, or the note was signed with a different Jenkins secret key than the one currently verifying.","triggerScenarios":"Reading a console log whose notes were signed by a different Jenkins instance/key; a log copied between instances; the Jenkins secret key was rotated/lost; the log bytes were altered.","commonSituations":"Copying build logs across instances with different secrets; restoring logs without the matching secret; tampering; key resharding that changed the MAC key.","solutions":["Do not transport logs across instances with different signing secrets; keep logs with their original instance.","Regenerate logs by re-running the build on the current instance.","Only as a last resort in a trusted test setup, set -Dhudson.console.ConsoleNote.INSECURE=true (disables MAC verification — insecure)."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    note = ConsoleNote.readFrom(in);\n} catch (IOException e) {\n    // MAC failed: treat note as untrusted, skip rendering it\n}","preventionTips":["Keep build logs with the instance that produced them; do not cross instances.","Avoid setting INSECURE=true — it disables integrity verification.","Re-run builds to regenerate logs after a secret/key change."],"tags":["console","security","deserialization","integrity"],"backgroundTag":null,"analyzedSha":"2e228ff40b14dbc8b14ffbc6edf0e4383cf744fc","analyzedAt":"2026-08-14T07:07:15.274Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}