Skip to content

fix(ext/node): prevent cipher operations after finalize#31533

Merged
littledivy merged 2 commits intodenoland:mainfrom
littledivy:fix-cipher-
Dec 9, 2025
Merged

fix(ext/node): prevent cipher operations after finalize#31533
littledivy merged 2 commits intodenoland:mainfrom
littledivy:fix-cipher-

Conversation

@littledivy
Copy link
Copy Markdown
Member

@littledivy littledivy commented Dec 8, 2025

Throw a state error for operations if the cipher is already finalized.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Dec 8, 2025

Walkthrough

The PR modifies the Cipheriv and Decipheriv classes to track finalization state and prevent further operations after completion. A private #finalized flag is introduced, initialized to false and set to true when final() completes. Subsequent calls to update() or final() on a finalized instance throw ERR_CRYPTO_INVALID_STATE errors. Unit tests are added to validate this lockdown behavior for both cipher and decipher workflows.

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Title check ✅ Passed The title accurately describes the main change: preventing cipher operations after finalization by adding state guards to Cipheriv and Decipheriv classes.
Description check ✅ Passed The description directly relates to the changeset by explaining the core purpose of preventing cipher operations after finalization.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
ext/node/polyfills/internal/crypto/cipher.ts (1)

187-258: Finalization guards are good; consider treating any final() attempt as terminal

The #finalized flag plus the new checks in final() and update() for both Cipheriv and Decipheriv correctly prevent normal “double final” and “update after final” misuse, and the tests exercise the happy‑path finalize‑then‑reuse scenario well.

One thing to double‑check: #finalized is only flipped to true on the explicit success paths. If op_node_cipheriv_final / op_node_decipheriv_final (or subsequent checks like the Invalid final block size branch in Decipheriv.final()) throw, the instance remains non‑finalized and callers can still invoke update()/final() on an object whose native context may already have been advanced or errored.

It might be safer and clearer to treat any final() attempt as terminal for the instance (success or failure), for example by setting #finalized = true in a finally block around the native *_final call or just before throwing in the “invalid block size” path, and adding a test that update()/final() after a failing final() also yields ERR_CRYPTO_INVALID_STATE. That would fully enforce the “no further operations after finalization attempt” invariant and avoid accidental reuse of a potentially inconsistent context.

Also applies to: 287-295, 417-418, 454-457, 471-472, 479-480, 509-516

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a15cafe and 8a65237.

📒 Files selected for processing (2)
  • ext/node/polyfills/internal/crypto/cipher.ts (9 hunks)
  • tests/unit_node/crypto/crypto_cipher_test.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx,js}: For JavaScript runtime debugging, enable V8 inspector with --inspect-brk flag and connect Chrome DevTools to chrome://inspect
Use console.log() for debug prints in JavaScript runtime code

Files:

  • ext/node/polyfills/internal/crypto/cipher.ts
  • tests/unit_node/crypto/crypto_cipher_test.ts
🧬 Code graph analysis (1)
ext/node/polyfills/internal/crypto/cipher.ts (1)
ext/node/polyfills/internal/errors.ts (1)
  • ERR_CRYPTO_INVALID_STATE (1043-1047)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
  • GitHub Check: bench release linux-x86_64
  • GitHub Check: test release linux-x86_64
  • GitHub Check: test debug linux-aarch64
  • GitHub Check: test debug macos-aarch64
  • GitHub Check: test debug linux-x86_64
  • GitHub Check: test debug windows-x86_64
  • GitHub Check: build libs
  • GitHub Check: lint debug windows-x86_64
  • GitHub Check: lint debug linux-x86_64
🔇 Additional comments (1)
tests/unit_node/crypto/crypto_cipher_test.ts (1)

596-656: New cipher/decipher lockdown tests look solid

These tests exercise both update() and final() after a successful final() on cipher and decipher, and validate the expected Invalid state for operation ... messages. They’re focused, deterministic, and clearly document the new lifecycle guarantees.

Copy link
Copy Markdown
Member

@bartlomieju bartlomieju left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, please update the description before landing.

@littledivy littledivy changed the title fix(ext/node): prevent cipher double finalize fix(ext/node): prevent cipher operations after finalize Dec 9, 2025
@littledivy littledivy merged commit 0bc213b into denoland:main Dec 9, 2025
35 of 39 checks passed
@Mic92
Copy link
Copy Markdown

Mic92 commented Jan 17, 2026

Will this bug also get backported to 2.5.x? According to https://docs.deno.com/runtime/fundamentals/stability_and_releases/ it's still a supported LTS release.

Mic92 pushed a commit to Mic92/deno that referenced this pull request Jan 17, 2026
Throw a state error for operations if the cipher is already finalized.
github-merge-queue Bot pushed a commit to NixOS/nixpkgs that referenced this pull request Jan 18, 2026
Backport upstream fix to prevent cipher operations after finalize.
This fixes a vulnerability where node:crypto doesn't finalize cipher,
allowing infinite encryptions which could enable brute forcing attacks.

Upstream fix: denoland/deno#31533
Security advisory: GHSA-5379-f5hf-w38v
bartlomieju pushed a commit that referenced this pull request Jan 22, 2026
Throw a state error for operations if the cipher is already finalized.
bartlomieju pushed a commit to bartlomieju/deno that referenced this pull request Jan 26, 2026
Throw a state error for operations if the cipher is already finalized.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants