{"record":{"id":"44756b6ebfcc8658","repo":"gchq/CyberChef","slug":"unhandled-charset","errorCode":null,"errorMessage":"Unhandled Charset","messagePattern":"Unhandled Charset","errorType":"exception","errorClass":"OperationError","httpStatus":null,"severity":"error","filePath":"src/core/operations/MIMEDecoding.mjs","lineNumber":137,"sourceCode":"     *\n     * @param encodedWord\n     */\n    convertFromCharset(charset, encodedText) {\n        charset = charset.toLowerCase();\n        const parsedCharset = charset.split(\"-\");\n\n        if (parsedCharset.length === 2 && parsedCharset[0] === \"utf\" && charset === \"utf-8\") {\n            return cptable.utils.decode(65001, encodedText);\n        } else if (parsedCharset.length === 2 && charset === \"us-ascii\") {\n            return cptable.utils.decode(20127, encodedText);\n        } else if (parsedCharset.length === 3 && parsedCharset[0] === \"iso\" && parsedCharset[1] === \"8859\") {\n            const isoCharset = parseInt(parsedCharset[2], 10);\n            if (isoCharset >= 1 && isoCharset <= 16) {\n                return cptable.utils.decode(28590 + isoCharset, encodedText);\n            }\n        }\n\n        throw new OperationError(\"Unhandled Charset\");\n    }\n\n    /**\n     * Parses a Q encoded word\n     *\n     * @param encodedWord\n     */\n    parseQEncodedWord(encodedWord) {\n        let decodedWord = \"\";\n        for (let i = 0; i < encodedWord.length; i++) {\n            if (encodedWord[i] === \"_\") {\n                decodedWord += \" \";\n            // Parse hex encoding\n            } else if (encodedWord[i] === \"=\") {\n                if ((i + 2) >= encodedWord.length) throw new OperationError(\"Incorrectly Encoded Word\");\n                const decodedHex = Utils.byteArrayToChars(fromHex(encodedWord.substring(i + 1, i + 3)));\n                decodedWord += decodedHex;\n                i += 2;","sourceCodeStart":119,"sourceCodeEnd":155,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/operations/MIMEDecoding.mjs#L119-L155","documentation":"Thrown by the MIME Decoding operation when an RFC 2047 encoded word specifies a charset that convertFromCharset() does not support. Only UTF-8, US-ASCII, and ISO-8859-1 through ISO-8859-16 are handled; any other charset token (or an ISO-8859 part number outside 1–16) reaches the final throw at MIMEDecoding.mjs:137. The charset string is lower-cased and split on '-' before matching.","triggerScenarios":"Decoding a MIME header whose encoded word uses an unsupported charset, e.g. =?windows-1252?Q?...?=, =?ISO-8859-17?Q?...?= (part 17 is out of range), =?Shift_JIS?B?...?=, =?KOI8-R?Q?...?=. Raised at MIMEDecoding.mjs:137 inside convertFromCharset, called from decodeHeaders.","commonSituations":"Mail from Windows clients using windows-1252; Asian-language headers (ISO-2022-JP, Shift_JIS, EUC-KR); Russian/Eastern-European charsets (KOI8-R, CP1251); an ISO-8859 variant beyond part 16.","solutions":["Pre-convert the header to a supported charset (UTF-8, US-ASCII, or ISO-8859-1..16) before feeding it to MIME Decoding.","If you only need the raw bytes, strip the charset from the encoded-word marker or use a different decoding operation.","For windows-1252 content, map it to the closest ISO-8859-1 token (lossy for the 0x80-0x9F range) or decode it manually.","Request charset support be added, or fall back to an external library for unsupported charsets."],"exampleFix":"// before — unsupported charset in header\n// =?windows-1252?Q?Test=92s?=\nmimeDecoding.run(bytes, []);   // throws 'Unhandled Charset'\n\n// after — normalise charset to a supported one first\nconst text = Utils.byteArrayToUtf8(bytes)\n  .replace(/=\\?windows-1252\\?/gi, '=?ISO-8859-1?');\nmimeDecoding.run(Utils.strToByteArray(text), []);","handlingStrategy":"fallback","validationCode":"const SUPPORTED = /^utf-8$|^us-ascii$|^iso-8859-(1[0-6]|[1-9])$/i;\nfunction supportedCharset(cs) {\n  return SUPPORTED.test(String(cs).toLowerCase().trim());\n}\n// before decoding, normalise or reject unsupported charsets\nif (!supportedCharset(charset)) {\n  // e.g. rewrite windows-1252 -> ISO-8859-1, or skip the encoded word\n}","typeGuard":"const SUPPORTED_CHARSET = /^utf-8$|^us-ascii$|^iso-8859-(1[0-6]|[1-9])$/i;\nfunction isSupportedCharset(v: unknown): v is string {\n  return typeof v === 'string' && SUPPORTED_CHARSET.test(v.toLowerCase().trim());\n}","tryCatchPattern":"try {\n  mimeDecoding.run(bytes, []);\n} catch (e) {\n  if (e instanceof OperationError && /Unhandled Charset/.test(e.message)) {\n    // fall back: normalise charset to ISO-8859-1/UTF-8 and retry, or return raw text\n  } else throw e;\n}","preventionTips":["Pre-rewrite uncommon charsets (windows-1252, KOI8-R, Shift_JIS) to UTF-8 before decoding.","Detect unsupported encoded-words and strip or replace them.","Maintain a charset allow-list matching the op's coverage (UTF-8, US-ASCII, ISO-8859-1..16)."],"tags":["mime","rfc2047","charset","validation","encoding"],"backgroundTag":null,"analyzedSha":"4290ea753912378913b1f3f54e0fc5720afeda5d","analyzedAt":"2026-08-13T06:05:50.210Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}