Skip to content

feat(crypto): add RSA-PSS codemod for DEP0154 - #164

Merged
JakobJingleheimer merged 41 commits into
nodejs:mainfrom
nievasdev:feat/crypto-rsa-pss-update
Oct 8, 2025
Merged

JakobJingleheimer merged 41 commits into
nodejs:mainfrom
nievasdev:feat/crypto-rsa-pss-update

Conversation

@nievasdev

Copy link
Copy Markdown
Contributor

Summary

Add codemod to transform deprecated RSA-PSS crypto options:

  • hash → hashAlgorithm
  • mgf1Hash → mgf1HashAlgorithm

Changes

  • Only transforms crypto.generateKeyPair() and crypto.generateKeyPairSync() calls with 'rsa-pss' key type
  • Supports both direct calls (crypto.generateKeyPair) and destructured imports (generateKeyPair)
  • Comprehensive test coverage for various usage patterns

Test plan

  • Tests pass for basic transformations
  • Tests pass for destructured imports
  • Tests verify non-rsa-pss calls are ignored
  • Lint and type checks pass

Resolves #144

Add codemod to transform deprecated RSA-PSS crypto options:
- hash -> hashAlgorithm
- mgf1Hash -> mgf1HashAlgorithm

Only transforms crypto.generateKeyPair() and crypto.generateKeyPairSync()
calls with 'rsa-pss' key type. Includes comprehensive test coverage
for various usage patterns.

Resolves: nodejs#144
Initial code generated with Claude Code assistance.

Verified functionality through detailed review and testing.

@AugustinMauroy AugustinMauroy left a comment •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

good starting ! But there are missing piece:

  • if user do import * as foo from 'node:crypto'
  • if use do const { generateKeyPair: foo } = require('node:crypto')
    Solution: have this pr merged #151 EDIT it's merged you should use this utility

Also for strictness on parameters analyst you should do something like that:

for (const call of callNode) {
	const optionsMatch = call.getMatch("OPTIONS");
	if (!optionsMatch) continue;

	// Find the object node that contains the URL options
	const objectNode = optionsMatch.find({
		rule: {
			kind: "object"
		}
	});

	if (!objectNode) continue;

	// Find all property pairs in the object
	const pairs = objectNode.findAll({
		rule: {
			kind: "pair"
		}
	});

	// find hash pair then replace it
	pairs.find(pair => {
		const keyNode = pair.find({
				rule: {
					kind: "property_identifier"
				}
			});
		if (!keyNode) return false;

		const key = keyNode.text();
		if (key === "hash") {
			const valueNode = pair.find({
				rule: {
					kind: "string_fragment"
				}
			}) || pair.find({
				rule: {
					kind: "string"
				}
			});

			if (!valueNode) return false;

			const value = valueNode.text().slice(1, -1); // Remove quotes
			const replacement = `hashAlgorithm: '${value}'`;
			edits.push(call.replace(replacement));
			return true;
		}
		return false;
	});
}

Comment thread recipes/crypto-rsa-pss-update/README.md Outdated
Comment thread recipes/crypto-rsa-pss-update/README.md Outdated
  - Add support for namespace imports (import * as crypto)
  - Add support for destructured renamed imports ({generateKeyPair: foo})
  - Implement stricter parameter analysis for hash/mgf1Hash detection
  - Add comprehensive test cases for new import patterns

  Addresses feedback from nodejs#164
@nievasdev

Copy link
Copy Markdown
Contributor Author

Hi @AugustinMauroy, I updated the branch, I would appreciate any feedback, thank you for your attention.

Comment thread recipes/crypto-rsa-pss-update/src/workflow.ts Outdated
Comment thread recipes/crypto-rsa-pss-update/src/workflow.ts Outdated
Comment thread recipes/crypto-rsa-pss-update/src/workflow.ts Outdated
Comment thread recipes/crypto-rsa-pss-update/workflow.yaml
Comment thread recipes/crypto-rsa-pss-update/workflow.yaml
Comment thread recipes/crypto-rsa-pss-update/tests/expected/import-star-as.js
Comment thread recipes/crypto-rsa-pss-update/src/workflow.ts Outdated

@AugustinMauroy AugustinMauroy left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nit

Comment thread recipes/crypto-rsa-pss-update/README.md Outdated
Comment thread recipes/crypto-rsa-pss-update/README.md
Comment thread recipes/crypto-rsa-pss-update/README.md
Comment thread recipes/crypto-rsa-pss-update/README.md
…dingPath utility

  Replace manual namespace import parsing with resolveBindingPath utility for
  cleaner code. This change only affects namespace imports (import * as crypto)
  while maintaining all existing functionality for other import patterns.

  Changes:
  - Import resolveBindingPath from @nodejs/codemod-utils
  - Simplify namespace import handling in getCryptoBindings()
  - Fix TypeScript types for SgRoot<JS> and SgNode<JS> compatibility
  - Maintain backward compatibility and all test coverage
@AugustinMauroy

Copy link
Copy Markdown
Member

this case should be handled

const algo =  'sha256';

crypto.generateKeyPairSync('rsa-pss', {
  modulusLength: 2048,
  mgf1Hash: algo
});

  Fix transformation logic to properly handle both string literals and variable
  references in hash/mgf1Hash properties. Previously only property names were
  replaced, now the entire property is transformed while preserving the value.

  Changes:
  - Replace entire property pair instead of just the key name
  - Support both string literals and identifier variables as values
  - Add test cases for variable value scenarios (variable-value.js)
  - Ensure backward compatibility with existing string literal cases

  Fixes case where mgf1Hash: algo was not being transformed to mgf1HashAlgorithm: algo
@nievasdev

Copy link
Copy Markdown
Contributor Author

@AugustinMauroy @brunocroh thanks for you feedback, I did the changes witch you ask for,
Sorry for the delay, I had to be away for a while.

nievasdev and others added 3 commits August 13, 2025 13:17
… utility

  Replace manual import pattern parsing (~107 lines) with resolveBindingPath calls (~22 lines).
  This approach handles all import patterns (namespace, named, aliased, require) uniformly
  and improves maintainability as new patterns are automatically supported by the utility.
…suite

  - Add template_string support in workflow.ts for template literals
  - Add test cases for template literals, spread operators, nested objects
  - Consolidate and optimize test suite
  - Remove redundant tests and improve coverage
@AugustinMauroy
AugustinMauroy marked this pull request as ready for review August 14, 2025 07:24
Comment thread recipes/crypto-rsa-pss-update/package.json Outdated
Comment thread recipes/crypto-rsa-pss-update/src/workflow.ts Outdated
subdivision of the main code into another auxiliary function to facilitate its reading
- Merge import-aliases.js functionality into destructured.js

- Add namespace imports, function aliases, and variable assignments

- Maintain comprehensive coverage of all import patterns

- Consolidate ES6 imports, CommonJS requires, and alias patterns
- Remove duplicate test case consolidated into destructured.js

- Eliminate redundancy while maintaining test coverage

- Optimize test suite from 12 to 11 unique cases
- ast-node-types.js: Test complex AST value types (member_expression, call_expression, etc.)

- dynamic-options.js: Test unsupported dynamic options pattern

- variable-type.js: Test unsupported variable key type pattern
- Remove "@types/node": "^24.0.3" from package.json

- Fix an example in the readme
  - Add resolveVariableValue() function to detect variables containing 'rsa-pss'
  - Update type detection logic to handle both string literals and variables
  - Transform variable-type.js test case (now supported)
  - Translate Spanish comments to English in ast-node-types.js
  - Add getPromisifiedBindings() function to detect util.promisify() patterns
  - Extend getCryptoBindings() to include promisified crypto function wrappers
  - Add promisified-wrappers.js test case covering 6 different scenarios
  - Update workflow documentation to reflect new capabilities
  - Support patterns like: const genAsync = util.promisify(crypto.generateKeyPair)
Comment thread recipes/crypto-rsa-pss-update/src/workflow.ts Outdated
  - Use resolveBindingPath for dynamic promisify binding detection
  - Support destructured imports: const {promisify} = require('util')
  - Add test cases for destructured/aliased promisify patterns
  - Fix variable naming conflict and improve fallback logic
  - Fix TypeScript error: conditional_expression → ternary_expression

@brunocroh brunocroh left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nice work, thanks! 🚀

Comment thread recipes/crypto-rsa-pss-update/src/workflow.ts Outdated
Comment thread recipes/crypto-rsa-pss-update/src/workflow.ts Outdated
Comment thread recipes/crypto-rsa-pss-update/src/workflow.ts Outdated
Comment thread recipes/crypto-rsa-pss-update/src/workflow.ts Outdated
dependabot Bot and others added 5 commits August 19, 2025 15:28
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…d edge cases

  - Remove safeGet* wrapper functions
  - Consolidate destructured.js test (merge aliases/mixed imports)
  - Delete redundant tests: ast-node-types, variable-type
  - Add 5 new edge case tests: complex-ast-patterns, computed-properties, method-chaining, ternary-operators, variable-key-type
  - Update basic.js transformations

@brunocroh brunocroh left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM 🚀🎉

@AugustinMauroy
AugustinMauroy requested a review from a team August 21, 2025 10:02
nievasdev and others added 5 commits August 21, 2025 16:56
  Use proper type assertions for SgRoot<javascriptTypes> and SgRoot<TypesMap>
  compatibility in utility functions getModuleStatements and resolveBindings.
- Remove 'as any' casts in crypto-rsa-pss-update workflow
- Update correct-ts-specifiers test snapshot to match current behavior
…tibility

  - Restore package-lock.json from main
@nievasdev

Copy link
Copy Markdown
Contributor Author

@brunocroh @AugustinMauroy, how are you? Are there other things we should change? How should I continue with this work?

@brunocroh

Copy link
Copy Markdown
Member

@brunocroh @AugustinMauroy, how are you? Are there other things we should change? How should I continue with this work?

We need one more member to review/approve before proceeding with the merge.
We are currently waiting for feedback from the team.

@nievasdev

Copy link
Copy Markdown
Contributor Author

Good, could I take another issue while I wait, or is it better if I just wait?

@AugustinMauroy

Copy link
Copy Markdown
Member

Good, could I take another issue while I wait, or is it better if I just wait?

yeah if you want you can open an second pr

@AugustinMauroy

Copy link
Copy Markdown
Member

cc @JakobJingleheimer

@JakobJingleheimer JakobJingleheimer left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM 🙌

PS Sorry for the delay. This got lost in my inbox 😓

@JakobJingleheimer
JakobJingleheimer merged commit 6c013ab into nodejs:main Oct 8, 2025
15 checks passed
@JakobJingleheimer JakobJingleheimer added the dep:20.x Migrate a deprecation for node 20.x label Oct 16, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dep:20.x Migrate a deprecation for node 20.x

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feat: handle RSA-PSS generate key pair options

4 participants