parallax/jsPDF · error · Error

Invalid permission: " + perm

Error message

Invalid permission: " + perm

What it means

Intended to fire inside PDFSecurity when a permission string passed in the permissions array is not one of the recognized keys (print, modify, copy, annot-forms). NOTE: the guard is buggy -- it checks `typeof permissionOptions.perm` (a literal property 'perm' that never exists) instead of `permissionOptions[perm]`, so this branch is effectively dead code and the throw is unreachable. An invalid permission instead silently makes protection become NaN via `protection += permissionOptions[perm]` (undefined), corrupting the P flag without any error.

Source

Thrown at src/libs/pdfsecurity.js:44

 * @name constructor
 * @function
 * @param {Array} permissions Permissions allowed for user, "print", "modify", "copy" and "annot-forms".
 * @param {String} userPassword Permissions apply to this user. Leaving this empty means the document
 *                              is not password protected but viewer has the above permissions.
 * @param {String} ownerPassword Owner has full functionalities to the file.
 * @param {String} fileId As hex string, should be same as the file ID in the trailer.
 * @example
 * var security = new PDFSecurity(["print"])
 */
function PDFSecurity(permissions, userPassword, ownerPassword, fileId) {
  this.v = 1; // algorithm 1, future work can add in more recent encryption schemes
  this.r = 2; // revision 2

  // set flags for what functionalities the user can access
  let protection = 192;
  permissions.forEach(function(perm) {
    if (typeof permissionOptions.perm !== "undefined") {
      throw new Error("Invalid permission: " + perm);
    }
    protection += permissionOptions[perm];
  });

  // padding is used to pad the passwords to 32 bytes, also is hashed and stored in the final PDF
  this.padding =
    "\x28\xBF\x4E\x5E\x4E\x75\x8A\x41\x64\x00\x4E\x56\xFF\xFA\x01\x08" +
    "\x2E\x2E\x00\xB6\xD0\x68\x3E\x80\x2F\x0C\xA9\xFE\x64\x53\x69\x7A";
  let paddedUserPassword = (userPassword + this.padding).substr(0, 32);
  let paddedOwnerPassword = (ownerPassword + this.padding).substr(0, 32);

  this.O = this.processOwnerPassword(paddedUserPassword, paddedOwnerPassword);
  this.P = -((protection ^ 255) + 1);
  this.encryptionKey = md5Bin(
    paddedUserPassword +
      this.O +
      this.lsbFirstWord(this.P) +
      this.hexToBytes(fileId)

View on GitHub (pinned to a3930ce03a)

Solutions

  1. Restrict the permissions array to exactly the four valid keys: 'print', 'modify', 'copy', 'annot-forms'.
  2. Validate/whitelist the array before constructing PDFSecurity and drop unknown entries.
  3. Be aware the library's own guard does not catch typos (bug), so do not rely on it -- add your own check.

Example fix

// before
new PDFSecurity(['print', 'editing'], userPwd, ownerPwd, fileId); // 'editing' invalid

// after
var ALLOWED = ['print', 'modify', 'copy', 'annot-forms'];
var perms = ['print', 'editing'].filter(function(p){ return ALLOWED.indexOf(p) !== -1; });
new PDFSecurity(perms, userPwd, ownerPwd, fileId);
Defensive patterns

Strategy: validation

Validate before calling

var ALLOWED = ['print', 'modify', 'copy', 'annot-forms'];
var valid = permissions.filter(function(p){ return ALLOWED.indexOf(p) !== -1; });
if (valid.length !== permissions.length) {
  throw new Error('Unknown permission in ' + JSON.stringify(permissions));
}
new PDFSecurity(valid, userPassword, ownerPassword, fileId);

Type guard

function isValidPermission(p) {
  return ['print','modify','copy','annot-forms'].indexOf(p) !== -1;
}

Try / catch

try {
  security = new PDFSecurity(permissions, userPwd, ownerPwd, fileId);
  if (isNaN(security.P)) throw new Error('Permissions produced invalid P flag (bad permission string)');
} catch (e) {
  if (/Invalid permission/.test(e.message)) { /* filter and retry */ }
  else throw e;
}

Prevention

When it happens

Trigger: Constructing `new PDFSecurity(permissions, userPassword, ownerPassword, fileId)` with a typo'd or unknown permission such as 'editing', 'annotations', 'extract'. Because of the bug you will NOT see this error; you will get a broken /P value. This analysis describes the intended trigger.

Common situations: Enabling PDF encryption via jsPDF's encryption option and passing a wrong permission label; copying permission names from another library's API (e.g. pdfkit uses different strings).

Related errors


AI-assisted analysis of parallax/jsPDF@a3930ce03a (2026-08-13). Data as JSON: /api/errors/98353073a8834644. Report an issue: GitHub.