{"record":{"id":"3f6b447abd1b61e2","repo":"gchq/CyberChef","slug":"invalid-file-type-3f6b44","errorCode":null,"errorMessage":"Invalid file type.","messagePattern":"Invalid file type\\.","errorType":"exception","errorClass":"OperationError","httpStatus":null,"severity":"error","filePath":"src/core/operations/ImageBrightnessContrast.mjs","lineNumber":57,"sourceCode":"            {\n                name: \"Contrast\",\n                type: \"number\",\n                value: 0,\n                min: -100,\n                max: 100,\n            },\n        ];\n    }\n\n    /**\n     * @param {ArrayBuffer} input\n     * @param {Object[]} args\n     * @returns {byteArray}\n     */\n    async run(input, args) {\n        const [brightness, contrast] = args;\n        if (!isImage(input)) {\n            throw new OperationError(\"Invalid file type.\");\n        }\n\n        let image;\n        try {\n            image = await Jimp.read(input);\n        } catch (err) {\n            throw new OperationError(`Error loading image. (${err})`);\n        }\n        try {\n            if (brightness !== 0) {\n                if (isWorkerEnvironment())\n                    self.sendStatusMessage(\"Changing image brightness...\");\n                image.brightness(brightness / 100);\n            }\n            if (contrast !== 0) {\n                if (isWorkerEnvironment())\n                    self.sendStatusMessage(\"Changing image contrast...\");\n                image.contrast(contrast / 100);","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/operations/ImageBrightnessContrast.mjs#L39-L75","documentation":"Thrown at the top of Image Brightness/Contrast run() when isImage(input) returns false. isImage sniffs magic bytes against known image types (PNG/JPEG/GIF/BMP/WebP etc.). If the leading bytes do not match any image signature the buffer is rejected before Jimp is ever called.","triggerScenarios":"Feeding a non-image file (text, PDF, archive, executable); a truncated or empty ArrayBuffer; a buffer whose magic bytes were corrupted; wrong file dropped into the recipe.","commonSituations":"Operation placed after a decode/gunzip that produced non-image output; feeding a base64 blob that was not yet From Base64 decoded; a SVG (no sniffable magic bytes in the raster sense); an empty input from a previous failed op.","solutions":["Verify the input ArrayBuffer is a complete, valid raster image.","If the data is base64/hex, run From Base64 / From Hex first.","Check for an empty buffer (byteLength === 0) before invoking.","For SVG, rasterise to PNG/JPEG first - Jimp does not read SVG."],"exampleFix":"// before: raw base64 string fed directly\nop.run(base64String, [10, 10]);\n// after: decode to bytes first\nconst buf = fromBase64(base64String).buffer;\nop.run(buf, [10, 10]);","handlingStrategy":"type-guard","validationCode":"import { isImage } from \"../lib/FileType.mjs\";\nfunction assertImageInput(buf) {\n  if (!isImage(buf)) throw new Error('Input is not a recognised image type');\n}","typeGuard":"function isImageInput(buf) {\n  return buf instanceof ArrayBuffer ? isImage(new Uint8Array(buf)) : !!isImage(buf);\n}","tryCatchPattern":"try {\n  result = await brightness.run(buf, [b, c]);\n} catch (e) {\n  if (e instanceof OperationError && /Invalid file type/.test(e.message)) {\n    // not an image - skip or convert first\n    return null;\n  }\n  throw e;\n}","preventionTips":["Decode base64/hex input to bytes before invoking.","Reject empty buffers (byteLength === 0).","Rasterise SVG/PDF to PNG/JPEG first."],"tags":["image","jimp","file-type","magic-bytes","argument-validation"],"backgroundTag":null,"analyzedSha":"4290ea753912378913b1f3f54e0fc5720afeda5d","analyzedAt":"2026-08-13T06:05:50.210Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}