Skip to content

RSA PKCS#1 v1.5 signature forgery via garbage in DigestAlgorithm (incomplete CVE-2026-33894 fix) #1149

Closed

Description

@geo-chen

reported via email on 4 June 2026 - no response.

The CVE-2026-33894 fix (af094e6) is incomplete. It only checks the top-level DigestInfo element count:

lib/rsa.js:1174 if(!asn1.validate(obj, digestInfoValidator, capture, errors) || obj.value.length !== 2) { ... }

The nested DigestAlgorithm SEQUENCE has no element-count check, and asn1.validate ignores extra children. An attacker can stuff garbage bytes inside DigestAlgorithm; node-forge still accepts the DigestInfo and captures the attacker's digest. Because _parseAllDigestBytes defaults to true, trailing garbage is blocked, but garbage inside the structure is not.

I confirmed the parser gap on 1.4.0 (a DigestAlgorithm with [OID, NULL, garbage] validates, top-level length stays 2, attacker digest captured), and then forged a working signature end to end on an e=3 key with no private key:

node-forge version: 1.4.0
pub.verify(forged) => true (message "forged-by-attacker-no-privkey")
control (forged sig vs different message) => false

The forgery uses the standard low-exponent technique: the 32-byte digest is fixed at the bottom of the block, the ASN.1/padding framing at the top, and ~314 free "garbage" bytes inside DigestAlgorithm absorb the middle of S^3 so that S^3 is an exact cube matching a block node-forge accepts.

Suggested fix: require the DigestAlgorithm AlgorithmIdentifier SEQUENCE to contain exactly the OID plus optional NULL (add a nested value.length check), or make asn1.validate reject unconsumed children. Validating element counts at every nesting level (not just the outer SEQUENCE) closes the remaining slack.

Activity

  1. andyedwardsibm commented on Sep 17, 2026

    @andyedwardsibm

    This has been assigned CVE-2026-85393

  2. atulkumar2381-cmd commented on Sep 30, 2026

    @atulkumar2381-cmd

    Hi Team - My Product also affected by CVE-2026-85393 and I need an updated version as soon as possible for the same.

  3. hardass commented on Oct 3, 2026

    @hardass

    Downstream reachability note — there is no patched release to move to:

    pi-sandbox 0.6.9                       (npm, latest)
      └─ @carderne/sandbox-runtime 0.0.73  (latest)
           └─ node-forge 1.4.0             (latest — advisory covers *)
    

    npm audit in any consumer of pi-sandbox reports this as high, and npm audit fix --force can only "resolve" it by downgrading pi-sandbox 0.6.9 → 0.4.4, which is a breaking change. So dependents have no non-destructive path until a fix actually lands; the advisory being open against * means the audit finding is un-actionable rather than merely unfixed.

    For what it's worth, this particular consumer is not exploitable: sandbox-runtime reaches node-forge only for signing and certificate construction (forgeKey.sign, the leaf/CRL builders in mitm-ca and mitm-leaf) and makes no verify calls anywhere in dist, so the PKCS#1 v1.5 verification path this advisory describes is never executed. The cost here is the stuck advisory, not live risk.

    Worth flagging since it may shape the release priority: the community's ability to pick up a fix depends on it reaching npm, and 1.4.0 is already the newest version published there.

  4. pranjal-yadav05 commented on Oct 12, 2026

    @pranjal-yadav05

    Hi maintainers,

    Are there any updates on the fix for CVE-2026-85393 (GHSA-86w9-cpqp-85rv)?

    The proposed fix in PR #1152 appears to address the issue, but the PR is still open and no patched npm release is available. This vulnerability is affecting dependency security checks in downstream projects.

    Could you share an estimated timeline for reviewing and merging the fix, and publishing a patched release?

    Thanks for maintaining the project.

  5. gabradohub commented on Oct 23, 2026

    @gabradohub

    Hello maintainers,

    Could you share the supported remediation path for GHSA-86w9-cpqp-85rv / CVE-2026-85393 affecting [email protected]?

    Our Expo SDK 57 mobile application uses these dependencies:

    Our mandatory dependency-security checks currently block development acceptance because of this vulnerability.

    We understand that proposed fixes exist in PR #1152 and PR #1158, but no officially patched release has been confirmed.

    Could you please clarify:

    1. Is either proposed PR the intended permanent fix?
    2. When might a patched version become available?
    3. Is there a supported permanent solution for Expo users in the meantime?
    4. Is there an alternative package or configuration that removes the vulnerability without compromising functionality?
    5. Are there any certificate or signing compatibility considerations we should be aware of?

    We prefer an officially supported, permanent solution rather than temporary security exceptions or unsupported patches.

    Thank you for your work on node-forge. We appreciate any guidance you can provide.

  6. gabradohub commented on Oct 23, 2026

    @gabradohub

    Hi maintainers,

    We're experiencing the same vulnerability issue with [email protected], introduced through Expo SDK 57 and its certificate tooling.

    Our mandatory security checks are currently blocking development acceptance.

    In addition to the release timeline requested above, could you advise whether there is a supported permanent workaround specifically for Expo users while PRs #1152 and #1158 remain pending?

    We would prefer to retain Expo rather than migrate our mobile framework or introduce temporary security exceptions.

    Thank you for your guidance.

  7. Binyam-dev commented on Oct 24, 2026

    @Binyam-dev

    We independently validated both proposed fixes on Node 24.21.0:

    The executable RSA fixes are equivalent. We favor retaining #1152's signed regression vector when applying the selected fix to the maintained release base.

    Separately, both candidates still accept nonempty ASN.1 NULL parameter contents. We have not demonstrated an additional forgery exploit from that acceptance; this is extra parser strictness tested by our downstream backport. Adding this small check after the proposed nested-element check makes all 30 of our checks pass, with the same 829 upstream tests passing and 4 pending:

                 obj.value[0].value.length !==
    -              (('parameters' in capture) ? 2 : 1)) {
    +              (('parameters' in capture) ? 2 : 1) ||
    +            ('parameters' in capture && capture.parameters !== '')) {

    Could a maintainer identify the preferred release branch and any remaining validation needed for an official compatible patched npm release? We can provide the independent probes and exact-commit results. We want to retain official dependencies and a strict audit rather than substitute a fork or add an advisory exception.

  8. davidlehn commented on Oct 27, 2026

    @davidlehn
    Member

    Fixed in node-forge 1.4.1. Advisory: GHSA-2g46-22mc-6gwp (CVE-2026-85393). Thank you for the report and the forgery.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions