{"record":{"id":"040d2155453e4a8d","repo":"jenkinsci/jenkins","slug":"refusing-to-deserialize-unsigned-note-from-an-old","errorCode":null,"errorMessage":"Refusing to deserialize unsigned note from an old log.","messagePattern":"Refusing to deserialize unsigned note from an old log\\.","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"warning","filePath":"core/src/main/java/hudson/console/ConsoleNote.java","lineNumber":272,"sourceCode":"                    if (sz < 0) {\n                        throw new IOException(\"Corrupt stream\");\n                    }\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    }","sourceCodeStart":254,"sourceCodeEnd":290,"githubUrl":"https://github.com/jenkinsci/jenkins/blob/2e228ff40b14dbc8b14ffbc6edf0e4383cf744fc/core/src/main/java/hudson/console/ConsoleNote.java#L254-L290","documentation":"IOException from ConsoleNote.readFrom when the INSECURE flag is false (the default, set by system property hudson.console.ConsoleNote.INSECURE) and a console note in the OLD unsigned format is encountered. Old logs predate note signing; default policy refuses to deserialize them to block deserialization attacks. The note is rejected, not the whole log.","triggerScenarios":"Viewing/parsing a very old build log (created before ConsoleNote signing) on a current Jenkins with INSECURE left at its default false.","commonSituations":"Old historical builds viewed after upgrade; logs restored from an ancient backup; migration from a pre-signing Jenkins version.","solutions":["Accept that old unsigned notes are skipped — the surrounding plain-text log still displays.","If you fully trust the log source and only need it in a throwaway/test instance, set -Dhudson.console.ConsoleNote.INSECURE=true (security risk; not for production).","Re-run the build to regenerate a signed log."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    note = ConsoleNote.readFrom(in);\n} catch (IOException e) {\n    // unsigned old note refused: skip, render plain text\n}","preventionTips":["Do not set INSECURE=true in production; only in trusted throwaway setups.","Expect old logs to lose their notes after upgrade — plain text remains."],"tags":["console","security","deserialization"],"backgroundTag":null,"analyzedSha":"2e228ff40b14dbc8b14ffbc6edf0e4383cf744fc","analyzedAt":"2026-08-14T07:07:15.274Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}