lambda-nodejs: local bundling on Windows fails under AllSigned PowerShell execution policy (regression from #37412)
- Dominant language
- TypeScript
- Stars
- 12.9k
- Forks
- 4.6k
- Avg merge
- 2d 3h
- Merged PRs (30d)
- 83
Description
### Describe the bug
`NodejsFunction` local bundling fails due to policy violation.
This seems to be a side effect of the fix for **CVE-2026-11417** (command injection in local bundling, [GHSA-999r-qq7v-r334](https://github.com/aws/aws-cdk/security/advisories/GHSA-999r-qq7v-r334)):
- [#37292](https://github.com/aws/aws-cdk/pull/37292) replaced shell-string bundling with argument-array `spawnSync` calls — correct fix for the injection issue, but broke direct spawning of `.cmd` shims on Windows/Node 22+ (`EINVAL`), tracked in [#37387](https://github.com/aws/aws-cdk/issues/37387).
- [#37412](https://github.com/aws/aws-cdk/pull/37412) fixed the `EINVAL` regression by routing local-bundling `spawn` steps on `win32` through `powershell.exe -NoProfile -Command`, using the call operator (e.g. `& 'npm' 'ci'`) with escaped arguments.
The problem: invoking a bare command name (`npm`, `npx`) via PowerShell's call operator forces PowerShell to resolve it through its own command search, which considers `npm.ps1` (a `.ps1` script, subject to `ExecutionPolicy`) alongside `npm.cmd` (a batch file, not subject to `ExecutionPolicy` at all). On systems where PowerShell resolves the `.ps1` shim, `AllSigned` blocks it outright, and there is no user-level override since `MachinePolicy` takes precedence over `Process`/`CurrentUser`/`LocalMachine` scopes.
### Regression Issue
- [x] Select this option if this issue appears to be a regression.
### Last Known Working CDK Library Version
_No response_
### Expected Behavior
Local bundling working even when PowerShell `AllSigned` execution policy is set (commonly set via Group Policy at `MachinePolicy` scope).
### Current Behavior
`NodejsFunction` local bundling fails with:
```
File C:\Program Files\nodejs\npm.ps1 cannot be loaded. The file C:\Program Files\nodejs\npm.ps1
is not digitally signed. You cannot run this script on the current system.
+ CategoryInfo : SecurityError: (:) [], PSSecurityException
+ FullyQualifiedErrorId : UnauthorizedAccess
```
This happens on any machine where `Get-ExecutionPolicy -List` shows `MachinePolicy: AllSigned` (a Group Policy setting that overrides all other execution-policy scopes, including `CurrentUser`/`LocalMachine`, and cannot be worked around via `Set-ExecutionPolicy` by the developer).
### Reproduction Steps
1. Set `Set-ExecutionPolicy AllSigned -Scope MachinePolicy` (or equivalent Group Policy) on a Windows machine with Node 22+.
2. Create a `NodejsFunction` with a `nodeModules` entry (triggers a local `npm ci`/install step).
3. Run `cdk synth`.
4. Observe the `npm.ps1 ... not digitally signed` error.
### Possible Solution
Crude workaround, not recommended for general use
Renaming `C:\Program Files\nodejs\npm.ps1` to eg `npm.ps1old` (and equivalently for `npx.ps1`) removes the `.ps1` shim from resolution, causing PowerShell to fall back to `npm.cmd`, which bundles successfully. This requires admin access, isn't durable across Node.js reinstalls/upgrades, and effectively routes around the intent of the `AllSigned` policy rather than fixing the underlying resolution behavior.
### Additional Information/Context
_No response_
### AWS CDK Library version (aws-cdk-lib)
aws-cdk-lib@2.248.0
### AWS CDK CLI version
2.1120.0 (build acefbf8)
### Node.js Version
v25.9.0
### OS
Windows 11
### Language
TypeScript
### Language Version
5.6.2
### Other information
Regression seems present since 2.246.0.
Contributor guide
Research direction
Start at the NodejsFunction local-bundling spawn path changed by #37412, then reproduce the npm ci step on Windows with MachinePolicy set to AllSigned. Done means cdk synth completes for a NodejsFunction with nodeModules without the npm.ps1 signature error, while preserving the command-injection fix and the Node 22+ Windows behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- node.js, powershell, typescript
- Domain
- build-system, operating-systems, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100