aws / aws/aws-cdk

aws-lambda-nodejs: Dockerfile's 'update-notifier false' step re-creates /tmp/npm-cache/_logs as root, regressing #9167's fix

Open Beginner friendly
#38,764 1 comment 0 reactions 0 assignees View on GitHub
@aws-cdk/aws-lambda-nodejs effort/medium feature-request p2
Dominant language
TypeScript
Stars
12.9k
Forks
4.6k
Avg merge
2d 3h
Merged PRs (30d)
83

Description

### Describe the bug

`aws-cdk-lib`'s Lambda-bundling Docker image (`aws-cdk-lib/aws-lambda-nodejs/lib/docker/Dockerfile`) makes `npm ci`/`npm install` fail for any Lambda built with `bundling.forceDockerBundling: true` (or any Lambda that needs Docker bundling for another reason, e.g. a native dependency compiled for the target platform/arch) — because `/tmp/npm-cache/_logs` ends up owned by `root:root` (mode 755) instead of the `777`-permissioned `/tmp/npm-cache` it lives under.

Any later `npm ci` run as the non-root bundling UID (CDK does `docker run -u ":" ...`) then fails outright, because npm treats "can't write the log file" as fatal for `npm ci`, not just a warning.

### This is a regression of #9167 (merged 2020)

PR #9167 ("fix(lambda-nodejs): permission denied on npm cache") originally fixed this exact class of bug by adding a `chmod -R 777 /tmp/npm-cache` and moving cache-folder creation so no root-owned content existed in it before the image starts, plus disabling npm's update notifier "so [it doesn't] write to that folder as root."

Looking at the current Dockerfile (confirmed on `aws-cdk-lib@2.265.0`), the ordering has drifted so the update-notifier line now runs **after** the chmod, undoing the original fix:

```dockerfile
# Ensure all users can write to npm cache
RUN mkdir /tmp/npm-cache && \
chmod -R 777 /tmp/npm-cache && \
npm config --global set cache /tmp/npm-cache
...
# Disable npm update notifications
RUN npm config --global set update-notifier false
```

That second `RUN npm config --global set update-notifier false` executes as root during `docker build`, and itself writes an npm debug log to the configured cache dir, recreating `/tmp/npm-cache/_logs` as `root:root 755`. Nothing chmods it again afterward.

### Reproduction

```bash
docker run --rm public.ecr.aws/sam/build-nodejs24.x sh -c "
mkdir /tmp/npm-cache && chmod -R 777 /tmp/npm-cache && npm config --global set cache /tmp/npm-cache
npm config --global set update-notifier false
stat -c '%n %U %a' /tmp/npm-cache/_logs
"
# -> root 755
```

Then any `npm ci` run as a non-root UID against that cache directory fails:

```bash
docker run --rm -u "501:20" sh -c "
mkdir -p /tmp/t && cd /tmp/t
echo '{\"name\":\"t\",\"version\":\"1.0.0\"}' > package.json
echo '{\"name\":\"t\",\"version\":\"1.0.0\",\"lockfileVersion\":3,\"requires\":true,\"packages\":{\"\":{\"name\":\"t\",\"version\":\"1.0.0\"}}}' > package-lock.json
npm ci
"
# -> EACCES / log write failure, npm ci fails
```

### Expected Behavior

`npm ci`/`npm install` inside the Docker bundling image should succeed for any UID, the same guarantee #9167 originally established for the whole npm cache directory.

### Current Behavior

`npm ci` fails because `/tmp/npm-cache/_logs` is root-owned and non-writable by the bundling UID.

### Reproduction Steps

See reproduction commands above. Also reproducible via any `NodejsFunction` with `bundling.forceDockerBundling: true` and `bundling.nodeModules` set — running `cdk synth` fails with `CommandExecutionFailed: docker exited with status 1` and an `npm error` about the log directory (or, once the underlying log-write failure obscures the real error, a less obvious npm failure).

### Possible Solution

Either:
1. Move `RUN npm config --global set update-notifier false` before the `mkdir /tmp/npm-cache && chmod -R 777 ...` block, or
2. Re-run `chmod -R 777 /tmp/npm-cache` after the update-notifier line, or
3. Set the workaround `npm_config_logs_max=0` via env in the base image so npm never attempts to write a log file inside the container at all.

As an immediate workaround, setting `bundling.environment: { npm_config_logs_max: '0' }` on the affected `NodejsFunction`(s) avoids the issue without an aws-cdk-lib change, since it disables npm's log-writing entirely.

### CDK CLI Version

2.1139.0 (aws-cdk-lib 2.265.0)

### Framework Version

_No response_

### Node.js Version

Node 24 (bundling image: `public.ecr.aws/sam/build-nodejs24.x`)

### OS

macOS (host); Amazon Linux (SAM build image, Lambda-compatible Docker container)

### Language

TypeScript

### Language Version

_No response_

### Other information

Affects any project using `NodejsFunction` with `bundling.forceDockerBundling: true` and `bundling.nodeModules`, not specific to any one project — reproduced directly against the unmodified `public.ecr.aws/sam/build-nodejs24.x`-derived bundling image with no project-specific configuration involved.

Contributor guide

Open the contributing guide

Research direction

Start with aws-cdk-lib/aws-lambda-nodejs/lib/docker/Dockerfile and compare the npm cache setup with the update-notifier step described in the issue. Run the supplied Docker reproduction, then verify that npm ci succeeds as a non-root UID and that /tmp/npm-cache remains writable for any bundling UID.

Written by the indexing model from the issue text.

Assessment

Tech stack
aws, dockerfile, nodejs, typescript
Domain
build-system, cloud, devops
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
82/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.