Environments
LibPDF version: 0.4.0
Node version: v24.11.1
Minimal reproduction
import { PDF } from "@libpdf/core";
// `encryptedBytes` is a PDF encrypted with a known user password
const pdf = await PDF.load(encryptedBytes, {
credentials: { password: "WRONG_PASSWORD" },
});
console.log(pdf.isAuthenticated); // false
pdf.removeProtection(); // does not throw
const bytes = await pdf.save();
// The saved file no longer has an /Encrypt dictionary, but its content
// streams are still ciphertext — the resulting PDF is unreadable garbage.
Expected behavior
Per the method's own doc comment (@throws {PermissionDeniedError}), calling removeProtection() on a PDF instance that isn't authenticated (isAuthenticated === false) should throw.
Actual behavior
No error is thrown. The /Encrypt dictionary is removed from the trailer (so the file looks unencrypted), but the page content streams are never actually decrypted, since the correct key was never derived. The result is a PDF that "succeeds" but is silently corrupt — the same symptom occurs whenever credentials are simply missing, not just wrong.
Environments
LibPDF version: 0.4.0
Node version: v24.11.1
Minimal reproduction
Expected behavior
Per the method's own doc comment (@throws {PermissionDeniedError}), calling removeProtection() on a PDF instance that isn't authenticated (isAuthenticated === false) should throw.
Actual behavior
No error is thrown. The /Encrypt dictionary is removed from the trailer (so the file looks unencrypted), but the page content streams are never actually decrypted, since the correct key was never derived. The result is a PDF that "succeeds" but is silently corrupt — the same symptom occurs whenever credentials are simply missing, not just wrong.