{"record":{"id":"d1a0f6404e109bd9","repo":"gchq/CyberChef","slug":"letter-letter-is-not-in-the-key","errorCode":null,"errorMessage":"Letter ${letter} is not in the key","messagePattern":"Letter (.+?) is not in the key","errorType":"exception","errorClass":"OperationError","httpStatus":null,"severity":"error","filePath":"src/core/lib/LS47.mjs","lineNumber":123,"sourceCode":"            throw new OperationError(\"Letter \" + elem + \" not in LS47\");\n        counts[elem]++;\n        if (counts[elem] > 1)\n            throw new OperationError(\"Letter duplicated in the key\");\n    }\n}\n\n/**\n * Finds the position of a letter in they key.\n *\n * @param {letter} key\n * @param {string} letter\n * @returns {object}\n */\nfunction findPos (key, letter) {\n    const index = key.indexOf(letter);\n    if (index >= 0 && index < 49)\n        return [Math.floor(index/7), index%7];\n    throw new OperationError(\"Letter \" + letter + \" is not in the key\");\n}\n\n/**\n * Returns the character at the position on the tiles.\n *\n * @param {string} key\n * @param {object} coord\n * @returns {string}\n */\nfunction findAtPos(key, coord) {\n    return key.charAt(coord[1] + (coord[0] * 7));\n}\n\n/**\n * Returns new position by adding two positions.\n *\n * @param {object} a\n * @param {object} b","sourceCodeStart":105,"sourceCodeEnd":141,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/lib/LS47.mjs#L105-L141","documentation":"findPos(key, letter) maps a plaintext/ciphertext character to a [row, col] coordinate on the 7x7 key tile grid. If the character is not present in the key string (indexOf === -1) or the index is out of the 0..48 range, it throws. Because the valid key is a permutation of the LS47 alphabet, this effectively rejects any input character outside \"_abcdefghijklmnopqrstuvwxyz.0123456789,-+*/:?!'()\".","triggerScenarios":"Calling encrypt(key, plaintext) with a plaintext containing uppercase letters, '@', newlines, or any char not in the 49-char alphabet. Calling decrypt(key, ciphertext) with a ciphertext containing such a char (typically because the ciphertext was corrupted or the wrong key was used to partially decode).","commonSituations":"User feeds raw prose containing spaces or uppercase letters directly to encrypt(); input not lowercased/normalized; ciphertext mangled by transport (URL-decoding, copy-paste through formatting); wrong operation chained before LS47 decrypt.","solutions":["Sanitize input to only LS47-alphabet characters before encrypting: input.replace(/[^_a-z0-9.,\\-+*/:?!'()]/g, '').","Lowercase any alphabetic input and substitute or strip unsupported punctuation.","Verify the ciphertext comes from the same LS47 alphabet before calling decrypt.","Confirm you are using the correct key and that the ciphertext was not transformed by another operation."],"exampleFix":"// before\nconst ct = LS47.encrypt(key, \"Hello World\"); // 'H',' ','W' not in alphabet\n\n// after\nconst clean = plaintext.toLowerCase().replace(/[^_a-z0-9.,\\-+*/:?!'()]/g, '');\nconst ct = LS47.encrypt(key, clean);","handlingStrategy":"validation","validationCode":"const LS47_ALPHABET = \"_abcdefghijklmnopqrstuvwxyz.0123456789,-+*/:?!'()\";\n\nfunction sanitizeLS47Input(s) {\n  return s.toLowerCase().replace(/[^_a-z0-9.,\\-+*/:?!'()]/g, '');\n}\n\nconst clean = sanitizeLS47Input(plaintext);\nconst ct = LS47.encrypt(key, clean);","typeGuard":"function isLS47AlphabetString(x): x is string {\n  const A = \"_abcdefghijklmnopqrstuvwxyz.0123456789,-+*/:?!'()\";\n  return typeof x === 'string' && [...x].every(c => A.includes(c));\n}","tryCatchPattern":"try {\n  return LS47.encrypt(key, plaintext);\n} catch (e) {\n  if (e instanceof OperationError && /is not in the key/.test(e.message)) {\n    throw new Error('Input contains a character outside the LS47 alphabet: ' + e.message);\n  }\n  throw e;\n}","preventionTips":["Lowercase and strip non-alphabet characters from input before encrypting.","Verify ciphertext integrity and alphabet before decrypting.","Chain a 'Remove non-alphabet chars' or 'Replace' operation in CyberChef before LS47 encrypt.","Confirm the upstream operation produced LS47-alphabet output."],"tags":["cryptography","ls47","validation","user-input"],"backgroundTag":null,"analyzedSha":"4290ea753912378913b1f3f54e0fc5720afeda5d","analyzedAt":"2026-08-13T06:05:50.210Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}