{"record":{"id":"b7d4c03448b23c26","repo":"mozilla/pdf.js","slug":"invalid-crypt-filter-name","errorCode":null,"errorMessage":"Invalid crypt filter name.","messagePattern":"Invalid crypt filter name\\.","errorType":"exception","errorClass":"FormatError","httpStatus":null,"severity":"error","filePath":"src/core/crypto.js","lineNumber":1287,"sourceCode":"      password\n    );\n    this.encryptionKey = transform.encryptionKey;\n  }\n\n  /**\n   * @param {number} num\n   *   Object number.\n   * @param {number} gen\n   *   Generation number.\n   * @returns {CipherTransform}\n   *   Cipher transform.\n   */\n  createCipherTransform(num, gen) {\n    if (this.algorithm === 4 || this.algorithm === 5) {\n      /** @type {ResolveCipher} */\n      const resolveCipher = filterName => {\n        if (!(filterName instanceof Name)) {\n          throw new FormatError(\"Invalid crypt filter name.\");\n        }\n        const cryptFilter = this.cf.get(filterName.name);\n        const cfm = cryptFilter?.get(\"CFM\");\n\n        if (!cfm || cfm.name === \"None\") {\n          return NullCipher;\n        }\n        if (!this.encryptionKey) {\n          throw new PasswordException(\n            \"No password given\",\n            PasswordResponses.NEED_PASSWORD\n          );\n        }\n        if (this.algorithm === 5 || cfm.name === \"AESV3\") {\n          // V=5 always uses 256-bit AES with the file encryption key, even\n          // when a producer wrongly sets the crypt filter's CFM to AESV2\n          // (bug 2046659).\n          return AES256Cipher.bind(null, this.encryptionKey);","sourceCodeStart":1269,"sourceCodeEnd":1305,"githubUrl":"https://github.com/mozilla/pdf.js/blob/5903d58d58e4dd9ce6ffa3834aea8480f06b4ada/src/core/crypto.js#L1269-L1305","documentation":"FormatError thrown inside the per-object cipher resolver (used for V=4/V=5 documents) when the crypt filter name passed in is not a PDF Name object. The StmF/StrF entries in the Encrypt dict must reference crypt filters by Name; if they resolve to something else (string, number, null), the resolver cannot look up the filter.","triggerScenarios":"A V=4/V=5 Encrypt dict whose StmF or StrF entry is a string literal or other non-Name type; an indirect reference that resolved to a non-Name; a malformed CF lookup triggered when decrypting a stream or string object.","commonSituations":"Buggy producers that emit StmF as a string instead of a name; corrupt Encrypt dict; rarely hit because most producers emit Names correctly.","solutions":["Re-save the PDF with a conformant producer so StmF/StrF are Names.","If you must handle such files, pre-process the Encrypt dict to coerce string-valued StmF/StrF to Names (advanced, requires xref access).","Surface a 'corrupt crypt filter configuration' message to the user."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  const doc = await getDocument({ url }).promise;\n} catch (e) {\n  if (e.name === 'FormatError' && e.message === 'Invalid crypt filter name.') {\n    notifyUser('The PDF has a corrupt crypt filter configuration and cannot be opened.');\n    return;\n  }\n  throw e;\n}","preventionTips":["Repair Encrypt dict with qpdf before serving.","Validate that StmF/StrF are PDF Names if you do low-level dict inspection.","Reject malformed encryption configs at ingestion."],"tags":["encryption","pdf-security","format-error","crypt-filter"],"backgroundTag":null,"analyzedSha":"5903d58d58e4dd9ce6ffa3834aea8480f06b4ada","analyzedAt":"2026-08-13T02:28:27.364Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}