Skip to main content
Vulnerability Database/CVE-2025-47934

CVE-2025-47934: OpenPGP.js Auth Bypass Vulnerability

CVE-2025-47934 is an authentication bypass flaw in OpenPGP.js that allows attackers to spoof signature verifications on inline-signed and signed-encrypted messages. This post covers technical details, affected versions, and mitigation.

Updated:

CVE-2025-47934 Overview

CVE-2025-47934 is a signature verification spoofing vulnerability in OpenPGP.js, a JavaScript implementation of the OpenPGP protocol. The flaw allows attackers to craft maliciously modified messages that pass signature verification while containing data that was never actually signed. This enables complete forgery of inline-signed messages and signed-and-encrypted messages, undermining the fundamental integrity guarantees that cryptographic signatures are designed to provide.

Critical Impact

Attackers can spoof signature verifications, causing openpgp.verify and openpgp.decrypt to return valid verification results for data that was never legitimately signed, enabling complete message forgery.

Affected Products

  • OpenPGP.js versions 5.0.1 through 5.11.2
  • OpenPGP.js versions 6.0.0 through 6.1.0
  • Applications using openpgp.verify for inline-signed message verification
  • Applications using openpgp.decrypt with verificationKeys for signed-and-encrypted messages

Discovery Timeline

  • 2025-05-19 - CVE-2025-47934 published to NVD
  • 2025-05-21 - Last updated in NVD database

Technical Details for CVE-2025-47934

Vulnerability Analysis

This vulnerability represents a critical flaw in the cryptographic message verification pipeline of OpenPGP.js. The library's openpgp.verify and openpgp.decrypt functions can be manipulated to return data that differs from what was originally signed while still reporting a valid signature verification result. This breaks the fundamental non-repudiation and integrity properties that digital signatures are meant to guarantee.

The attack requires the adversary to possess a single valid message signature (either inline or detached) along with the plaintext data that was legitimately signed. With these components, an attacker can construct a new inline-signed message or signed-and-encrypted message containing arbitrary data of their choosing. The affected OpenPGP.js functions will incorrectly validate these forged messages as legitimately signed.

Detached signature verifications are not affected by this vulnerability since no signed data is returned in that verification mode.

Root Cause

The root cause is classified as CWE-347: Improper Verification of Cryptographic Signature. The vulnerability stems from improper message mutation during the signature verification process. The original code directly mutated the message packets object (msg.packets) during stream processing, which allowed the returned data to become desynchronized from the data that was actually verified by the cryptographic signature.

The vulnerable code pushed packets directly to msg.packets using msg.packets.push(...), which modified the original message object. This mutation created a window where the signature verification could be performed against one set of data while the function returned different data to the caller.

Attack Vector

The attack is network-accessible and requires no authentication or user interaction. An attacker with knowledge of a valid signature and its corresponding signed plaintext can:

  1. Obtain a legitimate inline-signed or detached signature along with the original signed data
  2. Construct a new message containing attacker-controlled content
  3. Package the malicious content with the valid signature in a way that exploits the verification desynchronization
  4. Submit the crafted message to an application using vulnerable OpenPGP.js versions
  5. The application's verification returns success while exposing the attacker's forged data

The security patch addresses this by creating an immutable copy of the packets during verification:

javascript
// Security patch in src/message.js - Don't mutate message during verification
     if (literalDataList.length !== 1) {
       throw new Error('Can only verify message with one literal data packet.');
     }
-    if (stream.isArrayStream(msg.packets.stream)) {
-      msg.packets.push(...await stream.readToEnd(msg.packets.stream, _ => _ || []));
+    let packets = msg.packets;
+    if (stream.isArrayStream(packets.stream)) {
+      packets = packets.concat(await streamReadToEnd(packets.stream, _ => _ || []));
     }
-    const onePassSigList = msg.packets.filterByTag(enums.packet.onePassSignature).reverse();
-    const signatureList = msg.packets.filterByTag(enums.packet.signature);
-    if (onePassSigList.length && !signatureList.length && util.isStream(msg.packets.stream) && !stream.isArrayStream(msg.packets.stream)) {
+    const onePassSigList = packets.filterByTag(enums.packet.onePassSignature).reverse();
+    const signatureList = packets.filterByTag(enums.packet.signature);
+    if (onePassSigList.length && !signatureList.length && util.isStream(packets.stream) && !isArrayStream(packets.stream)) {
       await Promise.all(onePassSigList.map(async onePassSig => {
         onePassSig.correspondingSig = new Promise((resolve, reject) => {
           onePassSig.correspondingSigResolve = resolve;

Source: GitHub Commit 43f5f4e

Detect Identity Attacks the Moment Authentication Fails

Singularity™ Identity surfaces credential misuse, lateral movement, and privilege escalation in real time, so you can contain the breach before it spreads.

Stop Identity Attacks

Detection Methods for CVE-2025-47934

Indicators of Compromise

  • Messages passing signature verification where the extracted content differs from expected signed data
  • Unusual patterns in inline-signed messages with mismatched literal data packets
  • Applications accepting signed messages from untrusted sources that exhibit unexpected content
  • Cryptographic verification logs showing successful validations for messages with anomalous packet structures

Detection Strategies

  • Audit application dependencies for OpenPGP.js versions between 5.0.1 and 5.11.2 or 6.0.0 and 6.1.0
  • Implement secondary verification by manually extracting and re-verifying signatures using detached verification mode
  • Monitor for discrepancies between signed message content and expected payload formats
  • Review application logs for patterns indicating message tampering or unexpected signature verification successes

Monitoring Recommendations

  • Enable verbose logging for OpenPGP.js signature verification operations in production environments
  • Implement application-level integrity checks that validate message content against expected schemas or formats after signature verification
  • Monitor package manager update notifications for OpenPGP.js security releases
  • Consider implementing canary messages to detect signature verification tampering in high-security environments

How to Mitigate CVE-2025-47934

Immediate Actions Required

  • Upgrade OpenPGP.js to version 5.11.3 or 6.1.1 immediately
  • Audit all applications using openpgp.verify with inline-signed messages for potential compromise
  • Review applications using openpgp.decrypt with verificationKeys parameter
  • Implement the workarounds described below if immediate patching is not possible

Patch Information

Security patches are available in OpenPGP.js versions 5.11.3 and 6.1.1. The fix ensures that message packets are not mutated during verification by using immutable copies. Organizations should update to these versions through their package management systems. The patches are available via:

For additional technical details, refer to the GitHub Security Advisory GHSA-8qff-qr5q-5pr8.

Workarounds

  • For inline-signed messages: Extract the message and signature(s) from the message returned by openpgp.readMessage, then verify each signature as a detached signature by passing it along with a new message created using openpgp.createMessage containing only the data to openpgp.verify
  • For signed-and-encrypted messages: Perform decryption and verification as two separate steps by first calling openpgp.decrypt without the verificationKeys parameter, then passing the returned signature(s) and a new message containing the decrypted data (created via openpgp.createMessage) to openpgp.verify
  • Consider temporarily blocking acceptance of inline-signed messages from untrusted sources until patching is complete
  • Implement application-level content validation as a defense-in-depth measure
bash
# Update OpenPGP.js via npm
npm update openpgp@5.11.3
# or for version 6.x
npm update openpgp@6.1.1

# Verify installed version
npm list openpgp

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.