Skip to content

Updated vulnerable packages #1573

Open
DeepakNemad wants to merge 8 commits intomainfrom
fix/docker-vulnerabilities
Open

Updated vulnerable packages #1573
DeepakNemad wants to merge 8 commits intomainfrom
fix/docker-vulnerabilities

Conversation

@DeepakNemad
Copy link

@DeepakNemad DeepakNemad commented Feb 25, 2026

  • Updated vulnerable packages and Updated all Dockerfiles to use Node.js 24

Summary by CodeRabbit

  • Infrastructure/DevOps

    • Upgraded container base to Node 24 Alpine, streamlined multi-stage builds, and simplified startup to run built Node apps directly for smaller, consistent runtime images.
  • Security

    • Containers now run as non-root users with tightened filesystem permissions and reduced runtime tooling.
  • Dependencies

    • Broad dependency and tooling upgrades across runtime and dev tooling (including Prisma and package manager improvements).

…s 24

Signed-off-by: DeepakNemad <deepak.nemade@ayanworks.com>
@DeepakNemad DeepakNemad self-assigned this Feb 25, 2026
@coderabbitai
Copy link

coderabbitai bot commented Feb 25, 2026

Warning

Rate limit exceeded

@DeepakNemad has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 13 minutes and 13 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 24ad3df and d23d50f.

📒 Files selected for processing (2)
  • Dockerfiles/Dockerfile.oid4vc-verification
  • Dockerfiles/Dockerfile.x509
📝 Walkthrough

Walkthrough

Modernizes many Dockerfiles: upgrades build/final images to Node 24 (alpine), pins pnpm, consolidates apk/pnpm steps, moves Prisma client generation into build stage, trims final images to built artifacts/node_modules, enforces non-root runtime user, and bumps many package.json dependencies.

Changes

Cohort / File(s) Summary
Service Dockerfiles — build-stage and package handling
Dockerfiles/Dockerfile.agent-provisioning, Dockerfiles/Dockerfile.agent-service, Dockerfiles/Dockerfile.api-gateway, Dockerfiles/Dockerfile.cloud-wallet, Dockerfiles/Dockerfile.connection, Dockerfiles/Dockerfile.ecosystem, Dockerfiles/Dockerfile.geolocation, Dockerfiles/Dockerfile.issuance, Dockerfiles/Dockerfile.ledger, Dockerfiles/Dockerfile.notification, Dockerfiles/Dockerfile.oid4vc-issuance, Dockerfiles/Dockerfile.oid4vc-verification, Dockerfiles/Dockerfile.organization, Dockerfiles/Dockerfile.user, Dockerfiles/Dockerfile.utility, Dockerfiles/Dockerfile.verification, Dockerfiles/Dockerfile.webhook, Dockerfiles/Dockerfile.x509
Switch build base to node:24-alpine3.21; consolidate apk + openssl steps; install/pin pnpm@9.15.3 globally; copy package manifests together; set PUPPETEER_SKIP_DOWNLOAD=true; run pnpm i --frozen-lockfile --ignore-scripts; run prisma generate in build; run service builds in build stage.
Service Dockerfiles — final image & runtime
(same files as above)
Final stage to node:24-alpine3.21; create non-root nextjs user / nodejs group (uid/gid 1001); copy only node_modules (and service dist as needed) from build; remove runtime Prisma migrate/generate; set USER to nextjs and CMD to ["node","dist/apps/<service>/main.js"]; add ownership/permission adjustments.
Seed Dockerfile
Dockerfiles/Dockerfile.seed
Upgrade to Node 24 Alpine; install postgresql-client; consolidate apk/pnpm steps; create non-root user; adjust permissions; set runtime CMD to seed DB via cd libs/prisma-service && npx prisma db seed.
Package manifest
package.json
Large dependency and devDependency version upgrades across many packages (notable: Prisma, AWS SDK, OpenTelemetry, numerous @types and tooling). No API/signature changes indicated.

Sequence Diagram(s)

(omitted)

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • KambleSahil3
  • GHkrishna

Poem

🐰
I hopped through Alpine, quick and bright,
Upgraded Node and tuned the light,
pnpm pinned, Prisma moved to build,
Non-root users now are thrilled,
Clean dist, light images — carrotbite! 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The PR title 'Updated vulnerable packages' is vague and does not capture the main scope of changes, which involves both package updates AND comprehensive Dockerfile modernization to Node.js 24 with multi-stage build improvements. Consider a more descriptive title like 'Upgrade to Node.js 24 and modernize Dockerfiles' or 'Update vulnerable packages and migrate Node.js 18 to 24' to better reflect the significant changes across all Dockerfiles.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/docker-vulnerabilities

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

@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: 20

♻️ Duplicate comments (5)
Dockerfiles/Dockerfile.oid4vc-issuance (1)

1-24: Same cross-cutting issues as noted in Dockerfile.oid4vc-verification apply here.

No additional unique issues beyond the unpinned pnpm, missing lockfile, prisma migrate in CMD, and full libs/ copy.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.oid4vc-issuance` around lines 1 - 24, The Dockerfile
repeats cross-cutting issues: pin pnpm version instead of installing latest
(replace RUN npm install -g pnpm@latest with a specific version), ensure a
lockfile is copied and used (COPY pnpm-lock.yaml before running pnpm i and run
pnpm install --frozen-lockfile), avoid copying the entire libs/ into the runtime
image (only copy necessary built artifacts from /app/dist or specific libs
needed by oid4vc-issuance instead of COPY --from=build --chown=nextjs:nodejs
/app/libs/ ./libs/), and remove runtime schema changes from CMD (do not run
prisma migrate deploy in CMD; run migrations during image build or via a
separate migration step and keep CMD to start node
dist/apps/oid4vc-issuance/main.js).
Dockerfiles/Dockerfile.organization (1)

1-24: Same cross-cutting issues as noted in Dockerfile.oid4vc-verification apply here.

The unpinned pnpm@latest, missing lockfile before pnpm i, prisma migrate deploy in CMD, misleading user names, and full libs/ copy all apply identically to this file. No additional unique issues.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.organization` around lines 1 - 24, This Dockerfile
repeats the cross-cutting issues: pin pnpm instead of using RUN npm install -g
pnpm@latest, copy the lockfile (pnpm-lock.yaml) into the build stage before RUN
pnpm i --ignore-scripts so installs are reproducible, move runtime schema
migrations out of the container CMD (the long CMD that runs "cd
libs/prisma-service && npx prisma migrate deploy && npx prisma generate && ...")
into a controlled deploy/init step or run only prisma generate at build time
(use RUN in the build stage to npx prisma generate after copying schema), avoid
copying the entire libs/ directory into the final image (replace COPY
--from=build --chown=nextjs:nodejs /app/libs/ ./libs/ with only the needed built
artifacts or the prisma service output), and replace misleading user/group names
(adduser nextjs/ nodejs) with neutral names like appuser/appgroup or align names
with project conventions; ensure ENV PUPPETEER_SKIP_DOWNLOAD is still set if
required.
Dockerfiles/Dockerfile.notification (1)

1-24: Same cross-cutting issues as noted in Dockerfile.oid4vc-verification apply here.

No additional unique issues.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.notification` around lines 1 - 24, This Dockerfile
repeats cross-cutting issues: avoid copying full dev node_modules from the build
stage and invoking npx at runtime; instead produce a production-only
node_modules in the build stage (use pnpm install --prod or pnpm prune --prod in
the build stage after building), remove dev-only tooling from the final image,
and change the startup CMD to run the app binary directly without running npx
during container start; also ensure Prisma migration/generate steps are handled
safely (either run migrations as part of CI/deploy or run migration commands
from an init container or an entrypoint script that ensures proper DB
credentials and filesystem permissions for the nextjs user) — update the
Dockerfile lines involving RUN pnpm i --ignore-scripts, COPY --from=build
--chown=nextjs:nodejs /app/node_modules, USER nextjs, and CMD ["sh", "-c", "cd
libs/prisma-service && npx prisma migrate deploy && npx prisma generate && cd
../.. && node dist/apps/notification/main.js"] accordingly.
Dockerfiles/Dockerfile.utility (1)

1-24: Same cross-cutting issues as noted in Dockerfile.oid4vc-verification apply here.

No additional unique issues.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.utility` around lines 1 - 24, The Dockerfile repeats
cross-cutting issues: remove the global pnpm install and instead enable Corepack
or use pnpm from the build base, set NODE_ENV=production, install only
production dependencies during the build (replace "RUN pnpm i --ignore-scripts"
with a deterministic production install such as "pnpm install --frozen-lockfile
--prod" in the build stage and avoid copying the entire node_modules into the
final image), ensure prisma codegen runs at build time ("RUN cd
libs/prisma-service && npx prisma generate" is fine) and remove runtime
migration/generation from the CMD (remove "npx prisma migrate deploy && npx
prisma generate" from the CMD so migrations are applied out-of-band), and keep
copying only required artifacts ("COPY --from=build --chown=nextjs:nodejs
/app/dist/apps/utility/ ./dist/apps/utility/" and needed libs) while preserving
non-root user setup (nextjs/nodejs) and minimal layers.
Dockerfiles/Dockerfile.x509 (1)

1-24: Same cross-cutting issues as noted in Dockerfile.oid4vc-verification apply here.

Unpinned pnpm, missing lockfile, prisma migrate in CMD, and full libs/ copy.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.x509` around lines 1 - 24, Pin pnpm instead of using
npm install -g pnpm@latest (replace the npm install command with a fixed
version, e.g., npm install -g pnpm@X.Y.Z) and ensure you COPY and use the
workspace lockfile (pnpm-lock.yaml) before running pnpm install so installs are
reproducible (reference COPY package.json pnpm-workspace.yaml and RUN pnpm i
--ignore-scripts). Remove heavy COPY of the entire libs/ into the final image
and instead copy only the built output and the generated Prisma client for
prisma-service (address COPY --from=build --chown=nextjs:nodejs /app/libs/
./libs/ and RUN cd libs/prisma-service && npx prisma generate in the build
stage). Move runtime migrations out of the container CMD (do not run npx prisma
migrate deploy && npx prisma generate inside CMD); either run migrations during
image build or implement a safe startup entrypoint script that conditionally
runs migrations with proper rights (modify the CMD line referencing prisma
migrate deploy && npx prisma generate accordingly).
🧹 Nitpick comments (10)
Trivy-scann-data/Before-detailed-vulnerability-report.md (1)

1-97: Consider adding an "After" scan report to confirm remediation.

This report captures the pre-fix vulnerability state, but there's no corresponding post-fix report to verify which CVEs were actually resolved by the Node 24 upgrade and dependency updates. Including a Trivy scan of the rebuilt images would provide evidence that the changes achieved their goal.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Trivy-scann-data/Before-detailed-vulnerability-report.md` around lines 1 -
97, Add a new "After" scan section to the report that shows Trivy results for
the rebuilt images (post-Node24 and dependency updates): run Trivy on the same
image list (the entries under "## Images Scanned") using the rebuilt image tags,
include scan timestamp, per-image vulnerability counts and a CVE diff table
mapping which CVEs from the "## Critical Vulnerabilities Found" and "## High
Severity Vulnerabilities Found" sections were fixed vs. still present (reference
the report headers "Docker Images Vulnerability Scan Report", "## Images
Scanned", and the listed CVEs), and include a short CI note in "##
Recommendations" describing the command used (e.g., trivy image ...) and where
the after-scan artifacts are stored.
Dockerfiles/Dockerfile.seed (1)

1-8: Single-stage build includes all build-time dependencies in the final image.

Unlike the other Dockerfiles in this PR which use multi-stage builds, this Dockerfile installs build tools (pnpm, full source) directly into the runtime image. This increases image size and attack surface. Consider using a multi-stage build consistent with the rest of the services, copying only the necessary artifacts (prisma-service, node_modules, scripts) into a clean final stage.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.seed` around lines 1 - 8, Current Dockerfile.seed
creates a single-stage image that installs build-time tools like pnpm and leaves
source/dependencies in the runtime image; convert it to a multi-stage build: add
a builder stage (FROM node:24-alpine3.21 AS builder) that runs apk add and RUN
npm install -g pnpm@latest, installs dependencies and builds the prisma-service,
then create a slim final stage (FROM node:24-alpine3.21) that only copies the
built artifacts, necessary node_modules, and runtime files from the builder,
re-creates the runtime user/group (addgroup/adduser nextjs), and omits pnpm and
other build-time packages (postgresql-client/openssl) to minimize image size and
attack surface.
Dockerfiles/Dockerfile.oid4vc-verification (2)

14-18: Non-root user/group names "nextjs"/"nodejs" are misleading for non-Next.js services.

These names originate from Next.js conventions but are used here across all backend microservices (oid4vc-verification, organization, notification, etc.). Consider using generic names like appuser/appgroup for clarity. This applies to all Dockerfiles in this PR.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.oid4vc-verification` around lines 14 - 18, The
Dockerfile uses misleading non-root user/group names "nodejs" and "nextjs" in
the addgroup and adduser commands; update these invocations (addgroup -g 1001 -S
nodejs and adduser -S nextjs -u 1001) to use generic names such as appgroup and
appuser (e.g., addgroup -g 1001 -S appgroup and adduser -S appuser -u 1001) and
apply the same rename consistently across all Dockerfiles in the PR so service
images no longer reference Next.js-specific identifiers.

20-22: Copying entire /app/libs/ into the final image may include unnecessary source files.

Line 21 copies the full libs/ directory from the build stage. If only libs/prisma-service is needed at runtime (for Prisma migrations/generation), copying everything else bloats the final image and leaks build-time source into production.

Proposed fix — copy only what's needed
-COPY --from=build --chown=nextjs:nodejs /app/libs/ ./libs/
+COPY --from=build --chown=nextjs:nodejs /app/libs/prisma-service ./libs/prisma-service
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.oid4vc-verification` around lines 20 - 22, The
Dockerfile currently copies the entire /app/libs/ directory into the final image
(COPY --from=build --chown=nextjs:nodejs /app/libs/ ./libs/), which pulls
unnecessary source and bloats the image; update that COPY to only copy the
runtime-required library (e.g., COPY --from=build --chown=nextjs:nodejs
/app/libs/prisma-service ./libs/prisma-service/) and any specific subpaths it
needs (migrations, generated client, schema) so only prisma-service artifacts
are included; keep the existing node_modules and other needed COPY lines but
avoid copying the rest of /app/libs/.
Dockerfiles/Dockerfile.agent-provisioning (2)

2-2: Consider using alpine3.22 or later for improved security posture.

The current Docker Hub tags show 24-alpine3.22 and 24-alpine3.23 variants are available. Since this PR is specifically about fixing vulnerabilities, pinning to alpine3.21 (released Dec 2024) means missing Alpine security patches from later releases.

Also applies to: 22-22

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.agent-provisioning` at line 2, The base image is
pinned to node:24-alpine3.21 which misses newer Alpine security patches; update
the FROM line in the Dockerfile(s) (the FROM instruction referencing
node:24-alpine3.21) to a newer Alpine variant such as node:24-alpine3.22 or
node:24-alpine3.23 (or later) to pick up security fixes, and apply the same
update to any other Dockerfiles using alpine3.21 (e.g., the 22-22 variant).

31-32: Misleading user/group names nextjs:nodejs for a non-Next.js project.

This is the CREDEBL platform, not a Next.js app. Using nextjs and nodejs as the user/group names is confusing and suggests this was copy-pasted from a Next.js template. Consider using descriptive names like credebl or appuser. This applies to all Dockerfiles in the PR.

Proposed fix (apply across all Dockerfiles)
-    && addgroup -g 1001 -S nodejs \
-    && adduser -S nextjs -u 1001
+    && addgroup -g 1001 -S appgroup \
+    && adduser -S appuser -u 1001

And update all --chown=nextjs:nodejs references to --chown=appuser:appgroup and USER nextjs to USER appuser.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.agent-provisioning` around lines 31 - 32, Replace the
misleading Next.js-specific user/group names: change the addgroup/adduser calls
that create "nodejs" and "nextjs" (see addgroup -g 1001 -S nodejs and adduser -S
nextjs -u 1001) to descriptive names such as "appgroup"/"appuser" or
"credebl"/"credebl"; then update all related usages across the
Dockerfiles—replace any --chown=nextjs:nodejs occurrences with
--chown=appuser:appgroup (or your chosen names) and change USER nextjs to USER
appuser so the image user/group names consistently reflect the CREDEBL project.
Trivy-scann-data/Changes-made.md (1)

46-47: Piping a remote script to sudo sh is a security anti-pattern.

While this is a documentation/report file rather than a runnable script, documenting curl ... | sudo sh as a recommended installation method normalizes an insecure practice. Consider noting that the script should be downloaded, inspected, and then executed — or use a package manager.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Trivy-scann-data/Changes-made.md` around lines 46 - 47, The documented
installation line "sudo curl -sfL
https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh |
sudo sh -s -- -b /usr/local/bin" is a security anti-pattern; update
Changes-made.md to replace that single-line recommendation with guidance to
first download the installer, inspect/verify it (or verify a
checksum/signature), then run it with elevated privileges, or alternatively
recommend installing Trivy via a supported package manager or release binary;
mention the exact snippet text so the maintainer can locate and replace it.
Dockerfiles/Dockerfile.user (1)

20-22: Entire node_modules (including devDependencies) copied to production image.

Copying the full node_modules from the build stage includes development dependencies, inflating the final image. Consider using pnpm deploy --prod or pnpm prune --prod in the build stage before copying, to include only production dependencies in the final image. This applies to all Dockerfiles in this PR.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.user` around lines 20 - 22, The Dockerfile is copying
the entire node_modules from the build stage (see the COPY --from=build
--chown=nextjs:nodejs /app/node_modules ./node_modules line), which brings
devDependencies into the production image; update the build stage to install
only production dependencies (e.g., run pnpm deploy --prod or pnpm prune --prod
or pnpm install --prod in the build stage) and then remove or change the final
stage copy so it only includes the pruned production node_modules (or avoid
copying node_modules and use a production-only installation in the final stage);
ensure the change is applied to the same COPY invocation and any equivalent COPY
lines across the other Dockerfiles in the PR.
package.json (1)

59-63: Move @types/* packages to devDependencies.

Lines 59–63 contain type declaration packages that belong in devDependencies, not runtime dependencies. These are used only during TypeScript compilation, not at runtime. The codebase confirms actual usage of the underlying packages (async-retry, crypto-js, json2csv), while other @types/* packages are already correctly placed in devDependencies.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@package.json` around lines 59 - 63, Package.json currently lists type
declaration packages ("@types/async-retry", "@types/crypto-js",
"@types/json2csv", "@types/pdfkit") under dependencies; move each of these
entries out of dependencies and into devDependencies (preserving their versions)
so they are only installed for TypeScript compilation. Remove the entries from
dependencies and add them to devDependencies (or run the equivalent package
manager command, e.g., npm/yarn add --save-dev) and update any lockfile
accordingly.
Dockerfiles/Dockerfile.agent-service (1)

21-27: Remove unnecessary tools from runtime image to reduce size and attack surface.

The runtime stage (Stage 2) installs aws-cli, docker, docker-compose, and openssh-client, but none of these are invoked in the agent-service code. The container only runs node dist/apps/agent-service/main.js and Prisma migrations at runtime. Removing these four tools will reduce image bloat and security risk without impacting functionality.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.agent-service` around lines 21 - 27, Remove unused
runtime packages from the Stage 2 RUN layer: eliminate aws-cli, docker,
docker-compose, and openssh-client from the apk add list in the
Dockerfile.agent-service runtime stage so the image only installs required
packages (e.g., openssl) for running node dist/apps/agent-service/main.js and
Prisma migrations; update the RUN command to only add necessary packages and
keep the rm -rf /var/cache/apk/* cleanup to minimize image size and attack
surface.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@Dockerfiles/Dockerfile.agent-provisioning`:
- Line 49: The Dockerfile's startup CMD currently runs "prisma migrate deploy"
and "npx prisma generate" which can race in multi-replica starts and redundantly
regenerate the client; remove both commands from the CMD and leave only the app
start (e.g., replace CMD ["sh", "-c", "cd libs/prisma-service && npx prisma
migrate deploy && npx prisma generate && cd ../.. && node
dist/apps/agent-provisioning/main.js"] with a CMD that simply starts the built
app like node dist/apps/agent-provisioning/main.js), and instead run migrations
via a separate migration job or init container (not in application startup);
keep the generation step only in the build stage where Prisma client was already
generated.
- Line 18: Remove the debug RUN line that lists files in the image—specifically
delete the "RUN ls -R /app/apps/agent-provisioning/AFJ/" instruction from the
Dockerfile so the extra build layer is not created; ensure no other build logic
depends on that command and keep the remaining Dockerfile steps unchanged.
- Line 11: The Dockerfile currently installs pnpm with a floating tag ("RUN npm
install -g pnpm@latest --ignore-scripts"); change this to pin pnpm to the
project's exact version (replace "@latest" with the version found in
package.json's packageManager field or the lockfile, e.g., "pnpm@9.15.4") so
builds are reproducible—update the RUN line(s) across all Dockerfiles that use
"npm install -g pnpm@latest --ignore-scripts".

In `@Dockerfiles/Dockerfile.agent-service`:
- Line 35: The Docker CMD currently runs Prisma migrations at container startup
(CMD invoking "npx prisma migrate deploy" and "npx prisma generate" in the
Dockerfile agent-service), which can cause race conditions; remove the migration
step from the CMD so the container only starts the app (keep only the runtime
invocation of node dist/apps/agent-service/main.js or node startup command) and
run migrations as a separate init job/CI step or Kubernetes
initContainer/entrypoint script; also remove or separate "npx prisma migrate
deploy" from the Dockerfile's CMD while retaining any necessary "npx prisma
generate" earlier in the build stage if required for production artifacts.
- Around line 10-14: Replace the unpinned global install and the incomplete
COPY: change the RUN that currently installs pnpm@latest to install a specific
pinned pnpm version (e.g., pnpm@<desired-version>) instead of `@latest`, and
update the COPY command that currently copies package.json and
pnpm-workspace.yaml to also include pnpm-lock.yaml so the subsequent RUN pnpm i
--ignore-scripts uses the lockfile for deterministic installs.

In `@Dockerfiles/Dockerfile.connection`:
- Line 24: The Dockerfile currently runs migrations in the container CMD (the
line invoking "npx prisma migrate deploy && npx prisma generate" inside CMD),
which should be removed from the app startup path; instead create a separate
one‑shot migration job (init container or pre-deploy hook) that runs the
commands "npx prisma migrate deploy && npx prisma generate" against the same
built image or a dedicated migration image, and change the Dockerfile CMD to
only start the app (e.g., run "node dist/apps/connection/main.js"); apply this
same change to all Dockerfiles that contain the migration invocation
(agent-provisioning, agent-service, api-gateway, cloud-wallet, connection,
ecosystem, geolocation, issuance, ledger, notification, oid4vc-issuance,
oid4vc-verification, organization, user, utility, verification, webhook, x509)
so migrations run once before app replicas start.
- Around line 4-8: Replace the global "npm install -g pnpm@latest" approach with
Corepack to pin the pnpm runtime, copy the repository's pnpm-lock.yaml into the
image alongside package.json and pnpm-workspace.yaml before running install, and
change the install invocation referenced by the RUN pnpm i --ignore-scripts
command to use --frozen-lockfile so the build strictly honors pnpm-lock.yaml;
keep ENV PUPPETEER_SKIP_DOWNLOAD=true and the WORKDIR /app usage intact.

In `@Dockerfiles/Dockerfile.issuance`:
- Around line 4-8: Replace the global install of "pnpm@latest" with the pinned
version declared in package.json (pnpm@9.15.3) and ensure the lockfile is copied
and honored: copy pnpm-lock.yaml alongside package.json/pnpm-workspace.yaml (the
COPY that currently targets package.json pnpm-workspace.yaml ./) and change the
install invocation (the RUN pnpm i --ignore-scripts) to fail if the lockfile is
out of date (use pnpm install with the frozen-lockfile behavior). Keep ENV
PUPPETEER_SKIP_DOWNLOAD=true as-is; the goal is to enforce reproducible installs
by using the pinned pnpm executable and by installing strictly from the
committed pnpm-lock.yaml.
- Line 24: Remove runtime schema migration and generate commands from the image
startup command: delete the "npx prisma migrate deploy" and "npx prisma
generate" invocations from the Dockerfile CMD that currently runs in
libs/prisma-service and leave the container startup to only launch the app (node
dist/apps/issuance/main.js). Keep prisma generate in the build stage (it already
runs on line 10) and move "prisma migrate deploy" to your deployment
orchestration (an init Job, initContainer, or Helm/Kustomize pre-install hook)
so migrations run once before replicas start; apply this same change to all 19
microservice Dockerfiles that currently run migrations in CMD.

In `@Dockerfiles/Dockerfile.ledger`:
- Around line 4-8: The Dockerfile uses a non-deterministic pnpm install (RUN npm
install -g pnpm@latest) and omits the lockfile from COPY (COPY package.json
pnpm-workspace.yaml ./), which breaks reproducible builds; update the Dockerfile
to pin pnpm to a specific version instead of pnpm@latest and include the
repository's pnpm-lock.yaml in the COPY step so that the subsequent RUN pnpm i
--ignore-scripts installs deterministically while keeping ENV
PUPPETEER_SKIP_DOWNLOAD=true unchanged.
- Line 24: The Dockerfile currently runs migration and codegen at container
start via the CMD invoking "cd libs/prisma-service && npx prisma migrate deploy
&& npx prisma generate && ... node dist/apps/ledger/main.js", which causes race
conditions and tight coupling; remove the runtime migration and generation
commands from the CMD so the container just starts the app (node
dist/apps/ledger/main.js), and move "npx prisma migrate deploy" into a
centralized one-time deployment step (init container, Kubernetes Job, or
dedicated migration service) that targets the database before app pods start;
also remove redundant "npx prisma generate" at runtime since it should run
during the Dockerfile build (ensure libs/prisma-service codegen is executed in
build stage instead).

In `@Dockerfiles/Dockerfile.oid4vc-verification`:
- Line 24: The Dockerfile currently runs "npx prisma migrate deploy" in the
image CMD (the CMD line invoking prisma migrate deploy && npx prisma generate &&
node dist/apps/oid4vc-verification/main.js), which risks concurrent migrations
for multi-replica deployments; remove the migration step from the CMD so the
container only starts the app (keep npx prisma generate if you need runtime
codegen, or better run generate at build time), and instead run migrations as a
one-time operation outside the replica containers (e.g., a Kubernetes Job, Helm
pre-install hook, or an init container that is executed once), updating the
Dockerfile's CMD to only start the app (refer to the CMD invocation and the "npx
prisma migrate deploy" token to locate the change).
- Around line 4-8: Copy the repository lockfile before installing dependencies
and pin the pnpm version instead of using "latest": update the Dockerfile so the
COPY step includes pnpm-lock.yaml (e.g., change COPY package.json
pnpm-workspace.yaml ./ to COPY package.json pnpm-workspace.yaml pnpm-lock.yaml
./) and move that COPY to occur before the RUN pnpm i --ignore-scripts, and
replace RUN npm install -g pnpm@latest with a pinned version like RUN npm
install -g pnpm@<PINNED_VERSION> (use the repo's agreed pnpm version); apply the
same two changes (include pnpm-lock.yaml in the pre-install copy and pin pnpm)
to all Dockerfiles in the repo.

In `@Dockerfiles/Dockerfile.seed`:
- Around line 10-18: The Dockerfile runs COPY --chown=nextjs:nodejs but then
executes RUN pnpm i and RUN cd libs/prisma-service && npx prisma generate as
root and later switches to USER nextjs for the CMD, which causes root-owned
node_modules/ and Prisma client files; to fix, keep the install/generate steps
as root but immediately chown the installed artefacts (e.g., chown -R
nextjs:nodejs node_modules libs/prisma-service/.prisma and generated client
files) before the USER nextjs directive, and remove the redundant COPY
pnpm-workspace.yaml ./ since COPY . . already includes it so the file isn't
copied twice; reference the RUN pnpm i, RUN cd libs/prisma-service && npx prisma
generate, COPY --chown=nextjs:nodejs, USER nextjs and CMD lines to locate the
changes.

In `@Dockerfiles/Dockerfile.user`:
- Line 4: Update the RUN instruction that installs pnpm (the line containing
"RUN npm install -g pnpm@latest") to match the other Dockerfiles by pinning pnpm
to a specific version and adding the --ignore-scripts flag (i.e., replace the
unpinned global install with a pinned version plus --ignore-scripts) so
installation is consistent and scripts are not executed during global install.

In `@Dockerfiles/Dockerfile.verification`:
- Around line 4-8: The Dockerfile uses a floating pnpm tag and omits the
lockfile which breaks reproducible builds: replace the floating install (the RUN
npm install -g pnpm@latest) with a pinned version (e.g., use an ARG PNPM_VERSION
and install pnpm@$PNPM_VERSION) and update the copy step (the COPY package.json
pnpm-workspace.yaml ./) to also copy pnpm-lock.yaml so the RUN pnpm i
--ignore-scripts layer uses the lockfile; adjust the Dockerfile to expose the
ARG and use the pinned version when running the install.
- Line 24: The CMD in Dockerfile.verification runs "npx prisma migrate deploy"
and "npx prisma generate" at container startup (inside CMD ["sh", "-c", "cd
libs/prisma-service && npx prisma migrate deploy && npx prisma generate && cd
../.. && node dist/apps/verification/main.js"]), which risks concurrent
migrations; remove the migration step from the container CMD and instead run
migrations as a separate one-off init job or deployment hook (keep prisma
generate in startup only if necessary), leaving the CMD to only start the app
(node dist/apps/verification/main.js) after removing "npx prisma migrate deploy"
from the command string and ensuring migration execution is handled by your
deployment pipeline or an init container.

In `@Dockerfiles/Dockerfile.x509`:
- Line 11: The Dockerfile uses "RUN npm run build x509" inconsistent with the
rest of the images that install pnpm and run builds via pnpm; change the build
command from "npm run build x509" to "pnpm run build x509" so the
Dockerfile.x509 uses pnpm for the build step (matching the earlier "pnpm i" and
other Dockerfiles).

In `@Trivy-scann-data/Changes-made.md`:
- Line 41: The sed command in the changes notes (sed -i
's/node:20-alpine3.21/node:24-alpine3.21/g') conflicts with other documentation
that mentions upgrading from Node 18 to 24 and a separate note claiming 20→24;
verify the actual base images in your Dockerfiles and then make the docs
consistent: if you actually upgraded from node:18-alpineX, update the sed
command and any lines that say "Node.js 20" to "Node.js 18", or if the real
upgrade was 20→24, correct the PR description and AI summary to say 20→24;
ensure the sed snippet (sed -i 's/node:20-alpine3.21/node:24-alpine3.21/g') and
the textual summaries all match the verified source version.
- Around line 175-179: The Markdown list items starting with "Enhanced
Security", "Updated Dependencies", "Performance", "Visibility", and
"Verification" are missing numeric list prefixes and have mismatched bold
markup; update each line to be a properly numbered list (e.g., "1. Enhanced
Security: Eliminated critical and most high-severity vulnerabilities") ensuring
consistent numbering (1.-5.), fix the bolding so it surrounds only the intended
text (if needed use **text**), and verify blank line or two-space line breaks
are correct so the list renders as separate numbered items.

---

Duplicate comments:
In `@Dockerfiles/Dockerfile.notification`:
- Around line 1-24: This Dockerfile repeats cross-cutting issues: avoid copying
full dev node_modules from the build stage and invoking npx at runtime; instead
produce a production-only node_modules in the build stage (use pnpm install
--prod or pnpm prune --prod in the build stage after building), remove dev-only
tooling from the final image, and change the startup CMD to run the app binary
directly without running npx during container start; also ensure Prisma
migration/generate steps are handled safely (either run migrations as part of
CI/deploy or run migration commands from an init container or an entrypoint
script that ensures proper DB credentials and filesystem permissions for the
nextjs user) — update the Dockerfile lines involving RUN pnpm i
--ignore-scripts, COPY --from=build --chown=nextjs:nodejs /app/node_modules,
USER nextjs, and CMD ["sh", "-c", "cd libs/prisma-service && npx prisma migrate
deploy && npx prisma generate && cd ../.. && node
dist/apps/notification/main.js"] accordingly.

In `@Dockerfiles/Dockerfile.oid4vc-issuance`:
- Around line 1-24: The Dockerfile repeats cross-cutting issues: pin pnpm
version instead of installing latest (replace RUN npm install -g pnpm@latest
with a specific version), ensure a lockfile is copied and used (COPY
pnpm-lock.yaml before running pnpm i and run pnpm install --frozen-lockfile),
avoid copying the entire libs/ into the runtime image (only copy necessary built
artifacts from /app/dist or specific libs needed by oid4vc-issuance instead of
COPY --from=build --chown=nextjs:nodejs /app/libs/ ./libs/), and remove runtime
schema changes from CMD (do not run prisma migrate deploy in CMD; run migrations
during image build or via a separate migration step and keep CMD to start node
dist/apps/oid4vc-issuance/main.js).

In `@Dockerfiles/Dockerfile.organization`:
- Around line 1-24: This Dockerfile repeats the cross-cutting issues: pin pnpm
instead of using RUN npm install -g pnpm@latest, copy the lockfile
(pnpm-lock.yaml) into the build stage before RUN pnpm i --ignore-scripts so
installs are reproducible, move runtime schema migrations out of the container
CMD (the long CMD that runs "cd libs/prisma-service && npx prisma migrate deploy
&& npx prisma generate && ...") into a controlled deploy/init step or run only
prisma generate at build time (use RUN in the build stage to npx prisma generate
after copying schema), avoid copying the entire libs/ directory into the final
image (replace COPY --from=build --chown=nextjs:nodejs /app/libs/ ./libs/ with
only the needed built artifacts or the prisma service output), and replace
misleading user/group names (adduser nextjs/ nodejs) with neutral names like
appuser/appgroup or align names with project conventions; ensure ENV
PUPPETEER_SKIP_DOWNLOAD is still set if required.

In `@Dockerfiles/Dockerfile.utility`:
- Around line 1-24: The Dockerfile repeats cross-cutting issues: remove the
global pnpm install and instead enable Corepack or use pnpm from the build base,
set NODE_ENV=production, install only production dependencies during the build
(replace "RUN pnpm i --ignore-scripts" with a deterministic production install
such as "pnpm install --frozen-lockfile --prod" in the build stage and avoid
copying the entire node_modules into the final image), ensure prisma codegen
runs at build time ("RUN cd libs/prisma-service && npx prisma generate" is fine)
and remove runtime migration/generation from the CMD (remove "npx prisma migrate
deploy && npx prisma generate" from the CMD so migrations are applied
out-of-band), and keep copying only required artifacts ("COPY --from=build
--chown=nextjs:nodejs /app/dist/apps/utility/ ./dist/apps/utility/" and needed
libs) while preserving non-root user setup (nextjs/nodejs) and minimal layers.

In `@Dockerfiles/Dockerfile.x509`:
- Around line 1-24: Pin pnpm instead of using npm install -g pnpm@latest
(replace the npm install command with a fixed version, e.g., npm install -g
pnpm@X.Y.Z) and ensure you COPY and use the workspace lockfile (pnpm-lock.yaml)
before running pnpm install so installs are reproducible (reference COPY
package.json pnpm-workspace.yaml and RUN pnpm i --ignore-scripts). Remove heavy
COPY of the entire libs/ into the final image and instead copy only the built
output and the generated Prisma client for prisma-service (address COPY
--from=build --chown=nextjs:nodejs /app/libs/ ./libs/ and RUN cd
libs/prisma-service && npx prisma generate in the build stage). Move runtime
migrations out of the container CMD (do not run npx prisma migrate deploy && npx
prisma generate inside CMD); either run migrations during image build or
implement a safe startup entrypoint script that conditionally runs migrations
with proper rights (modify the CMD line referencing prisma migrate deploy && npx
prisma generate accordingly).

---

Nitpick comments:
In `@Dockerfiles/Dockerfile.agent-provisioning`:
- Line 2: The base image is pinned to node:24-alpine3.21 which misses newer
Alpine security patches; update the FROM line in the Dockerfile(s) (the FROM
instruction referencing node:24-alpine3.21) to a newer Alpine variant such as
node:24-alpine3.22 or node:24-alpine3.23 (or later) to pick up security fixes,
and apply the same update to any other Dockerfiles using alpine3.21 (e.g., the
22-22 variant).
- Around line 31-32: Replace the misleading Next.js-specific user/group names:
change the addgroup/adduser calls that create "nodejs" and "nextjs" (see
addgroup -g 1001 -S nodejs and adduser -S nextjs -u 1001) to descriptive names
such as "appgroup"/"appuser" or "credebl"/"credebl"; then update all related
usages across the Dockerfiles—replace any --chown=nextjs:nodejs occurrences with
--chown=appuser:appgroup (or your chosen names) and change USER nextjs to USER
appuser so the image user/group names consistently reflect the CREDEBL project.

In `@Dockerfiles/Dockerfile.agent-service`:
- Around line 21-27: Remove unused runtime packages from the Stage 2 RUN layer:
eliminate aws-cli, docker, docker-compose, and openssh-client from the apk add
list in the Dockerfile.agent-service runtime stage so the image only installs
required packages (e.g., openssl) for running node
dist/apps/agent-service/main.js and Prisma migrations; update the RUN command to
only add necessary packages and keep the rm -rf /var/cache/apk/* cleanup to
minimize image size and attack surface.

In `@Dockerfiles/Dockerfile.oid4vc-verification`:
- Around line 14-18: The Dockerfile uses misleading non-root user/group names
"nodejs" and "nextjs" in the addgroup and adduser commands; update these
invocations (addgroup -g 1001 -S nodejs and adduser -S nextjs -u 1001) to use
generic names such as appgroup and appuser (e.g., addgroup -g 1001 -S appgroup
and adduser -S appuser -u 1001) and apply the same rename consistently across
all Dockerfiles in the PR so service images no longer reference Next.js-specific
identifiers.
- Around line 20-22: The Dockerfile currently copies the entire /app/libs/
directory into the final image (COPY --from=build --chown=nextjs:nodejs
/app/libs/ ./libs/), which pulls unnecessary source and bloats the image; update
that COPY to only copy the runtime-required library (e.g., COPY --from=build
--chown=nextjs:nodejs /app/libs/prisma-service ./libs/prisma-service/) and any
specific subpaths it needs (migrations, generated client, schema) so only
prisma-service artifacts are included; keep the existing node_modules and other
needed COPY lines but avoid copying the rest of /app/libs/.

In `@Dockerfiles/Dockerfile.seed`:
- Around line 1-8: Current Dockerfile.seed creates a single-stage image that
installs build-time tools like pnpm and leaves source/dependencies in the
runtime image; convert it to a multi-stage build: add a builder stage (FROM
node:24-alpine3.21 AS builder) that runs apk add and RUN npm install -g
pnpm@latest, installs dependencies and builds the prisma-service, then create a
slim final stage (FROM node:24-alpine3.21) that only copies the built artifacts,
necessary node_modules, and runtime files from the builder, re-creates the
runtime user/group (addgroup/adduser nextjs), and omits pnpm and other
build-time packages (postgresql-client/openssl) to minimize image size and
attack surface.

In `@Dockerfiles/Dockerfile.user`:
- Around line 20-22: The Dockerfile is copying the entire node_modules from the
build stage (see the COPY --from=build --chown=nextjs:nodejs /app/node_modules
./node_modules line), which brings devDependencies into the production image;
update the build stage to install only production dependencies (e.g., run pnpm
deploy --prod or pnpm prune --prod or pnpm install --prod in the build stage)
and then remove or change the final stage copy so it only includes the pruned
production node_modules (or avoid copying node_modules and use a production-only
installation in the final stage); ensure the change is applied to the same COPY
invocation and any equivalent COPY lines across the other Dockerfiles in the PR.

In `@package.json`:
- Around line 59-63: Package.json currently lists type declaration packages
("@types/async-retry", "@types/crypto-js", "@types/json2csv", "@types/pdfkit")
under dependencies; move each of these entries out of dependencies and into
devDependencies (preserving their versions) so they are only installed for
TypeScript compilation. Remove the entries from dependencies and add them to
devDependencies (or run the equivalent package manager command, e.g., npm/yarn
add --save-dev) and update any lockfile accordingly.

In `@Trivy-scann-data/Before-detailed-vulnerability-report.md`:
- Around line 1-97: Add a new "After" scan section to the report that shows
Trivy results for the rebuilt images (post-Node24 and dependency updates): run
Trivy on the same image list (the entries under "## Images Scanned") using the
rebuilt image tags, include scan timestamp, per-image vulnerability counts and a
CVE diff table mapping which CVEs from the "## Critical Vulnerabilities Found"
and "## High Severity Vulnerabilities Found" sections were fixed vs. still
present (reference the report headers "Docker Images Vulnerability Scan Report",
"## Images Scanned", and the listed CVEs), and include a short CI note in "##
Recommendations" describing the command used (e.g., trivy image ...) and where
the after-scan artifacts are stored.

In `@Trivy-scann-data/Changes-made.md`:
- Around line 46-47: The documented installation line "sudo curl -sfL
https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh |
sudo sh -s -- -b /usr/local/bin" is a security anti-pattern; update
Changes-made.md to replace that single-line recommendation with guidance to
first download the installer, inspect/verify it (or verify a
checksum/signature), then run it with elevated privileges, or alternatively
recommend installing Trivy via a supported package manager or release binary;
mention the exact snippet text so the maintainer can locate and replace it.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e516d40 and 857ad18.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (23)
  • Dockerfiles/Dockerfile.agent-provisioning
  • Dockerfiles/Dockerfile.agent-service
  • Dockerfiles/Dockerfile.api-gateway
  • Dockerfiles/Dockerfile.cloud-wallet
  • Dockerfiles/Dockerfile.connection
  • Dockerfiles/Dockerfile.ecosystem
  • Dockerfiles/Dockerfile.geolocation
  • Dockerfiles/Dockerfile.issuance
  • Dockerfiles/Dockerfile.ledger
  • Dockerfiles/Dockerfile.notification
  • Dockerfiles/Dockerfile.oid4vc-issuance
  • Dockerfiles/Dockerfile.oid4vc-verification
  • Dockerfiles/Dockerfile.organization
  • Dockerfiles/Dockerfile.seed
  • Dockerfiles/Dockerfile.user
  • Dockerfiles/Dockerfile.utility
  • Dockerfiles/Dockerfile.verification
  • Dockerfiles/Dockerfile.webhook
  • Dockerfiles/Dockerfile.x509
  • Trivy-scann-data/After-vulnerability-scan-report.md
  • Trivy-scann-data/Before-detailed-vulnerability-report.md
  • Trivy-scann-data/Changes-made.md
  • package.json

&& rm -rf /var/cache/apk/*

# Set the working directory
RUN npm install -g pnpm@latest --ignore-scripts
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Pin pnpm to a specific version for reproducible builds.

pnpm@latest resolves to whatever version is current at build time, making builds non-reproducible and potentially introducing breaking changes. This applies to all 19 Dockerfiles.

Proposed fix
-RUN npm install -g pnpm@latest --ignore-scripts
+RUN npm install -g pnpm@9.15.4 --ignore-scripts

Replace 9.15.4 with whatever version the project is currently using (check packageManager in package.json or the lockfile).

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
RUN npm install -g pnpm@latest --ignore-scripts
RUN npm install -g pnpm@9.15.4 --ignore-scripts
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.agent-provisioning` at line 11, The Dockerfile
currently installs pnpm with a floating tag ("RUN npm install -g pnpm@latest
--ignore-scripts"); change this to pin pnpm to the project's exact version
(replace "@latest" with the version found in package.json's packageManager field
or the lockfile, e.g., "pnpm@9.15.4") so builds are reproducible—update the RUN
line(s) across all Dockerfiles that use "npm install -g pnpm@latest
--ignore-scripts".

&& chmod 755 /app/agent-provisioning/AFJ/token \
&& chown -R nextjs:nodejs /app/agent-provisioning
USER nextjs
CMD ["sh", "-c", "cd libs/prisma-service && npx prisma migrate deploy && npx prisma generate && cd ../.. && node dist/apps/agent-provisioning/main.js"] No newline at end of file
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Running prisma migrate deploy in CMD is risky for multi-replica deployments.

If multiple container replicas start simultaneously, concurrent migration attempts can race and cause failures or data corruption. Migrations should be run as a separate init container or job (e.g., Kubernetes init container), not as part of the application startup command. This concern applies to all Dockerfiles in the PR that use this pattern.

Additionally, running npx prisma generate at startup is redundant — the Prisma client was already generated during the build stage (Line 17). This adds unnecessary startup latency.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.agent-provisioning` at line 49, The Dockerfile's
startup CMD currently runs "prisma migrate deploy" and "npx prisma generate"
which can race in multi-replica starts and redundantly regenerate the client;
remove both commands from the CMD and leave only the app start (e.g., replace
CMD ["sh", "-c", "cd libs/prisma-service && npx prisma migrate deploy && npx
prisma generate && cd ../.. && node dist/apps/agent-provisioning/main.js"] with
a CMD that simply starts the built app like node
dist/apps/agent-provisioning/main.js), and instead run migrations via a separate
migration job or init container (not in application startup); keep the
generation step only in the build stage where Prisma client was already
generated.

Comment on lines +175 to +179
1. Enhanced Security**: Eliminated critical and most high-severity vulnerabilities
2. Updated Dependencies**: All packages updated to latest secure versions
3. Performance**: Node.js 24 provides better performance and security
4. Visibility**: Comprehensive vulnerability scanning and reporting implemented
5. Verification**: Confirmed fixes through post-remediation scanning
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Broken Markdown list formatting — missing list number prefix.

Lines 175–179 appear to have lost their numbered list prefix. They start with emoji but lack the 1., 2., etc., making them render as a single paragraph instead of a list.

Proposed fix
-1.  Enhanced Security**: Eliminated critical and most high-severity vulnerabilities
-2.  Updated Dependencies**: All packages updated to latest secure versions  
-3.  Performance**: Node.js 24 provides better performance and security
-4.  Visibility**: Comprehensive vulnerability scanning and reporting implemented
-5.  Verification**: Confirmed fixes through post-remediation scanning
+1. **Enhanced Security**: Eliminated critical and most high-severity vulnerabilities
+2. **Updated Dependencies**: All packages updated to latest secure versions  
+3. **Performance**: Node.js 24 provides better performance and security
+4. **Visibility**: Comprehensive vulnerability scanning and reporting implemented
+5. **Verification**: Confirmed fixes through post-remediation scanning
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
1. Enhanced Security**: Eliminated critical and most high-severity vulnerabilities
2. Updated Dependencies**: All packages updated to latest secure versions
3. Performance**: Node.js 24 provides better performance and security
4. Visibility**: Comprehensive vulnerability scanning and reporting implemented
5. Verification**: Confirmed fixes through post-remediation scanning
1. **Enhanced Security**: Eliminated critical and most high-severity vulnerabilities
2. **Updated Dependencies**: All packages updated to latest secure versions
3. **Performance**: Node.js 24 provides better performance and security
4. **Visibility**: Comprehensive vulnerability scanning and reporting implemented
5. **Verification**: Confirmed fixes through post-remediation scanning
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Trivy-scann-data/Changes-made.md` around lines 175 - 179, The Markdown list
items starting with "Enhanced Security", "Updated Dependencies", "Performance",
"Visibility", and "Verification" are missing numeric list prefixes and have
mismatched bold markup; update each line to be a properly numbered list (e.g.,
"1. Enhanced Security: Eliminated critical and most high-severity
vulnerabilities") ensuring consistent numbering (1.-5.), fix the bolding so it
surrounds only the intended text (if needed use **text**), and verify blank line
or two-space line breaks are correct so the list renders as separate numbered
items.

Signed-off-by: DeepakNemad <deepak.nemade@ayanworks.com>
Copy link

@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: 19

Note

Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.

♻️ Duplicate comments (6)
Dockerfiles/Dockerfile.connection (1)

8-8: ⚠️ Potential issue | 🟠 Major

Enforce lockfile during install for deterministic builds.

Line 8 installs dependencies without --frozen-lockfile, so builds can still drift despite copying pnpm-lock.yaml.

🔧 Proposed fix
-RUN pnpm i --ignore-scripts
+RUN pnpm i --frozen-lockfile --ignore-scripts
#!/bin/bash
# Verify lockfile enforcement and install command in Dockerfile.connection
rg -nP 'COPY\s+package\.json\s+pnpm-lock\.yaml\s+pnpm-workspace\.yaml' Dockerfiles/Dockerfile.connection
rg -nP 'RUN\s+pnpm\s+i\b(?!.*--frozen-lockfile).*' Dockerfiles/Dockerfile.connection

Expected: first command matches; second command should return no matches after the fix.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.connection` at line 8, The Dockerfile currently runs
"RUN pnpm i --ignore-scripts" which ignores the lockfile and can cause
non-deterministic installs; update the RUN invocation that installs dependencies
(the line containing "RUN pnpm i --ignore-scripts") to enforce the lockfile by
adding the --frozen-lockfile flag (e.g., use pnpm install with --frozen-lockfile
and keep --ignore-scripts if needed) so installs fail when pnpm-lock.yaml is out
of sync.
Dockerfiles/Dockerfile.user (1)

4-4: ⚠️ Potential issue | 🟡 Minor

Add --ignore-scripts to global pnpm install.

Line 4 still allows lifecycle scripts during global install, which weakens container hardening.

Proposed fix
-RUN npm install -g pnpm@9.15.3
+RUN npm install -g pnpm@9.15.3 --ignore-scripts
#!/bin/bash
set -euo pipefail
# Verify global pnpm install commands and whether ignore-scripts is consistently applied
rg -nP 'RUN\s+npm\s+install\s+-g\s+pnpm@' Dockerfiles
rg -nP 'RUN\s+npm\s+install\s+-g\s+pnpm@.*--ignore-scripts' Dockerfiles
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.user` at line 4, The global pnpm install invocation in
the Dockerfile (the RUN npm install -g pnpm@9.15.3 command) allows lifecycle
scripts to run; update that RUN command to include the --ignore-scripts flag so
the global install is hardened (e.g., change the RUN that references pnpm@9.15.3
to include --ignore-scripts), and then scan other Dockerfiles for any other
occurrences of RUN npm install -g pnpm@... to apply the same --ignore-scripts
protection consistently.
Dockerfiles/Dockerfile.oid4vc-verification (1)

8-8: --frozen-lockfile still missing on pnpm i.

pnpm-lock.yaml is now copied before install (resolving half of the previously flagged issue), but the absence of --frozen-lockfile means pnpm can still silently update the lockfile during the build, producing non-deterministic installs.

🐛 Proposed fix
-RUN pnpm i --ignore-scripts
+RUN pnpm i --frozen-lockfile --ignore-scripts
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.oid4vc-verification` at line 8, The pnpm install step
(RUN pnpm i --ignore-scripts) can mutate pnpm-lock.yaml during image build;
update the Dockerfile's RUN invocation to include the --frozen-lockfile flag
(e.g., change RUN pnpm i --ignore-scripts to include --frozen-lockfile) so the
build fails if the lockfile would be altered and ensures deterministic installs.
Dockerfiles/Dockerfile.x509 (1)

11-11: pnpm run build x509 — previous inconsistency resolved.

The build command now correctly uses pnpm instead of npm.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.x509` at line 11, The Dockerfile build step should
consistently use pnpm: update the RUN instruction so it reads "RUN pnpm run
build x509" (see the RUN pnpm run build x509 line) and propagate this change to
any other Dockerfiles or CI scripts still calling npm; also remove any stray
review-marker tokens like "[duplicate_comment]" or "[approve_code_changes]" left
in the commit/comments to avoid clutter.
Dockerfiles/Dockerfile.verification (1)

8-8: ⚠️ Potential issue | 🟠 Major

Install step should fail on lockfile drift.

Line 8 should use frozen lockfile mode so Docker builds remain deterministic.

Suggested fix
-RUN pnpm i --ignore-scripts
+RUN pnpm install --frozen-lockfile --ignore-scripts
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.verification` at line 8, The Dockerfile uses a
non-deterministic install command (RUN pnpm i --ignore-scripts); update this to
run pnpm in frozen lockfile mode so builds fail on lockfile drift by replacing
that command with the equivalent frozen-lockfile invocation (e.g., use the
--frozen-lockfile flag alongside --ignore-scripts) in the Dockerfile's RUN
instruction.
Dockerfiles/Dockerfile.issuance (1)

8-8: ⚠️ Potential issue | 🟠 Major

Enforce lockfile during dependency install.

Line 8 still allows dependency resolution drift. For deterministic and auditable builds, install with a frozen lockfile.

Suggested fix
-RUN pnpm i --ignore-scripts
+RUN pnpm install --frozen-lockfile --ignore-scripts
#!/bin/bash
# Verify all Dockerfiles still using pnpm install without frozen lockfile
rg -nP 'RUN\s+pnpm\s+(?:i|install)\b(?!.*--frozen-lockfile).*--ignore-scripts' Dockerfiles/
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.issuance` at line 8, Replace the Dockerfile RUN entry
that currently reads "RUN pnpm i --ignore-scripts" to enforce the lockfile by
adding pnpm's frozen-lockfile option so installs fail when the lockfile is out
of sync; update the RUN pnpm i --ignore-scripts line to include the
frozen-lockfile flag (so the build is deterministic and auditable).
🟡 Minor comments (5)
Dockerfiles/Dockerfile.connection-22-22 (1)

22-22: ⚠️ Potential issue | 🟡 Minor

Reduce runtime image size and attack surface by copying production dependencies only.

Line 22 copies the full node_modules from the build stage, which includes devDependencies and unnecessary files. Add a production-only pruning step after the build to reduce the runtime image footprint and vulnerability surface.

♻️ Suggested refinement
 RUN pnpm run build connection
+RUN pnpm prune --prod
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.connection` at line 22, The Dockerfile currently
copies the entire node_modules from the build stage via the COPY --from=build
/app/node_modules ./node_modules instruction which pulls devDependencies and
extras into the runtime image; update the build pipeline so that only production
dependencies are present before that COPY (for example run a production prune or
install step in the build stage such as npm ci --only=production or npm prune
--production) and then keep the COPY --from=build /app/node_modules
./node_modules as-is to copy only the pruned production deps; ensure the step
runs in the same build stage referenced as "build" so the runtime image size and
attack surface are reduced.
Dockerfiles/Dockerfile.oid4vc-verification-15-18 (1)

15-18: ⚠️ Potential issue | 🟡 Minor

nodejs group is never used; nextjs user name is mismatched for this service.

Two distinct problems:

  1. addgroup -g 1001 -S nodejs creates a group named nodejs, but adduser -S nextjs -u 1001 does not assign the user to that group. The nodejs group is orphaned and unused.
  2. The user name nextjs is semantically associated with Next.js applications, not an oid4vc-verification service. This is likely a copy-paste artefact from another service's Dockerfile and will cause confusion during incident response or audits.
🐛 Proposed fix
 RUN apk update && apk upgrade && apk add --no-cache openssl \
     && rm -rf /var/cache/apk/* \
-    && addgroup -g 1001 -S nodejs \
-    && adduser -S nextjs -u 1001
+    && addgroup -g 1001 -S nodejs \
+    && adduser -S oid4vc -u 1001 -G nodejs

Then update the downstream references:

-USER nextjs
+USER oid4vc
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.oid4vc-verification` around lines 15 - 18, The
Dockerfile creates an unused group "nodejs" with addgroup and a mismatched user
"nextjs" with adduser; change them so the user and group are consistent and
semantically correct for this service: replace addgroup -g 1001 -S nodejs and
adduser -S nextjs -u 1001 with a single consistent pair (e.g., addgroup -g 1001
-S oid4vc && adduser -S oid4vc -u 1001 -G oid4vc or ensure adduser specifies -G
nodejs to join the nodejs group), and then update any downstream references that
assume the username/group to the new name (look for usages of "nextjs",
"nodejs", addgroup/adduser in this Dockerfile and related service configs).
Dockerfiles/Dockerfile.oid4vc-verification-20-22 (1)

20-22: ⚠️ Potential issue | 🟡 Minor

Files copied before USER nextjs are owned by root — add --chown to all COPY directives.

The three COPY --from=build instructions on lines 20–22 execute before USER nextjs is set, so all copied files are owned by root. If the app writes to any of these paths at runtime (e.g., Prisma's query engine extracting a binary, or log output), it will fail with a permission error because the non-root user has no write access.

The AI-generated summary also states that artifacts were "reduced to only node_modules", but dist/apps/oid4vc-verification/ and libs/ are still copied on lines 20–21.

🐛 Proposed fix
-COPY --from=build /app/dist/apps/oid4vc-verification/ ./dist/apps/oid4vc-verification/
-COPY --from=build /app/libs/ ./libs/
-COPY --from=build /app/node_modules ./node_modules
+COPY --chown=nextjs:nodejs --from=build /app/dist/apps/oid4vc-verification/ ./dist/apps/oid4vc-verification/
+COPY --chown=nextjs:nodejs --from=build /app/libs/ ./libs/
+COPY --chown=nextjs:nodejs --from=build /app/node_modules ./node_modules
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.oid4vc-verification` around lines 20 - 22, The three
COPY --from=build instructions that copy /app/dist/apps/oid4vc-verification/,
/app/libs/, and /app/node_modules are executed as root before USER nextjs, so
change each COPY to include --chown=nextjs:nextjs (or the correct non-root
user/group used by USER nextjs) to ensure files are owned by the runtime user;
update the COPY lines that reference those paths (the COPY --from=build entries)
to add the --chown flag so runtime writes (e.g., Prisma extraction, logs) won’t
fail due to root-only ownership.
Dockerfiles/Dockerfile.x509-17-18 (1)

17-18: ⚠️ Potential issue | 🟡 Minor

nextjs user is not added to the nodejs group.

adduser -S nextjs -u 1001 creates the user without -G nodejs, leaving the nodejs group unused and group-based file permission checks broken for this user. The common pattern used across Next.js and NestJS Dockerfiles pairs these two commands explicitly.

🔧 Proposed fix
-    && adduser -S nextjs -u 1001
+    && adduser -S -G nodejs nextjs -u 1001
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.x509` around lines 17 - 18, The Dockerfile creates a
nodejs group and a nextjs user but doesn't add nextjs to the nodejs group;
update the user creation command so nextjs is a member of nodejs (replace
"adduser -S nextjs -u 1001" with a command that includes the group, e.g.
"adduser -S -G nodejs nextjs -u 1001" or equivalent) so group-based file
permission checks work as expected; look for the commands that create the group
and user (addgroup -g 1001 -S nodejs and adduser -S nextjs -u 1001) and make
them consistent.
Dockerfiles/Dockerfile.x509-4-4 (1)

4-4: ⚠️ Potential issue | 🟡 Minor

Correct the pnpm version claim; the latest release is 10.29.3 (February 2026), not 10.30.2.

The Dockerfile pins pnpm@9.15.3, which the repository has explicitly declared in package.json with a corepack integrity hash. While v9 is now ~14 months behind the latest v10.29.3, this pinning appears intentional.

The main v10 breaking change—dependency lifecycle scripts disabled by default—is already mitigated in the Dockerfile via the --ignore-scripts flag on line 8, which is a best practice. If the team intends to remain on v9, the current setup is sound; if upgrading to v10 is planned, verify that native dependencies and postinstall hooks don't fail without explicit allowlisting in pnpm.onlyBuiltDependencies.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.x509` at line 4, Update the pinned pnpm version in the
Dockerfile RUN instruction from 9.15.3 to 10.29.3 (the current v10 release) or
explicitly document/confirm intent to remain on v9; if upgrading, also update
the repo's package.json/corepack integrity entry to match v10.29.3 and run a
test build to ensure native/postinstall hooks still work given the v10 default
of disabling lifecycle scripts (verify pnpm.onlyBuiltDependencies or
allowlisting for required scripts); otherwise add a comment next to the RUN
pnpm@... line referencing the intentional pin to v9 and why it’s required.
🧹 Nitpick comments (13)
Dockerfiles/Dockerfile.seed (2)

8-8: Optional: use Corepack instead of npm install -g pnpm.

Node 24 ships with Corepack. corepack enable && corepack prepare pnpm@9.15.3 --activate avoids a global npm install and aligns with Node's built-in package manager toolchain.

♻️ Proposed change
-RUN npm install -g pnpm@9.15.3
+RUN corepack enable && corepack prepare pnpm@9.15.3 --activate
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.seed` at line 8, Replace the global npm install of
pnpm (the RUN npm install -g pnpm@9.15.3 line) with Node's Corepack workflow:
enable Corepack and prepare/activate the desired pnpm version (e.g., run
corepack enable && corepack prepare pnpm@9.15.3 --activate) so the Dockerfile
uses the built-in package manager management instead of installing pnpm
globally.

1-1: Consider upgrading the Alpine base to node:24-alpine3.23.

The current Docker Hub tags for node:24 LTS include 24-alpine3.22, 24-alpine3.23, and the floating 24-alpinealpine3.21 is the oldest pinned variant for node:24 and receives no further OS-level security patches. Pinning to node:24-alpine3.23 provides the same reproducibility with a more up-to-date OS base.

♻️ Proposed change
-FROM node:24-alpine3.21
+FROM node:24-alpine3.23
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.seed` at line 1, Update the Docker base image pin used
in the seed Dockerfile: replace the current FROM node:24-alpine3.21 reference
with FROM node:24-alpine3.23 so the container uses the newer Alpine OS variant;
ensure the single FROM line in Dockerfiles/Dockerfile.seed (the literal "FROM
node:24-alpine3.21") is changed to "FROM node:24-alpine3.23" to keep
reproducibility while picking up newer OS security patches.
Dockerfiles/Dockerfile.oid4vc-verification (2)

2-2: Consider upgrading to a more current Alpine variant.

node:24-alpine3.21 is an older Alpine variant; the current Node.js 24 LTS images on Docker Hub are 24-alpine3.22 and 24-alpine3.23. Using a newer Alpine base reduces the exposure to known OS-level CVEs and keeps the apk package index more current.

♻️ Suggested update (apply to both stages)
-FROM node:24-alpine3.21 AS build
+FROM node:24-alpine3.23 AS build
 ...
-FROM node:24-alpine3.21
+FROM node:24-alpine3.23
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.oid4vc-verification` at line 2, Update the Docker base
image from the older Alpine variant to a current one by replacing all
occurrences of "FROM node:24-alpine3.21" (e.g., the "FROM node:24-alpine3.21 AS
build" line and any other FROM lines using that tag) with a newer tag such as
"node:24-alpine3.22" or "node:24-alpine3.23" in the Dockerfile so both build and
runtime stages use the updated Alpine variant.

4-4: Consider upgrading pnpm to v10.30.2 — The pinned version 9.15.3 is outdated. The current stable major version is 10.x (latest: 10.30.2), which includes improvements in security, performance, and efficiency. Review v10's release notes before upgrading if you're concerned about breaking changes.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.oid4vc-verification` at line 4, Update the pinned pnpm
version in the Dockerfile by replacing the existing global install command that
references pnpm@9.15.3 (the RUN npm install -g pnpm@9.15.3 line) to use
pnpm@10.30.2; after changing the version, rebuild the image and run your
standard dependency/install workflows to verify there are no breaking changes
from v10, and consult v10 release notes if any test failures occur.
Dockerfiles/Dockerfile.webhook (2)

8-8: Add --frozen-lockfile to ensure reproducible dependency installs.

The --frozen-lockfile flag prevents updates to the lockfile during CI builds; the pnpm-lock.yaml file ensures reproducible builds by capturing exact dependency versions, preventing "works on my machine" problems by guaranteeing every environment uses identical dependencies. Without it, pnpm can silently resolve different versions inside the Docker layer if the lockfile drifts from package.json.

♻️ Proposed fix
-RUN pnpm i --ignore-scripts
+RUN pnpm i --frozen-lockfile --ignore-scripts
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.webhook` at line 8, Update the Dockerfile command that
installs JS dependencies to use pnpm's frozen lockfile mode: modify the RUN pnpm
i --ignore-scripts invocation (in Dockerfile.webhook) to include the
--frozen-lockfile flag so the build will fail if pnpm-lock.yaml and package.json
disagree, ensuring reproducible installs in CI.

4-4: Consider using corepack to manage pnpm instead of a global npm install.

corepack is bundled with Node.js 24 but requires explicit activation. Using corepack enable && corepack prepare pnpm@9.15.3 --activate is the modern, idiomatic approach for managing pinned package manager versions without separate npm install -g steps.

♻️ Suggested alternative
-RUN npm install -g pnpm@9.15.3
+RUN corepack enable && corepack prepare pnpm@9.15.3 --activate
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.webhook` at line 4, Replace the global npm install
command with Corepack activation and preparation to pin pnpm: instead of running
"npm install -g pnpm@9.15.3" use Corepack flow by running "corepack enable" and
then "corepack prepare pnpm@9.15.3 --activate" so the Dockerfile uses Corepack
to manage the pnpm version; ensure Node runtime in the image supports Corepack
(Node 24+) or enable Corepack beforehand and verify the RUN step references the
same pnpm version (9.15.3) used elsewhere.
Dockerfiles/Dockerfile.geolocation (3)

8-8: Add --frozen-lockfile to ensure reproducible builds.

Without --frozen-lockfile, pnpm can silently modify pnpm-lock.yaml during install if it detects drift, producing non-deterministic images across builds.

♻️ Proposed fix
-RUN pnpm i --ignore-scripts
+RUN pnpm i --frozen-lockfile --ignore-scripts
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.geolocation` at line 8, Update the
Dockerfile.geolocation RUN command that currently invokes "pnpm i
--ignore-scripts" to add the --frozen-lockfile flag so installs fail if
pnpm-lock.yaml is out of sync; locate the RUN line with "pnpm i
--ignore-scripts" and modify it to include --frozen-lockfile to enforce
reproducible, deterministic builds.

15-18: nodejs group is created but never associated with the nextjs user.

adduser -S nextjs -u 1001 creates the nextjs user with a primary group also named nextjs, not nodejs. The nodejs group (GID 1001) is unused. Either add the user to the nodejs group or rename the group to match the user for clarity.

♻️ Proposed fix (consistent naming)
 RUN apk update && apk upgrade && apk add --no-cache openssl \
     && rm -rf /var/cache/apk/* \
-    && addgroup -g 1001 -S nodejs \
-    && adduser -S nextjs -u 1001
+    && addgroup -g 1001 -S nodejs \
+    && adduser -S nextjs -u 1001 -G nodejs
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.geolocation` around lines 15 - 18, The Dockerfile
creates a group with addgroup -g 1001 -S nodejs but then creates a user with
adduser -S nextjs -u 1001 which results in a separate primary group named
nextjs; update the user/group pairing so they match by either creating the group
with the same name as the user (change addgroup to use nextjs) or explicitly add
the nextjs user to the nodejs group (use adduser/addgroup flags to set the
primary/group membership), ensuring the symbols addgroup, adduser, nodejs, and
nextjs are adjusted consistently.

2-2: Update node:24-alpine3.21 to node:24-alpine3.23 on both build and final stages.

Node 24 currently tracks Alpine 3.23. Alpine 3.21 reached support status with "main-only" patches until 2026-11-01, while 3.23 receives "main + community" patches until 2027-11-01, providing longer security coverage and broader patch availability. Upgrading both FROM instructions to node:24-alpine3.23 aligns with the current LTS default.

Also applies to: 14-14

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.geolocation` at line 2, Update the Dockerfile base
image tags: replace the FROM image tag node:24-alpine3.21 with
node:24-alpine3.23 in both occurrences (the build stage and the final stage FROM
lines) so both stages use node:24-alpine3.23 to align with current Node 24
Alpine tracking and extended patch support.
Dockerfiles/Dockerfile.utility (1)

15-18: Bind nextjs to the created nodejs group explicitly.

addgroup is created but not explicitly used by adduser; making membership explicit avoids UID/GID ambiguity across environments.

Proposed fix
 RUN apk update && apk upgrade && apk add --no-cache openssl \
     && rm -rf /var/cache/apk/* \
     && addgroup -g 1001 -S nodejs \
-    && adduser -S nextjs -u 1001
+    && adduser -S nextjs -u 1001 -G nodejs
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.utility` around lines 15 - 18, The created group
nodejs is not being used when creating the nextjs user; update the adduser
invocation so nextjs is explicitly added to the nodejs group (e.g., use the
adduser flag to set primary group to nodejs) to avoid UID/GID ambiguity — change
the adduser command that currently references nextjs and UID 1001 to include the
nodejs group reference so nextjs is bound to nodejs.
Dockerfiles/Dockerfile.x509 (2)

20-22: Add --chown=nextjs:nodejs to all COPY instructions before the USER switch.

Without --chown, all copied files are owned by root:root. The nextjs user can still read them (world-readable defaults), but any runtime write (e.g., caches, temp files under /app) will fail. Applying --chown is the canonical pattern for least-privilege containers.

🔧 Proposed fix
-COPY --from=build /app/dist/apps/x509/ ./dist/apps/x509/
-COPY --from=build /app/libs/ ./libs/
-COPY --from=build /app/node_modules ./node_modules
+COPY --chown=nextjs:nodejs --from=build /app/dist/apps/x509/ ./dist/apps/x509/
+COPY --chown=nextjs:nodejs --from=build /app/libs/ ./libs/
+COPY --chown=nextjs:nodejs --from=build /app/node_modules ./node_modules
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.x509` around lines 20 - 22, The three COPY
instructions (COPY --from=build /app/dist/apps/x509/ ./dist/apps/x509/, COPY
--from=build /app/libs/ ./libs/, COPY --from=build /app/node_modules
./node_modules) should include ownership flag --chown=nextjs:nodejs so files
aren't root-owned when the Dockerfile later switches to the USER; update those
COPY lines to add --chown=nextjs:nodejs (before the USER switch) to ensure
nextjs can write caches/temp files at runtime.

8-8: Use --frozen-lockfile to prevent silent lockfile drift in CI/Docker builds.

pnpm i without --frozen-lockfile will silently update pnpm-lock.yaml if it's out of sync, producing a non-reproducible image. In a Dockerfile, the lockfile should always be the source of truth.

🔧 Proposed fix
-RUN pnpm i --ignore-scripts
+RUN pnpm i --frozen-lockfile --ignore-scripts
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.x509` at line 8, Replace the plain pnpm install
invocation in the Dockerfile RUN step with one that enforces the lockfile to
avoid drift: change the RUN command that currently calls "pnpm i" (the RUN pnpm
i --ignore-scripts step) to include the --frozen-lockfile flag (you can keep
--ignore-scripts if needed), so the build fails when pnpm-lock.yaml is out of
sync rather than silently updating it.
Dockerfiles/Dockerfile.agent-service (1)

21-27: Re-validate runtime need for Docker/AWS tooling in final stage.

Lines 21-27 install aws-cli, docker, docker-compose, and openssh-client in the runtime image. If the service doesn’t execute these binaries at runtime, remove them to reduce attack surface and patch churn.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.agent-service` around lines 21 - 27, The runtime
image's RUN layer that installs openssl, openssh-client, aws-cli, docker, and
docker-compose should be reviewed and trimmed: verify whether any runtime code
calls these binaries (search for usage of aws, docker, docker-compose, ssh in
entrypoint, service code, or health scripts) and if they are not required at
runtime remove them from the RUN install line (keep only openssl if TLS/crypto
libs are needed), thereby deleting the aws-cli, docker, docker-compose, and
openssh-client packages from the final image to reduce attack surface; if any
are required, document their usage in the Dockerfile comments and consider
moving build-only tools into a separate build stage.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@Dockerfiles/Dockerfile.agent-provisioning`:
- Line 15: Update the Dockerfile RUN invocation that currently uses "pnpm i
--ignore-scripts" to enforce the committed lockfile during image builds: change
the command to include the --frozen-lockfile flag so pnpm fails if the lockfile
and package manifests diverge (i.e., replace the existing RUN pnpm i
--ignore-scripts invocation in the Dockerfile with one that adds
--frozen-lockfile).

In `@Dockerfiles/Dockerfile.agent-service`:
- Line 14: The runtime image currently contains dev dependencies because the
build stage runs "pnpm i --ignore-scripts" and the node_modules are copied into
the final image; to fix this, in the build stage (the stage that runs "RUN pnpm
i --ignore-scripts" and performs the build) add a step to prune dev dependencies
by running "pnpm prune --prod" after the build is complete and before
node_modules are copied to the final image so only production dependencies
remain in the final image.
- Line 14: Replace the non-deterministic install command in the Dockerfile where
RUN pnpm i --ignore-scripts is used: change the invocation to enforce the
lockfile by adding --frozen-lockfile so pnpm will fail if package.json and the
lockfile diverge, ensuring reproducible builds; update the RUN line that
currently invokes pnpm i --ignore-scripts to include --frozen-lockfile (and keep
--ignore-scripts if needed).

In `@Dockerfiles/Dockerfile.api-gateway`:
- Line 8: Update the Dockerfile RUN invocation that currently executes "RUN pnpm
i --ignore-scripts" to enforce lockfile fidelity by adding the --frozen-lockfile
flag; specifically, modify the RUN command used to install node dependencies
(the line invoking pnpm install with --ignore-scripts) so it includes
--frozen-lockfile to fail the build if pnpm-lock.yaml is out of sync and ensure
reproducible installs.

In `@Dockerfiles/Dockerfile.cloud-wallet`:
- Line 8: The Dockerfile currently runs "pnpm i --ignore-scripts" which allows
installs to ignore the committed lockfile; update the RUN step to enforce the
lockfile by adding pnpm's frozen lockfile option so the build uses the committed
lockfile (i.e., run pnpm install with --frozen-lockfile alongside
--ignore-scripts in the same RUN instruction).

In `@Dockerfiles/Dockerfile.ecosystem`:
- Line 8: The Dockerfile's pnpm install command (RUN pnpm i --ignore-scripts)
doesn't enforce a frozen lockfile; update that command to include the
--frozen-lockfile flag so installs fail if package-lock changes (e.g., change
RUN pnpm i --ignore-scripts to include --frozen-lockfile) to ensure reproducible
builds and prevent accidental lockfile modifications.

In `@Dockerfiles/Dockerfile.geolocation`:
- Line 22: The final image currently copies the full build-stage node_modules
(COPY --from=build /app/node_modules ./node_modules) which includes
devDependencies installed by pnpm i; instead remove that COPY and perform a
production-only install in the final stage (e.g., run pnpm deploy or run pnpm
install with production flags / NODE_ENV=production) so only runtime deps are
included, or alternatively run a separate pnpm i --prod (or pnpm install
--frozen-lockfile --prod) in the final stage; update the Dockerfile.geolocation
final stage to stop copying node_modules from build and invoke the production
install command (keep existing build-stage pnpm i for building artifacts).

In `@Dockerfiles/Dockerfile.oid4vc-issuance`:
- Line 8: The production image currently installs dev deps (RUN pnpm i
--ignore-scripts) and then copies the full /app/node_modules into the final
stage (COPY --from=builder /app/node_modules), so dev packages remain in the
runtime image; after the build step in the builder stage and before the final
stage copies node_modules, run pnpm prune --prod (or pnpm prune --prod --filter
.) to remove devDependencies from node_modules so only production dependencies
are copied into the final image.

In `@Dockerfiles/Dockerfile.organization`:
- Line 22: The runtime image is copying the full node_modules (COPY --from=build
/app/node_modules ./node_modules) which includes devDependencies installed by
pnpm i --ignore-scripts; to fix, add a step in the build stage to prune
devDependencies before the runtime COPY by running pnpm prune --prod (or pnpm
prune --prod --no-optional if desired) after the build completes and before the
node_modules are copied, so the build stage's node_modules only contains
production deps when used by the runtime stage.
- Line 8: The Dockerfile uses a non-deterministic install command: locate the
RUN layer that invokes pnpm (currently written as "pnpm i --ignore-scripts") and
change it to use pnpm's frozen-lockfile mode while preserving ignore-scripts
(i.e., run pnpm install with the --frozen-lockfile flag and keep
--ignore-scripts) so builds use the committed pnpm-lock.yaml and are
reproducible.

In `@Dockerfiles/Dockerfile.seed`:
- Around line 16-18: The CMD currently only runs "npx prisma db seed" (in the
container after chown -R nextjs:nodejs and USER nextjs), which drops the
previous migration step; restore the missing migration by updating the CMD to
run "npx prisma migrate deploy" before "npx prisma db seed" (targeting the same
libs/prisma-service working dir) so migrations are applied prior to seeding;
ensure both commands run as the nextjs user and execute in libs/prisma-service
(e.g., combine or chain migrate deploy then db seed in the CMD).

In `@Dockerfiles/Dockerfile.user`:
- Line 24: The Dockerfile.user currently starts the app directly via CMD
["node", "dist/apps/user/main.js"], which bypasses the package.json "start"
script that runs migrations; update the Dockerfile.user to run migrations before
starting the app (e.g. invoke npx prisma migrate deploy or the "start" script)
or ensure CI/CD runs npx prisma migrate deploy prior to image deployment, or
alternatively implement an init container/job in docker-compose/Kubernetes to
run npx prisma migrate deploy; locate the CMD in Dockerfile.user and replace or
wrap it so migrations (npx prisma migrate deploy) complete successfully before
launching the main process.

In `@Dockerfiles/Dockerfile.utility`:
- Around line 20-22: The runtime image is carrying devDependencies because the
build stage copies the full node_modules into the runtime (see COPY --from=build
/app/node_modules ./node_modules); after the build step in the build stage
(before those COPYs) run a production prune (e.g., execute pnpm prune --prod or
equivalent) to remove devDependencies from /app/node_modules, then ensure the
Dockerfile still uses COPY --from=build /app/node_modules ./node_modules so only
production deps are copied into the runtime image.
- Line 24: The Dockerfile currently sets CMD ["node",
"dist/apps/utility/main.js"] which bypasses the npm start script that runs
prisma migrate deploy, so migrations are never executed; fix by ensuring
migrations run before the app process starts — either change the container
startup to invoke the start script (use the package.json "start" script instead
of directly running node), add an init container that runs npm run start:migrate
or prisma migrate deploy prior to launching the utility container, or add a
pre-deployment step in continuous-delivery.yml to run prisma migrate deploy;
update docker-compose.yml or CI config accordingly to call the start script or
explicit migration command so the database schema is applied before the service
runs.
- Line 8: Replace the existing RUN command "RUN pnpm i --ignore-scripts" with a
frozen-lockfile install; update it to "RUN pnpm i --frozen-lockfile
--ignore-scripts" (or "pnpm install --frozen-lockfile --ignore-scripts") so the
build uses the checked-in pnpm-lock.yaml for deterministic installs while
preserving the original --ignore-scripts behavior.

In `@Dockerfiles/Dockerfile.webhook`:
- Line 2: The Dockerfile uses the superseded base image tag "FROM
node:24-alpine3.21"; update both occurrences of that FROM line to
"node:24-alpine3.23" (or use the floating "node:24-alpine" alias if you want
automatic patch updates) so the build uses the current Alpine variant with
downstream CVE fixes; ensure any other identical FROM lines (e.g., the second
stage) are changed as well.
- Line 22: The final image is copying the full node_modules from the build stage
(COPY --from=build /app/node_modules ./node_modules) which includes
devDependencies; before performing that COPY, run a production prune in the
build stage (e.g., invoke pnpm prune --prod after install/build) or replace the
current build stage with a dedicated production-install stage that installs only
prod deps and then COPY --from=prod-stage /app/node_modules ./node_modules;
update the Dockerfile so the node_modules copied into the final image contains
only production dependencies.

In `@Dockerfiles/Dockerfile.x509`:
- Line 22: The final image is copying /app/node_modules from the build stage
(COPY --from=build /app/node_modules ./node_modules) but the build stage runs
pnpm i without production pruning, so devDependencies are included; update the
build stage to perform a production-only install (e.g., run pnpm install --prod
or set NODE_ENV=production and run pnpm install, or run pnpm prune --prod after
install) so that /app/node_modules in the build stage contains only production
deps before the COPY; ensure the command in the Dockerfile that currently runs
pnpm i is replaced or followed by the production-prune step so the final COPY
only brings production packages.
- Line 24: The container currently bypasses migrations by using the raw CMD
["node", "dist/apps/x509/main.js"] while the package.json "start" script runs
npx prisma migrate deploy; fix by ensuring prisma migrations run before app
start: either (A) change the image entry to run the existing "start" script (use
npm start) or add an entrypoint that runs npx prisma migrate deploy
--schema=./libs/prisma-service/prisma/schema.prisma before launching node, or
(B) move migrations out of the container and add a dedicated deployment step (CI
job), a Kubernetes initContainer, or a Helm pre-upgrade hook that executes
prisma migrate deploy; pick one approach and apply consistently across all
services (replace the raw CMD in Dockerfile.x509 and analogous Dockerfiles or
add the CI/K8s/Helm migration step).

---

Minor comments:
In `@Dockerfiles/Dockerfile.connection`:
- Line 22: The Dockerfile currently copies the entire node_modules from the
build stage via the COPY --from=build /app/node_modules ./node_modules
instruction which pulls devDependencies and extras into the runtime image;
update the build pipeline so that only production dependencies are present
before that COPY (for example run a production prune or install step in the
build stage such as npm ci --only=production or npm prune --production) and then
keep the COPY --from=build /app/node_modules ./node_modules as-is to copy only
the pruned production deps; ensure the step runs in the same build stage
referenced as "build" so the runtime image size and attack surface are reduced.

In `@Dockerfiles/Dockerfile.oid4vc-verification`:
- Around line 15-18: The Dockerfile creates an unused group "nodejs" with
addgroup and a mismatched user "nextjs" with adduser; change them so the user
and group are consistent and semantically correct for this service: replace
addgroup -g 1001 -S nodejs and adduser -S nextjs -u 1001 with a single
consistent pair (e.g., addgroup -g 1001 -S oid4vc && adduser -S oid4vc -u 1001
-G oid4vc or ensure adduser specifies -G nodejs to join the nodejs group), and
then update any downstream references that assume the username/group to the new
name (look for usages of "nextjs", "nodejs", addgroup/adduser in this Dockerfile
and related service configs).
- Around line 20-22: The three COPY --from=build instructions that copy
/app/dist/apps/oid4vc-verification/, /app/libs/, and /app/node_modules are
executed as root before USER nextjs, so change each COPY to include
--chown=nextjs:nextjs (or the correct non-root user/group used by USER nextjs)
to ensure files are owned by the runtime user; update the COPY lines that
reference those paths (the COPY --from=build entries) to add the --chown flag so
runtime writes (e.g., Prisma extraction, logs) won’t fail due to root-only
ownership.

In `@Dockerfiles/Dockerfile.x509`:
- Around line 17-18: The Dockerfile creates a nodejs group and a nextjs user but
doesn't add nextjs to the nodejs group; update the user creation command so
nextjs is a member of nodejs (replace "adduser -S nextjs -u 1001" with a command
that includes the group, e.g. "adduser -S -G nodejs nextjs -u 1001" or
equivalent) so group-based file permission checks work as expected; look for the
commands that create the group and user (addgroup -g 1001 -S nodejs and adduser
-S nextjs -u 1001) and make them consistent.
- Line 4: Update the pinned pnpm version in the Dockerfile RUN instruction from
9.15.3 to 10.29.3 (the current v10 release) or explicitly document/confirm
intent to remain on v9; if upgrading, also update the repo's
package.json/corepack integrity entry to match v10.29.3 and run a test build to
ensure native/postinstall hooks still work given the v10 default of disabling
lifecycle scripts (verify pnpm.onlyBuiltDependencies or allowlisting for
required scripts); otherwise add a comment next to the RUN pnpm@... line
referencing the intentional pin to v9 and why it’s required.

---

Duplicate comments:
In `@Dockerfiles/Dockerfile.connection`:
- Line 8: The Dockerfile currently runs "RUN pnpm i --ignore-scripts" which
ignores the lockfile and can cause non-deterministic installs; update the RUN
invocation that installs dependencies (the line containing "RUN pnpm i
--ignore-scripts") to enforce the lockfile by adding the --frozen-lockfile flag
(e.g., use pnpm install with --frozen-lockfile and keep --ignore-scripts if
needed) so installs fail when pnpm-lock.yaml is out of sync.

In `@Dockerfiles/Dockerfile.issuance`:
- Line 8: Replace the Dockerfile RUN entry that currently reads "RUN pnpm i
--ignore-scripts" to enforce the lockfile by adding pnpm's frozen-lockfile
option so installs fail when the lockfile is out of sync; update the RUN pnpm i
--ignore-scripts line to include the frozen-lockfile flag (so the build is
deterministic and auditable).

In `@Dockerfiles/Dockerfile.oid4vc-verification`:
- Line 8: The pnpm install step (RUN pnpm i --ignore-scripts) can mutate
pnpm-lock.yaml during image build; update the Dockerfile's RUN invocation to
include the --frozen-lockfile flag (e.g., change RUN pnpm i --ignore-scripts to
include --frozen-lockfile) so the build fails if the lockfile would be altered
and ensures deterministic installs.

In `@Dockerfiles/Dockerfile.user`:
- Line 4: The global pnpm install invocation in the Dockerfile (the RUN npm
install -g pnpm@9.15.3 command) allows lifecycle scripts to run; update that RUN
command to include the --ignore-scripts flag so the global install is hardened
(e.g., change the RUN that references pnpm@9.15.3 to include --ignore-scripts),
and then scan other Dockerfiles for any other occurrences of RUN npm install -g
pnpm@... to apply the same --ignore-scripts protection consistently.

In `@Dockerfiles/Dockerfile.verification`:
- Line 8: The Dockerfile uses a non-deterministic install command (RUN pnpm i
--ignore-scripts); update this to run pnpm in frozen lockfile mode so builds
fail on lockfile drift by replacing that command with the equivalent
frozen-lockfile invocation (e.g., use the --frozen-lockfile flag alongside
--ignore-scripts) in the Dockerfile's RUN instruction.

In `@Dockerfiles/Dockerfile.x509`:
- Line 11: The Dockerfile build step should consistently use pnpm: update the
RUN instruction so it reads "RUN pnpm run build x509" (see the RUN pnpm run
build x509 line) and propagate this change to any other Dockerfiles or CI
scripts still calling npm; also remove any stray review-marker tokens like
"[duplicate_comment]" or "[approve_code_changes]" left in the commit/comments to
avoid clutter.

---

Nitpick comments:
In `@Dockerfiles/Dockerfile.agent-service`:
- Around line 21-27: The runtime image's RUN layer that installs openssl,
openssh-client, aws-cli, docker, and docker-compose should be reviewed and
trimmed: verify whether any runtime code calls these binaries (search for usage
of aws, docker, docker-compose, ssh in entrypoint, service code, or health
scripts) and if they are not required at runtime remove them from the RUN
install line (keep only openssl if TLS/crypto libs are needed), thereby deleting
the aws-cli, docker, docker-compose, and openssh-client packages from the final
image to reduce attack surface; if any are required, document their usage in the
Dockerfile comments and consider moving build-only tools into a separate build
stage.

In `@Dockerfiles/Dockerfile.geolocation`:
- Line 8: Update the Dockerfile.geolocation RUN command that currently invokes
"pnpm i --ignore-scripts" to add the --frozen-lockfile flag so installs fail if
pnpm-lock.yaml is out of sync; locate the RUN line with "pnpm i
--ignore-scripts" and modify it to include --frozen-lockfile to enforce
reproducible, deterministic builds.
- Around line 15-18: The Dockerfile creates a group with addgroup -g 1001 -S
nodejs but then creates a user with adduser -S nextjs -u 1001 which results in a
separate primary group named nextjs; update the user/group pairing so they match
by either creating the group with the same name as the user (change addgroup to
use nextjs) or explicitly add the nextjs user to the nodejs group (use
adduser/addgroup flags to set the primary/group membership), ensuring the
symbols addgroup, adduser, nodejs, and nextjs are adjusted consistently.
- Line 2: Update the Dockerfile base image tags: replace the FROM image tag
node:24-alpine3.21 with node:24-alpine3.23 in both occurrences (the build stage
and the final stage FROM lines) so both stages use node:24-alpine3.23 to align
with current Node 24 Alpine tracking and extended patch support.

In `@Dockerfiles/Dockerfile.oid4vc-verification`:
- Line 2: Update the Docker base image from the older Alpine variant to a
current one by replacing all occurrences of "FROM node:24-alpine3.21" (e.g., the
"FROM node:24-alpine3.21 AS build" line and any other FROM lines using that tag)
with a newer tag such as "node:24-alpine3.22" or "node:24-alpine3.23" in the
Dockerfile so both build and runtime stages use the updated Alpine variant.
- Line 4: Update the pinned pnpm version in the Dockerfile by replacing the
existing global install command that references pnpm@9.15.3 (the RUN npm install
-g pnpm@9.15.3 line) to use pnpm@10.30.2; after changing the version, rebuild
the image and run your standard dependency/install workflows to verify there are
no breaking changes from v10, and consult v10 release notes if any test failures
occur.

In `@Dockerfiles/Dockerfile.seed`:
- Line 8: Replace the global npm install of pnpm (the RUN npm install -g
pnpm@9.15.3 line) with Node's Corepack workflow: enable Corepack and
prepare/activate the desired pnpm version (e.g., run corepack enable && corepack
prepare pnpm@9.15.3 --activate) so the Dockerfile uses the built-in package
manager management instead of installing pnpm globally.
- Line 1: Update the Docker base image pin used in the seed Dockerfile: replace
the current FROM node:24-alpine3.21 reference with FROM node:24-alpine3.23 so
the container uses the newer Alpine OS variant; ensure the single FROM line in
Dockerfiles/Dockerfile.seed (the literal "FROM node:24-alpine3.21") is changed
to "FROM node:24-alpine3.23" to keep reproducibility while picking up newer OS
security patches.

In `@Dockerfiles/Dockerfile.utility`:
- Around line 15-18: The created group nodejs is not being used when creating
the nextjs user; update the adduser invocation so nextjs is explicitly added to
the nodejs group (e.g., use the adduser flag to set primary group to nodejs) to
avoid UID/GID ambiguity — change the adduser command that currently references
nextjs and UID 1001 to include the nodejs group reference so nextjs is bound to
nodejs.

In `@Dockerfiles/Dockerfile.webhook`:
- Line 8: Update the Dockerfile command that installs JS dependencies to use
pnpm's frozen lockfile mode: modify the RUN pnpm i --ignore-scripts invocation
(in Dockerfile.webhook) to include the --frozen-lockfile flag so the build will
fail if pnpm-lock.yaml and package.json disagree, ensuring reproducible installs
in CI.
- Line 4: Replace the global npm install command with Corepack activation and
preparation to pin pnpm: instead of running "npm install -g pnpm@9.15.3" use
Corepack flow by running "corepack enable" and then "corepack prepare
pnpm@9.15.3 --activate" so the Dockerfile uses Corepack to manage the pnpm
version; ensure Node runtime in the image supports Corepack (Node 24+) or enable
Corepack beforehand and verify the RUN step references the same pnpm version
(9.15.3) used elsewhere.

In `@Dockerfiles/Dockerfile.x509`:
- Around line 20-22: The three COPY instructions (COPY --from=build
/app/dist/apps/x509/ ./dist/apps/x509/, COPY --from=build /app/libs/ ./libs/,
COPY --from=build /app/node_modules ./node_modules) should include ownership
flag --chown=nextjs:nodejs so files aren't root-owned when the Dockerfile later
switches to the USER; update those COPY lines to add --chown=nextjs:nodejs
(before the USER switch) to ensure nextjs can write caches/temp files at
runtime.
- Line 8: Replace the plain pnpm install invocation in the Dockerfile RUN step
with one that enforces the lockfile to avoid drift: change the RUN command that
currently calls "pnpm i" (the RUN pnpm i --ignore-scripts step) to include the
--frozen-lockfile flag (you can keep --ignore-scripts if needed), so the build
fails when pnpm-lock.yaml is out of sync rather than silently updating it.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 857ad18 and aaed3a4.

📒 Files selected for processing (19)
  • Dockerfiles/Dockerfile.agent-provisioning
  • Dockerfiles/Dockerfile.agent-service
  • Dockerfiles/Dockerfile.api-gateway
  • Dockerfiles/Dockerfile.cloud-wallet
  • Dockerfiles/Dockerfile.connection
  • Dockerfiles/Dockerfile.ecosystem
  • Dockerfiles/Dockerfile.geolocation
  • Dockerfiles/Dockerfile.issuance
  • Dockerfiles/Dockerfile.ledger
  • Dockerfiles/Dockerfile.notification
  • Dockerfiles/Dockerfile.oid4vc-issuance
  • Dockerfiles/Dockerfile.oid4vc-verification
  • Dockerfiles/Dockerfile.organization
  • Dockerfiles/Dockerfile.seed
  • Dockerfiles/Dockerfile.user
  • Dockerfiles/Dockerfile.utility
  • Dockerfiles/Dockerfile.verification
  • Dockerfiles/Dockerfile.webhook
  • Dockerfiles/Dockerfile.x509
🚧 Files skipped from review as they are similar to previous changes (1)
  • Dockerfiles/Dockerfile.notification

ENV PUPPETEER_SKIP_DOWNLOAD=true

# Install dependencies while ignoring scripts (including Puppeteer's installation)
RUN pnpm i --ignore-scripts
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n Dockerfiles/Dockerfile.agent-service

Repository: credebl/platform

Length of output: 1342


Remove dev dependencies from the runtime image.

The node_modules copied at Line 33 includes dev dependencies from the full install at Line 14. This increases the image size and CVE surface unnecessarily.

Add RUN pnpm prune --prod after the build step (after Line 17, in the build stage) to remove dev dependencies before the copy.

Proposed change
 RUN cd libs/prisma-service && npx prisma generate
 RUN pnpm run build agent-service
+RUN pnpm prune --prod
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.agent-service` at line 14, The runtime image currently
contains dev dependencies because the build stage runs "pnpm i --ignore-scripts"
and the node_modules are copied into the final image; to fix this, in the build
stage (the stage that runs "RUN pnpm i --ignore-scripts" and performs the build)
add a step to prune dev dependencies by running "pnpm prune --prod" after the
build is complete and before node_modules are copied to the final image so only
production dependencies remain in the final image.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n Dockerfiles/Dockerfile.agent-service

Repository: credebl/platform

Length of output: 1342


🏁 Script executed:

# Check pnpm documentation and common practices for --frozen-lockfile
web_search
pnpm --frozen-lockfile flag docker best practices

Repository: credebl/platform

Length of output: 199


🌐 Web query:

pnpm --frozen-lockfile flag docker best practices

💡 Result:

What --frozen-lockfile is for (and why it matters in Docker)

  • Use pnpm install --frozen-lockfile in Docker builds to guarantee the install does not modify pnpm-lock.yaml, and to fail the build if package.json and the lockfile are out of sync (reproducible, CI-friendly images). In CI, this “frozen” behavior is effectively the default expectation and you’ll see failures if the lockfile would need updates. [5]

Docker best practices with pnpm + --frozen-lockfile

1) Maximize Docker layer caching

  • Copy only the files that affect dependency resolution first (typically package.json, pnpm-lock.yaml, and config like .npmrc) and run install before copying the rest of the source, so code changes don’t invalidate the dependency layer. This is the same general Docker caching principle: order layers to avoid unnecessary cache busting. [1][2]

2) Prefer pnpm fetch for faster/reliable Docker builds (especially monorepos/CI)

  • pnpm fetch is specifically designed to improve Docker builds: it can prefetch packages into the pnpm store using only the lockfile, then you install with --offline so the install step doesn’t hit the network. This keeps cache valid as long as the lockfile doesn’t change. [3][4]

3) Use BuildKit cache mounts for the pnpm store (fast incremental rebuilds)

  • With BuildKit, mount a persistent cache directory during pnpm fetch/install so rebuilds reuse downloaded packages even when a layer must rerun. [2]
  • Common targets you’ll see used for pnpm’s store cache: /root/.local/share/pnpm/store or /pnpm/store (varies by image/user). [6][7]

4) Pin/activate pnpm via Corepack (consistent toolchain)

  • Enable Corepack in the image and (optionally) pin a pnpm version so local/CI/Docker all use the same pnpm, reducing lockfile/tooling mismatches. pnpm’s Docker examples use Corepack for this. [6][7]

Example Dockerfile pattern (fast + reproducible)

# syntax=docker/dockerfile:1.7
FROM node:20-slim AS base
WORKDIR /app
RUN corepack enable

FROM base AS deps
COPY pnpm-lock.yaml ./
RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store \
    pnpm fetch --prod
COPY package.json ./
RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store \
    pnpm install --prod --frozen-lockfile --offline

FROM base AS build
COPY --from=deps /app/node_modules /app/node_modules
COPY . .
RUN pnpm run build

FROM node:20-slim
WORKDIR /app
COPY --from=build /app/dist /app/dist
COPY --from=deps  /app/node_modules /app/node_modules
CMD ["node", "dist/server.js"]

Notes:

  • If you don’t want fetch, the simpler baseline is: copy package.json + pnpm-lock.yaml (+ .npmrc), run pnpm install --frozen-lockfile, then copy the rest. [3][4]
  • If you’re in a monorepo, pnpm’s Docker docs also show pnpm deploy patterns for producing per-package images. [6]

Sources: Docker cache optimization docs [1][2], pnpm fetch docs (Docker-focused) [3][4], pnpm Docker guide/examples [6], Depot’s pnpm Dockerfile best-practice example [7], --frozen-lockfile CI behavior discussion [5].


Use --frozen-lockfile for reproducible installs.

Line 14 uses pnpm i --ignore-scripts without lockfile enforcement. Since the lockfile is copied at line 12, add --frozen-lockfile to ensure the install fails if package.json and the lockfile are out of sync, preventing non-deterministic builds across CI and local environments.

-RUN pnpm i --ignore-scripts
+RUN pnpm install --frozen-lockfile --ignore-scripts
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
RUN pnpm i --ignore-scripts
RUN pnpm install --frozen-lockfile --ignore-scripts
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.agent-service` at line 14, Replace the
non-deterministic install command in the Dockerfile where RUN pnpm i
--ignore-scripts is used: change the invocation to enforce the lockfile by
adding --frozen-lockfile so pnpm will fail if package.json and the lockfile
diverge, ensuring reproducible builds; update the RUN line that currently
invokes pnpm i --ignore-scripts to include --frozen-lockfile (and keep
--ignore-scripts if needed).

CMD ["sh", "-c", "cd libs/prisma-service && npx prisma migrate deploy && npx prisma generate && cd ../.. && node dist/apps/utility/main.js"]
COPY --from=build /app/node_modules ./node_modules
USER nextjs
CMD ["node", "dist/apps/utility/main.js"]
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Search for migration commands across the repo
rg -n -C2 -g '!**/node_modules/**' -e 'prisma migrate deploy' -e 'npx prisma migrate' -e 'pnpm.*migrate' -e 'db:migrate'

Repository: credebl/platform

Length of output: 544


🏁 Script executed:

# Also search for Docker-related deployment files and scripts
fd -e 'yml' -e 'yaml' -e 'sh' -e 'ts' -e 'js' | grep -E '(docker-compose|deploy|pipeline|manifest|scripts)' | head -20

Repository: credebl/platform

Length of output: 549


🏁 Script executed:

# Look for the Dockerfile.utility and understand the project structure
git ls-files | grep -i dockerfile

Repository: credebl/platform

Length of output: 709


🏁 Script executed:

# Read the Dockerfile.utility to see the full context
cat -n Dockerfiles/Dockerfile.utility

Repository: credebl/platform

Length of output: 1068


🏁 Script executed:

# Check the docker-compose file for utility service configuration
cat -n docker-compose.yml

Repository: credebl/platform

Length of output: 5817


🏁 Script executed:

# Look for any utility-specific deployment or initialization scripts
fd -e 'sh' -e 'yml' -e 'yaml' | xargs rg -l 'utility' | head -20

Repository: credebl/platform

Length of output: 101


🏁 Script executed:

# Search for Kubernetes manifests or deployment configs
fd -e 'yml' -e 'yaml' | xargs grep -l 'utility\|migrate' 2>/dev/null | head -20

Repository: credebl/platform

Length of output: 116


🏁 Script executed:

# Search for CI/CD workflows (GitHub, GitLab, etc.)
fd -type f \( -name '*.yml' -o -name '*.yaml' -o -name 'Makefile' \) | xargs grep -l 'prisma migrate\|db.*migrate' 2>/dev/null | head -20

Repository: credebl/platform

Length of output: 230


🏁 Script executed:

# Check for any deployment or initialization documentation
fd -type f \( -name 'README*' -o -name 'DEPLOY*' -o -name '*deploy*' \) | head -10

Repository: credebl/platform

Length of output: 230


🏁 Script executed:

# Check the docker-compose-dev.yml for utility service
cat -n docker-compose-dev.yml | grep -A 10 -B 2 'utility'

Repository: credebl/platform

Length of output: 873


🏁 Script executed:

# Search for GitHub workflows or other CI/CD configs
find . -name '*.yml' -o -name '*.yaml' | grep -E '(\.github|\.gitlab|workflow|ci|pipeline)' | head -20

Repository: credebl/platform

Length of output: 278


🏁 Script executed:

# Look for any initialization or migration scripts in the repo
fd -e 'sh' -e 'js' -e 'ts' | xargs grep -l 'prisma migrate\|db.*migrate\|migration' 2>/dev/null | head -15

Repository: credebl/platform

Length of output: 42


🏁 Script executed:

# Check the continuous delivery workflow for migration steps
cat -n .github/workflows/continuous-delivery.yml

Repository: credebl/platform

Length of output: 2339


Migrations are not being executed in the current deployment setup.

The Dockerfile.utility CMD bypasses the start script which contains prisma migrate deploy. Neither docker-compose.yml nor the CI/CD pipeline (continuous-delivery.yml) execute migrations before starting the service. Add migration execution either via:

  • An init container that runs migrations before the app container starts
  • A pre-deployment step in your CD pipeline
  • Override the CMD in docker-compose to use the start script (which includes migrations)

Without this, the utility service will start with an uninitialized or out-of-sync database schema.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.utility` at line 24, The Dockerfile currently sets CMD
["node", "dist/apps/utility/main.js"] which bypasses the npm start script that
runs prisma migrate deploy, so migrations are never executed; fix by ensuring
migrations run before the app process starts — either change the container
startup to invoke the start script (use the package.json "start" script instead
of directly running node), add an init container that runs npm run start:migrate
or prisma migrate deploy prior to launching the utility container, or add a
pre-deployment step in continuous-delivery.yml to run prisma migrate deploy;
update docker-compose.yml or CI config accordingly to call the start script or
explicit migration command so the database schema is applied before the service
runs.

RUN apk add --no-cache openssl
RUN npm install -g pnpm
# Set the working directory
FROM node:24-alpine3.21 AS build
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

node:24-alpine3.21 is superseded — upgrade to node:24-alpine3.23.

Docker Hub currently lists 24-alpine3.22 and 24-alpine3.23 as the active Alpine variants for the Node.js 24 LTS line. Pinning to alpine3.21 means the base OS layer misses downstream Alpine CVE patches, undermining the vulnerability-remediation goal of this PR. Update both FROM lines to node:24-alpine3.23 (or the floating node:24-alpine alias if you prefer automatic patch-level updates).

🛡️ Proposed fix
-FROM node:24-alpine3.21 AS build
+FROM node:24-alpine3.23 AS build
-FROM node:24-alpine3.21
+FROM node:24-alpine3.23

Also applies to: 14-14

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.webhook` at line 2, The Dockerfile uses the superseded
base image tag "FROM node:24-alpine3.21"; update both occurrences of that FROM
line to "node:24-alpine3.23" (or use the floating "node:24-alpine" alias if you
want automatic patch updates) so the build uses the current Alpine variant with
downstream CVE fixes; ensure any other identical FROM lines (e.g., the second
stage) are changed as well.


# Set the command to run the microservice
CMD ["sh", "-c", "cd libs/prisma-service && npx prisma migrate deploy && npx prisma generate && cd ../.. && node dist/apps/webhook/main.js"]
COPY --from=build /app/node_modules ./node_modules
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Final image includes devDependencies — prune before copying node_modules.

pnpm i --ignore-scripts installs all dependencies (including devDependencies) in the build stage, and the entire node_modules directory is then copied verbatim into the final image with no pruning step. This bundles TypeScript, linters, test runners, and other build-time tooling into the production runtime, bloating the image and expanding the attack surface.

Add a pnpm prune --prod step in the build stage before the final COPY, or use a dedicated production-install stage:

🛡️ Option A — prune in-place in the build stage
 RUN pnpm run build webhook
+RUN pnpm prune --prod
 COPY --from=build /app/node_modules ./node_modules
♻️ Option B — dedicated production-install stage
+# Stage 1b: Production dependencies only
+FROM node:24-alpine3.23 AS deps
+RUN apk update && apk upgrade && apk add --no-cache openssl && rm -rf /var/cache/apk/*
+RUN npm install -g pnpm@9.15.3
+WORKDIR /app
+COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
+ENV PUPPETEER_SKIP_DOWNLOAD=true
+RUN pnpm i --frozen-lockfile --ignore-scripts --prod

 # Stage 2: Create the final image
 FROM node:24-alpine3.23
 ...
-COPY --from=build /app/node_modules ./node_modules
+COPY --from=deps /app/node_modules ./node_modules
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.webhook` at line 22, The final image is copying the
full node_modules from the build stage (COPY --from=build /app/node_modules
./node_modules) which includes devDependencies; before performing that COPY, run
a production prune in the build stage (e.g., invoke pnpm prune --prod after
install/build) or replace the current build stage with a dedicated
production-install stage that installs only prod deps and then COPY
--from=prod-stage /app/node_modules ./node_modules; update the Dockerfile so the
node_modules copied into the final image contains only production dependencies.


# Set the command to run the microservice
CMD ["sh", "-c", "cd libs/prisma-service && npx prisma migrate deploy && npx prisma generate && cd ../.. && node dist/apps/x509/main.js"] No newline at end of file
COPY --from=build /app/node_modules ./node_modules
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

node_modules carries all devDependencies into the production image — directly undermines the PR goal of removing vulnerable packages.

The build stage runs pnpm i without --prod, so the full node_modules (including devDependencies) is copied to the final image. This defeats the purpose of the multi-stage build and reintroduces every vulnerable dev package into the production runtime.

Add a production-only install step in the build stage before copying:

🔧 Proposed fix
 RUN pnpm run build x509
+RUN pnpm prune --prod
 
 # Stage 2: Create the final image

Then the final-stage COPY picks up the pruned node_modules.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.x509` at line 22, The final image is copying
/app/node_modules from the build stage (COPY --from=build /app/node_modules
./node_modules) but the build stage runs pnpm i without production pruning, so
devDependencies are included; update the build stage to perform a
production-only install (e.g., run pnpm install --prod or set
NODE_ENV=production and run pnpm install, or run pnpm prune --prod after
install) so that /app/node_modules in the build stage contains only production
deps before the COPY; ensure the command in the Dockerfile that currently runs
pnpm i is replaced or followed by the production-prune step so the final COPY
only brings production packages.

CMD ["sh", "-c", "cd libs/prisma-service && npx prisma migrate deploy && npx prisma generate && cd ../.. && node dist/apps/x509/main.js"] No newline at end of file
COPY --from=build /app/node_modules ./node_modules
USER nextjs
CMD ["node", "dist/apps/x509/main.js"] No newline at end of file
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# Search for prisma migrate deploy invocations across the repo
rg -rn "prisma migrate deploy" --glob "!node_modules"

Repository: credebl/platform

Length of output: 159


🏁 Script executed:

# Search for other migration-related patterns and mechanisms
rg -rn "prisma migrate" --glob "!node_modules" | head -50

Repository: credebl/platform

Length of output: 166


🏁 Script executed:

# Look for Kubernetes manifests that might contain init containers
fd -e yaml -e yml | grep -E "(k8s|kubernetes|helm|deployment)" | head -20

Repository: credebl/platform

Length of output: 42


🏁 Script executed:

# Search for CI/CD configuration files
fd -e yaml -e yml -e json -e sh | grep -E "^\.github|\.gitlab-ci|\.circleci|Makefile|package.json" | head -20

Repository: credebl/platform

Length of output: 150


🏁 Script executed:

# Search for .github workflows directory
find . -path "./.github/workflows" -type d 2>/dev/null

Repository: credebl/platform

Length of output: 79


🏁 Script executed:

# Search for docker-compose files
fd "docker-compose" --type f

Repository: credebl/platform

Length of output: 150


🏁 Script executed:

# Look at all Dockerfiles to see the full context
fd "Dockerfile" --type f | head -20

Repository: credebl/platform

Length of output: 709


🏁 Script executed:

# Get more context around the package.json "start" script
cat -n package.json | grep -A 2 -B 2 "start"

Repository: credebl/platform

Length of output: 654


🏁 Script executed:

# Search for any CI/CD related files (.gitlab-ci.yml, .circleci, jenkins, etc.)
fd -e yml -e yaml | grep -iE "(github|gitlab|circleci|jenkins|ci)"

Repository: credebl/platform

Length of output: 42


🏁 Script executed:

# Search for migration-related scripts or entrypoints
rg -rn "migrate" --glob "!node_modules" | head -30

Repository: credebl/platform

Length of output: 1171


🏁 Script executed:

# List workflow files
ls -la .github/workflows/

Repository: credebl/platform

Length of output: 306


🏁 Script executed:

# Check docker-compose.yml for migration steps
cat docker-compose.yml | head -100

Repository: credebl/platform

Length of output: 2399


🏁 Script executed:

# Check how many other Dockerfiles have the same bypass pattern (direct node call instead of npm start)
for f in $(fd "Dockerfile" --type f); do
  echo "=== $f ==="; 
  grep -E "^CMD|^ENTRYPOINT" "$f";
done

Repository: credebl/platform

Length of output: 1747


🏁 Script executed:

# Check if there are any init containers or pre-deployment scripts in the repo
rg -rn "initContainers|preUpgrade|pre-upgrade" --glob "!node_modules"

Repository: credebl/platform

Length of output: 42


🏁 Script executed:

cat .github/workflows/continuous-delivery.yml

Repository: credebl/platform

Length of output: 1828


Add Prisma migration step to deployment pipeline.

prisma migrate deploy was removed from container startup, and no alternative migration mechanism exists in the deployment pipeline. The npm start script includes migrations ("start": "npx prisma migrate deploy --schema=./libs/prisma-service/prisma/schema.prisma & nest start"), but all Dockerfiles bypass this with direct node calls. Neither the CI workflow, docker-compose setup, nor Kubernetes manifests handle schema migrations, so new database schema changes will be silently skipped on deployment. This affects all 18+ services.

Add migrations via one of: init container, pre-upgrade Helm hook, or dedicated CI step that runs before deployment.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.x509` at line 24, The container currently bypasses
migrations by using the raw CMD ["node", "dist/apps/x509/main.js"] while the
package.json "start" script runs npx prisma migrate deploy; fix by ensuring
prisma migrations run before app start: either (A) change the image entry to run
the existing "start" script (use npm start) or add an entrypoint that runs npx
prisma migrate deploy --schema=./libs/prisma-service/prisma/schema.prisma before
launching node, or (B) move migrations out of the container and add a dedicated
deployment step (CI job), a Kubernetes initContainer, or a Helm pre-upgrade hook
that executes prisma migrate deploy; pick one approach and apply consistently
across all services (replace the raw CMD in Dockerfile.x509 and analogous
Dockerfiles or add the CI/K8s/Helm migration step).

Signed-off-by: DeepakNemad <deepak.nemade@ayanworks.com>
Signed-off-by: DeepakNemad <deepak.nemade@ayanworks.com>
Signed-off-by: DeepakNemad <deepak.nemade@ayanworks.com>
Signed-off-by: DeepakNemad <deepak.nemade@ayanworks.com>
Copy link

@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: 14

♻️ Duplicate comments (15)
Dockerfiles/Dockerfile.ecosystem (1)

11-11: devDependencies still shipped in production.

Same as previously flagged — add RUN pnpm prune --prod after the build.

Also applies to: 22-22

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.ecosystem` at line 11, The Dockerfile currently runs
the build step with "RUN pnpm run build ecosystem" but still leaves
devDependencies in the image; after the build instruction add a "RUN pnpm prune
--prod" step to remove devDependencies (i.e., place the pnpm prune --prod
command immediately following the RUN pnpm run build ecosystem instruction so
only production deps remain).
Dockerfiles/Dockerfile.utility (2)

11-11: Production image still includes devDependencies.

Same issue as flagged previously — add RUN pnpm prune --prod after the build step to strip devDependencies before copying node_modules to the final image.

Also applies to: 22-22

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.utility` at line 11, The production Dockerfile
currently runs the build step (RUN pnpm run build utility) but still copies full
node_modules including devDependencies into the final image; after the build
step add a pruning step (RUN pnpm prune --prod) to remove devDependencies before
copying node_modules into the final image (or ensure the multi-stage copy pulls
node_modules from the stage where pnpm prune --prod ran), updating the stage
that runs RUN pnpm run build utility to include the pnpm prune --prod command so
the final image contains only production deps.

24-24: Prisma migrations not executed before application startup.

As flagged in a previous review, the CMD bypasses the start script which previously ran prisma migrate deploy. Ensure migrations are handled by your deployment orchestration (init container, CI job, etc.) before replicas start.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.utility` at line 24, The Dockerfile currently uses the
direct CMD ["node", "dist/apps/utility/main.js"], which bypasses the start
script that runs prisma migrate deploy; change the container startup strategy so
migrations run before the app: either restore the image to invoke the
package.json start script (so start runs prisma migrate deploy) or ensure your
deployment orchestration (init container, CI job, or startup hook) executes
prisma migrate deploy prior to replicas starting; update references to CMD and
the start script/prisma migrate deploy flow accordingly.
Dockerfiles/Dockerfile.oid4vc-verification (1)

11-11: devDependencies still shipped in production.

Same as previously flagged across other Dockerfiles — add RUN pnpm prune --prod after pnpm run build.

Also applies to: 22-22

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.oid4vc-verification` at line 11, The image still
contains devDependencies because you run the build but don't prune them; after
the RUN pnpm run build oid4vc-verification step add a RUN pnpm prune --prod to
remove devDependencies so only production deps remain (update the Dockerfile
step following the existing RUN pnpm run build oid4vc-verification command).
Dockerfiles/Dockerfile.organization (1)

11-11: devDependencies still shipped in production — pnpm prune --prod missing.

Same as flagged previously. Add RUN pnpm prune --prod after the build step.

Also applies to: 22-22

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.organization` at line 11, The Dockerfile currently
runs the build with the command "RUN pnpm run build organization" but does not
remove devDependencies, causing devDependencies to be shipped to production; add
a step immediately after that command to run "RUN pnpm prune --prod" (i.e.,
insert a RUN pnpm prune --prod line right after the RUN pnpm run build
organization statement) so the production image only keeps production
dependencies.
Dockerfiles/Dockerfile.oid4vc-issuance (1)

11-11: Production image ships devDependencies — add pnpm prune --prod after the build step.

No pruning step exists between pnpm run build and the final-stage COPY --from=build /app/node_modules. All devDependencies (TypeScript, test utilities, build tools) end up in the production image, increasing attack surface and image size.

Proposed fix
 RUN pnpm run build oid4vc-issuance
+RUN pnpm prune --prod

Also applies to: 22-22

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.oid4vc-issuance` at line 11, The production image is
including devDependencies because there is no pruning step after the build;
after the existing RUN pnpm run build oid4vc-issuance in the build stage, add a
step to run pnpm prune --prod (or equivalent pnpm install --prod/prune command)
so that node_modules only contains production deps before the final-stage COPY
--from=build /app/node_modules; apply the same change to the other identical
build step referenced in the review to ensure devDependencies are not copied
into the final image.
Dockerfiles/Dockerfile.seed (1)

18-18: prisma migrate deploy still missing before prisma db seed.

As flagged in a previous review, the CMD only runs prisma db seed without applying migrations first. If the database schema isn't already up-to-date (fresh environment, rollback, standalone execution), the seed will fail. Either restore prisma migrate deploy before the seed command or ensure migrations are guaranteed to run upstream.

Proposed fix if migrations should be self-contained
-CMD ["sh", "-c", "cd libs/prisma-service && npx prisma db seed"]
+CMD ["sh", "-c", "cd libs/prisma-service && npx prisma migrate deploy && npx prisma db seed"]
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.seed` at line 18, The Docker CMD currently only runs
"npx prisma db seed" in libs/prisma-service which can fail if migrations haven't
been applied; update the startup command for the container to run "npx prisma
migrate deploy" before "npx prisma db seed" (e.g., combine or sequence the
commands in the CMD that changes in Dockerfiles/Dockerfile.seed) so migrations
are applied first, or alternatively ensure upstream orchestration runs "prisma
migrate deploy" prior to invoking the existing CMD; target the CMD that
currently executes in libs/prisma-service and add the "prisma migrate deploy"
step before the seed.
Dockerfiles/Dockerfile.user (2)

11-11: devDependencies still shipped in production.

Same as previously flagged.

Also applies to: 22-22

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.user` at line 11, The Dockerfile currently runs "RUN
pnpm run build user" but ends up shipping devDependencies into the production
image; change to a multi-stage build: create a builder stage that installs all
deps (pnpm install) and runs "pnpm run build user" (e.g., stage name "builder"),
then create a slim final stage that copies only the build artifacts and
package.json/pnpm-lock.yaml and runs "pnpm install --prod" (or "pnpm install
--frozen-lockfile --prod") to install only production deps; ensure the final
image does not run a full install of devDependencies or copy node_modules from
the builder stage.

24-24: Prisma migrations not executed before application startup.

As flagged in a previous review, ensure migrations are handled externally.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.user` at line 24, The Dockerfile must not trigger
Prisma migrations at container start—ensure all migrations are applied
externally by the deployment pipeline; confirm that CMD ["node",
"dist/apps/user/main.js"] only starts the app and remove any automatic migration
invocations (e.g., calls to prisma migrate or use of an entrypoint script that
runs migrations) from the Docker image or startup code (inspect
dist/apps/user/main.js and any entrypoint scripts) so the container solely runs
the application and migration orchestration happens outside the container.
Dockerfiles/Dockerfile.issuance (1)

11-11: devDependencies still shipped in production.

Same as previously flagged.

Also applies to: 22-22

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.issuance` at line 11, The Dockerfile is installing
devDependencies into the production image because the RUN pnpm run build
issuance step runs with dev deps present; change the Dockerfile to build in a
separate builder stage and only copy the built artifacts and production
dependencies into the final image (or, at minimum, run pnpm install --prod /
pnpm install --prod --frozen-lockfile in the final stage before copying
artifacts) so devDependencies are not shipped; target the RUN pnpm run build
issuance step (and the npm/pnpm install steps surrounding it) to implement a
multi-stage build that installs devDependencies only in the builder stage and
installs only production deps in the runtime stage.
Dockerfiles/Dockerfile.x509 (2)

24-24: ⚠️ Potential issue | 🟠 Major

Confirm migrations run in deployment before app startup.

Line 24 bypasses the npm start script migration path. If no pre-deploy migration job exists, schema updates can be skipped.

#!/bin/bash
set -euo pipefail
echo "Docker CMD patterns:"
rg -n 'CMD \["node", "dist/apps/.+/main\.js"\]' Dockerfiles

echo
echo "Where prisma migrate deploy is invoked:"
rg -n "prisma migrate deploy" -g '!**/node_modules/**'

echo
echo "Potential deployment hooks for migrations:"
rg -n "initContainer|pre-upgrade|migration job|db-migration" -g '!**/node_modules/**'
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.x509` at line 24, The Dockerfile's direct CMD ["node",
"dist/apps/x509/main.js"] bypasses the npm start script (and any migration
steps), so ensure migrations run before app startup by invoking the project's
migration path; either replace the direct node CMD with the npm start entrypoint
that runs migrations, or add a startup wrapper that runs "prisma migrate deploy"
(or the project's migration command) before launching dist/apps/x509/main.js;
update the Dockerfile's CMD or ENTRYPOINT accordingly and reference the existing
CMD ["node", "dist/apps/x509/main.js"] when making the change so deployments
always run migrations prior to starting the app.

22-22: ⚠️ Potential issue | 🟠 Major

Prune devDependencies before copying node_modules to runtime.

Line 22 copies the full build-stage node_modules; without pruning, devDependencies are shipped in production.

🔧 Proposed fix
 RUN cd libs/prisma-service && npx prisma generate
 RUN pnpm run build x509
+RUN pnpm prune --prod
#!/bin/bash
set -euo pipefail
f="Dockerfiles/Dockerfile.x509"
echo "Inspecting ${f}"
rg -n "pnpm i|pnpm install|pnpm prune --prod|node_modules" "$f"
if rg -q "pnpm prune --prod" "$f"; then
  echo "✅ prune step present"
else
  echo "❌ Missing pnpm prune --prod before copying node_modules"
fi
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.x509` at line 22, The Dockerfile currently copies the
entire build-stage node_modules (COPY --from=build /app/node_modules
./node_modules) which includes devDependencies; modify the build stage in
Dockerfiles/Dockerfile.x509 to prune devDependencies before that COPY by running
a production-only prune/install (e.g., run pnpm prune --prod or reinstall
production deps) so that node_modules only contains production packages, then
keep the existing COPY --from=build /app/node_modules ./node_modules to pull the
slimmed modules into the runtime image.
Dockerfiles/Dockerfile.agent-service (1)

33-33: ⚠️ Potential issue | 🟠 Major

Prune devDependencies before runtime copy.

Line 33 pulls full node_modules from build stage; this typically includes devDependencies.

🔧 Proposed fix
 RUN cd libs/prisma-service && npx prisma generate
 RUN pnpm run build agent-service
+RUN pnpm prune --prod
#!/bin/bash
set -euo pipefail
f="Dockerfiles/Dockerfile.agent-service"
rg -n "pnpm i|pnpm install|pnpm prune --prod|node_modules" "$f"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.agent-service` at line 33, The Dockerfile copies the
entire node_modules from the build stage (COPY --from=build /app/node_modules
./node_modules), which may include devDependencies; change the build/runtime
flow to produce a production-only node_modules before copying — for example, run
a production install or prune step in the build stage (e.g., use pnpm install
--prod or pnpm prune --prod after installing dev deps) or perform a
production-only install in the final stage so that the node_modules copied by
COPY --from=build are pruned of devDependencies; update the Dockerfile around
the install/prune steps and the COPY --from=build reference (the COPY line and
the install/prune commands are the unique symbols to modify).
Dockerfiles/Dockerfile.webhook (1)

22-22: ⚠️ Potential issue | 🟠 Major

Prune build dependencies before final node_modules copy.

Line 22 copies build-stage node_modules directly, which likely carries devDependencies into production.

🔧 Proposed fix
 RUN cd libs/prisma-service && npx prisma generate
 RUN pnpm run build webhook
+RUN pnpm prune --prod
#!/bin/bash
set -euo pipefail
f="Dockerfiles/Dockerfile.webhook"
rg -n "pnpm i|pnpm install|pnpm prune --prod|node_modules" "$f"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.webhook` at line 22, The Dockerfile currently copies
the build-stage node_modules wholesale via the COPY --from=build
/app/node_modules ./node_modules instruction, which carries devDependencies into
the final image; to fix, prune or produce a production-only node_modules before
copying by either running pnpm prune --prod (or npm ci --only=production) in the
build stage after the build completes, or add a dedicated production install
stage that runs pnpm install --prod --frozen-lockfile and then COPY from that
stage (i.e., replace COPY --from=build /app/node_modules ./node_modules with a
copy from the pruned/prod-install stage or ensure the build stage runs pnpm
prune --prod and then copy the pruned node_modules).
Dockerfiles/Dockerfile.geolocation (1)

22-22: Final image still copies full devDependencies.

The existing review comment on this line has not been addressed — node_modules from the build stage still includes devDependencies.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.geolocation` at line 22, The Dockerfile currently
copies the entire node_modules from the build stage ("COPY --from=build
/app/node_modules ./node_modules"), which includes devDependencies; update the
build/final steps so only production deps are copied: either install only
production packages in the build stage (use npm ci --only=production or
NODE_ENV=production npm ci) or run npm prune --production in the build stage
before the COPY, or alternatively stop copying node_modules and instead COPY
package*.json then run npm ci --only=production in the final stage; apply the
change around the "COPY --from=build /app/node_modules ./node_modules" line.
🧹 Nitpick comments (4)
Dockerfiles/Dockerfile.geolocation (1)

2-2: node:24-alpine3.21 is superseded — consider bumping to alpine3.22.

Same concern as the other Dockerfiles in this PR: the current Node 24 Alpine pairings on Docker Hub are 24-alpine3.22 and 24-alpine3.23, both of which receive ongoing OS-level patches that alpine3.21 no longer receives.

♻️ Proposed fix
-FROM node:24-alpine3.21 AS build
+FROM node:24-alpine3.22 AS build
 ...
-FROM node:24-alpine3.21
+FROM node:24-alpine3.22

Also applies to: 14-14

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.geolocation` at line 2, Update the Docker base image
reference FROM node:24-alpine3.21 to a supported Alpine patch (e.g.
node:24-alpine3.22 or node:24-alpine3.23) in the Dockerfile where the FROM
node:24-alpine3.21 line appears so the image receives current OS-level security
patches; change the image tag consistently for other Dockerfiles that use the
same FROM node:24-alpine3.21 reference.
Dockerfiles/Dockerfile.api-gateway (1)

2-2: node:24-alpine3.21 is superseded — consider bumping to alpine3.22.

Same concern as the other Dockerfiles in this PR: Alpine 3.21 is no longer the current patch base for Node 24. Docker Hub now lists 24-alpine3.22 and 24-alpine3.23 as the current Node 24 Alpine variants.

♻️ Proposed fix
-FROM node:24-alpine3.21 AS build
+FROM node:24-alpine3.22 AS build
 ...
-FROM node:24-alpine3.21
+FROM node:24-alpine3.22

Also applies to: 14-14

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.api-gateway` at line 2, Replace the superseded base
image tag "node:24-alpine3.21" used in the Dockerfile (the FROM
node:24-alpine3.21 AS build line) with the current Alpine patch variant, e.g.
"node:24-alpine3.22" (or 24-alpine3.23), and apply the same change to other
Dockerfiles that use the same tag (the occurrences noted as 14-14) so all Node
24 Alpine base images are updated consistently.
Dockerfiles/Dockerfile.agent-provisioning (1)

2-2: node:24-alpine3.21 is superseded — consider updating to a newer Alpine variant.

The current latest Node 24 Alpine pairings on Docker Hub are 24-alpine3.22 and 24-alpine3.23. Alpine 3.21 no longer receives upstream patch updates, meaning OS-level CVE fixes are only published against newer Alpine releases. Since the intent of this PR is to remediate vulnerabilities, pinning to a stale Alpine base undermines that goal.

♻️ Proposed fix — upgrade Alpine base
-FROM  node:24-alpine3.21 AS build
+FROM  node:24-alpine3.22 AS build
 ...
-FROM  node:24-alpine3.21
+FROM  node:24-alpine3.22

Also applies to: 21-21

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.agent-provisioning` at line 2, Replace the pinned base
image string "FROM node:24-alpine3.21" with a current Alpine variant such as
"FROM node:24-alpine3.23" (or at minimum "node:24-alpine3.22") to ensure
upstream CVE/patch fixes are included; update the same FROM string in any other
Dockerfiles referencing "node:24-alpine3.21" (e.g., the other Dockerfile noted
as 21-21) and rebuild images to verify no downstream breakages from the base
image bump.
Dockerfiles/Dockerfile.notification (1)

2-2: node:24-alpine3.21 is superseded — consider bumping to alpine3.22.

Docker Hub now lists 24-alpine3.22 and 24-alpine3.23 as the current Node 24 Alpine variants. Pinning to alpine3.21 limits the OS-level CVE coverage that this PR aims to improve.

♻️ Proposed fix
-FROM node:24-alpine3.21 AS build
+FROM node:24-alpine3.22 AS build
 ...
-FROM node:24-alpine3.21
+FROM node:24-alpine3.22

Also applies to: 14-14

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.notification` at line 2, Update the pinned base image
string "node:24-alpine3.21" to a current Alpine variant (e.g.,
"node:24-alpine3.22" or "node:24-alpine3.23") wherever it appears (the
Dockerfile FROM line using that tag), and do the same for the analogous legacy
image tag (e.g., "node:14-alpine3.21") referenced in the other Dockerfile;
ensure both FROM lines are changed so the build uses the newer alpine3.22/3.23
variant to improve OS-level CVE coverage.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@Dockerfiles/Dockerfile.agent-provisioning`:
- Line 38: The final image currently copies the entire build-stage node_modules
via the COPY --from=build /app/node_modules ./node_modules line, which brings
devDependencies into the runtime image; replace that approach by installing only
production deps in the final stage: copy package.json (and
package-lock.json/yarn.lock) into the final stage and run a production install
(e.g., npm ci --only=production or npm ci && npm prune --production) or use
NODE_ENV=production during install so devDependencies are excluded; update the
Dockerfile to remove the COPY --from=build /app/node_modules ./node_modules and
perform the production-only install in the final stage (referencing the
Dockerfile final stage where node_modules is populated).
- Around line 22-29: The Dockerfile currently installs heavy runtime packages
(aws-cli, docker, docker-compose) that are used by shell scripts
(start_agent_ecs.sh, start_agent.sh) and by the walletProvision method in
agent-provisioning.service.ts via exec(); confirm whether these commands truly
must run inside the container at runtime and if not remove them from the final
image or replace with lighter alternatives (use AWS SDK calls from
walletProvision instead of aws-cli, call remote Docker daemon or include only
the docker client binary, or move tooling to a sidecar/host or a build-stage so
final image size/CVE surface is reduced); update the Dockerfile and the
referenced scripts/service accordingly and document the chosen operational model
if you keep the packages.

In `@Dockerfiles/Dockerfile.api-gateway`:
- Line 22: The final image currently copies the entire workspace node_modules
via "COPY --from=build /app/node_modules ./node_modules", pulling
devDependencies into production; instead, in the final stage remove that COPY
and perform a production-only install/prune there (e.g., run a production
npm/yarn install or npm prune --production) so only production deps are
present—update the Dockerfile final stage around the COPY --from=build
/app/node_modules ./node_modules to replace the copy with a production
install/prune step.

In `@Dockerfiles/Dockerfile.cloud-wallet`:
- Line 22: The Dockerfile copies the entire build-stage node_modules (COPY
--from=build /app/node_modules ./node_modules), which includes devDependencies
because the build stage ran pnpm i --frozen-lockfile --ignore-scripts without
pruning; fix by pruning devDependencies before copying or installing only
production deps in the final image—either run pnpm prune --prod (or pnpm prune
--prod --offline as appropriate) in the build stage and then copy the pruned
/app/node_modules, or replace the copy with a production install in the final
stage (e.g., run pnpm install --prod --frozen-lockfile in the final stage) so
that node_modules in the final image contains only production dependencies.

In `@Dockerfiles/Dockerfile.connection`:
- Line 22: The final image currently copies the entire node_modules from the
build stage (COPY --from=build /app/node_modules ./node_modules), which includes
devDependencies; fix it by running pnpm prune --prod in the build stage before
copying so dev-only packages are removed (add a RUN pnpm prune --prod step in
the build stage after install/build and before the COPY --from=build reference)
ensuring the final image only contains production dependencies.

In `@Dockerfiles/Dockerfile.ecosystem`:
- Around line 14-18: The Dockerfile creates the nodejs group (addgroup -g 1001
-S nodejs) but fails to assign the nextjs user to that group; update the user
creation command (adduser) to include the group flag so nextjs is added to
nodejs (use the -G nodejs option on the adduser command) so the new user is
properly associated with the created group.

In `@Dockerfiles/Dockerfile.issuance`:
- Around line 14-18: The Dockerfile's user creation omits adding the new user to
the nodejs group; update the adduser invocation (the adduser command in this
Dockerfile) to include the -G nodejs flag so the created nextjs user is added to
the nodejs group (keep existing -S and -u 1001 flags intact).

In `@Dockerfiles/Dockerfile.ledger`:
- Line 22: The final image currently copies all node_modules from the build
stage via COPY --from=build /app/node_modules ./node_modules which includes
devDependencies; remove devDeps before that copy by pruning production-only
packages in the build stage (e.g., run npm prune --production or npm ci
--only=production in a dedicated step/stage after the build) or install
production deps in a separate stage and COPY from that stage, ensuring only
production dependencies end up in the final image.

In `@Dockerfiles/Dockerfile.notification`:
- Line 22: The final Docker image currently copies the entire workspace
node_modules from the build stage via the COPY --from=build /app/node_modules
./node_modules line, which brings devDependencies into the image; change the
final stage to perform a production-only install instead — e.g., copy
package.json/package-lock.json (or yarn.lock) into the final stage and run npm
ci --only=production (or npm prune --production) there, or run a production
install in the build stage and copy only the production node_modules to replace
the current COPY --from=build /app/node_modules ./node_modules usage so
devDependencies are excluded.

In `@Dockerfiles/Dockerfile.oid4vc-issuance`:
- Around line 14-18: The adduser invocation for the nextjs user is not adding it
to the nodejs group; update the Dockerfile by modifying the adduser command (the
adduser call that creates "nextjs") to include the group flag "-G nodejs" so the
nextjs user is a member of the nodejs group created by the addgroup call
(symbols to change: addgroup -g 1001 -S nodejs and adduser -S nextjs -u 1001 →
ensure adduser includes -G nodejs).

In `@Dockerfiles/Dockerfile.organization`:
- Around line 14-18: The Dockerfile creates the nodejs group with addgroup -g
1001 -S nodejs but then adds the nextjs user without assigning it to that group;
update the adduser invocation (the one creating nextjs) to include the group
flag so nextjs is added to nodejs (use adduser -S nextjs -u 1001 -G nodejs) to
match other Dockerfiles and ensure correct group membership.

In `@Dockerfiles/Dockerfile.seed`:
- Around line 1-8: The adduser invocation currently creates the nextjs user
without assigning it to the previously-created nodejs group, so chown -R
nextjs:nodejs won't give the user group membership; update the adduser command
(the line that calls adduser -S nextjs -u 1001) to include the nodejs group
(e.g., adduser -S nextjs -u 1001 -G nodejs) so the nextjs user is created as a
member of group nodejs and the subsequent chown -R nextjs:nodejs will grant the
intended access.

In `@Dockerfiles/Dockerfile.user`:
- Around line 14-18: The adduser invocation in the Dockerfile is missing the
group flag, causing the new user not to be placed into the nodejs group; update
the adduser command (the line that currently calls adduser -S nextjs -u 1001) to
include -G nodejs so the created user is assigned to the addgroup-created nodejs
group (refer to the addgroup and adduser commands in the diff).

In `@Dockerfiles/Dockerfile.verification`:
- Line 22: The final image currently copies the full build-stage node_modules
(COPY --from=build /app/node_modules ./node_modules), which includes
devDependencies; before that COPY run pnpm prune --prod in the build stage (or
create a dedicated pruned step) so devDependencies are removed and only
production deps remain, then copy the pruned /app/node_modules into the final
image.

---

Duplicate comments:
In `@Dockerfiles/Dockerfile.agent-service`:
- Line 33: The Dockerfile copies the entire node_modules from the build stage
(COPY --from=build /app/node_modules ./node_modules), which may include
devDependencies; change the build/runtime flow to produce a production-only
node_modules before copying — for example, run a production install or prune
step in the build stage (e.g., use pnpm install --prod or pnpm prune --prod
after installing dev deps) or perform a production-only install in the final
stage so that the node_modules copied by COPY --from=build are pruned of
devDependencies; update the Dockerfile around the install/prune steps and the
COPY --from=build reference (the COPY line and the install/prune commands are
the unique symbols to modify).

In `@Dockerfiles/Dockerfile.ecosystem`:
- Line 11: The Dockerfile currently runs the build step with "RUN pnpm run build
ecosystem" but still leaves devDependencies in the image; after the build
instruction add a "RUN pnpm prune --prod" step to remove devDependencies (i.e.,
place the pnpm prune --prod command immediately following the RUN pnpm run build
ecosystem instruction so only production deps remain).

In `@Dockerfiles/Dockerfile.geolocation`:
- Line 22: The Dockerfile currently copies the entire node_modules from the
build stage ("COPY --from=build /app/node_modules ./node_modules"), which
includes devDependencies; update the build/final steps so only production deps
are copied: either install only production packages in the build stage (use npm
ci --only=production or NODE_ENV=production npm ci) or run npm prune
--production in the build stage before the COPY, or alternatively stop copying
node_modules and instead COPY package*.json then run npm ci --only=production in
the final stage; apply the change around the "COPY --from=build
/app/node_modules ./node_modules" line.

In `@Dockerfiles/Dockerfile.issuance`:
- Line 11: The Dockerfile is installing devDependencies into the production
image because the RUN pnpm run build issuance step runs with dev deps present;
change the Dockerfile to build in a separate builder stage and only copy the
built artifacts and production dependencies into the final image (or, at
minimum, run pnpm install --prod / pnpm install --prod --frozen-lockfile in the
final stage before copying artifacts) so devDependencies are not shipped; target
the RUN pnpm run build issuance step (and the npm/pnpm install steps surrounding
it) to implement a multi-stage build that installs devDependencies only in the
builder stage and installs only production deps in the runtime stage.

In `@Dockerfiles/Dockerfile.oid4vc-issuance`:
- Line 11: The production image is including devDependencies because there is no
pruning step after the build; after the existing RUN pnpm run build
oid4vc-issuance in the build stage, add a step to run pnpm prune --prod (or
equivalent pnpm install --prod/prune command) so that node_modules only contains
production deps before the final-stage COPY --from=build /app/node_modules;
apply the same change to the other identical build step referenced in the review
to ensure devDependencies are not copied into the final image.

In `@Dockerfiles/Dockerfile.oid4vc-verification`:
- Line 11: The image still contains devDependencies because you run the build
but don't prune them; after the RUN pnpm run build oid4vc-verification step add
a RUN pnpm prune --prod to remove devDependencies so only production deps remain
(update the Dockerfile step following the existing RUN pnpm run build
oid4vc-verification command).

In `@Dockerfiles/Dockerfile.organization`:
- Line 11: The Dockerfile currently runs the build with the command "RUN pnpm
run build organization" but does not remove devDependencies, causing
devDependencies to be shipped to production; add a step immediately after that
command to run "RUN pnpm prune --prod" (i.e., insert a RUN pnpm prune --prod
line right after the RUN pnpm run build organization statement) so the
production image only keeps production dependencies.

In `@Dockerfiles/Dockerfile.seed`:
- Line 18: The Docker CMD currently only runs "npx prisma db seed" in
libs/prisma-service which can fail if migrations haven't been applied; update
the startup command for the container to run "npx prisma migrate deploy" before
"npx prisma db seed" (e.g., combine or sequence the commands in the CMD that
changes in Dockerfiles/Dockerfile.seed) so migrations are applied first, or
alternatively ensure upstream orchestration runs "prisma migrate deploy" prior
to invoking the existing CMD; target the CMD that currently executes in
libs/prisma-service and add the "prisma migrate deploy" step before the seed.

In `@Dockerfiles/Dockerfile.user`:
- Line 11: The Dockerfile currently runs "RUN pnpm run build user" but ends up
shipping devDependencies into the production image; change to a multi-stage
build: create a builder stage that installs all deps (pnpm install) and runs
"pnpm run build user" (e.g., stage name "builder"), then create a slim final
stage that copies only the build artifacts and package.json/pnpm-lock.yaml and
runs "pnpm install --prod" (or "pnpm install --frozen-lockfile --prod") to
install only production deps; ensure the final image does not run a full install
of devDependencies or copy node_modules from the builder stage.
- Line 24: The Dockerfile must not trigger Prisma migrations at container
start—ensure all migrations are applied externally by the deployment pipeline;
confirm that CMD ["node", "dist/apps/user/main.js"] only starts the app and
remove any automatic migration invocations (e.g., calls to prisma migrate or use
of an entrypoint script that runs migrations) from the Docker image or startup
code (inspect dist/apps/user/main.js and any entrypoint scripts) so the
container solely runs the application and migration orchestration happens
outside the container.

In `@Dockerfiles/Dockerfile.utility`:
- Line 11: The production Dockerfile currently runs the build step (RUN pnpm run
build utility) but still copies full node_modules including devDependencies into
the final image; after the build step add a pruning step (RUN pnpm prune --prod)
to remove devDependencies before copying node_modules into the final image (or
ensure the multi-stage copy pulls node_modules from the stage where pnpm prune
--prod ran), updating the stage that runs RUN pnpm run build utility to include
the pnpm prune --prod command so the final image contains only production deps.
- Line 24: The Dockerfile currently uses the direct CMD ["node",
"dist/apps/utility/main.js"], which bypasses the start script that runs prisma
migrate deploy; change the container startup strategy so migrations run before
the app: either restore the image to invoke the package.json start script (so
start runs prisma migrate deploy) or ensure your deployment orchestration (init
container, CI job, or startup hook) executes prisma migrate deploy prior to
replicas starting; update references to CMD and the start script/prisma migrate
deploy flow accordingly.

In `@Dockerfiles/Dockerfile.webhook`:
- Line 22: The Dockerfile currently copies the build-stage node_modules
wholesale via the COPY --from=build /app/node_modules ./node_modules
instruction, which carries devDependencies into the final image; to fix, prune
or produce a production-only node_modules before copying by either running pnpm
prune --prod (or npm ci --only=production) in the build stage after the build
completes, or add a dedicated production install stage that runs pnpm install
--prod --frozen-lockfile and then COPY from that stage (i.e., replace COPY
--from=build /app/node_modules ./node_modules with a copy from the
pruned/prod-install stage or ensure the build stage runs pnpm prune --prod and
then copy the pruned node_modules).

In `@Dockerfiles/Dockerfile.x509`:
- Line 24: The Dockerfile's direct CMD ["node", "dist/apps/x509/main.js"]
bypasses the npm start script (and any migration steps), so ensure migrations
run before app startup by invoking the project's migration path; either replace
the direct node CMD with the npm start entrypoint that runs migrations, or add a
startup wrapper that runs "prisma migrate deploy" (or the project's migration
command) before launching dist/apps/x509/main.js; update the Dockerfile's CMD or
ENTRYPOINT accordingly and reference the existing CMD ["node",
"dist/apps/x509/main.js"] when making the change so deployments always run
migrations prior to starting the app.
- Line 22: The Dockerfile currently copies the entire build-stage node_modules
(COPY --from=build /app/node_modules ./node_modules) which includes
devDependencies; modify the build stage in Dockerfiles/Dockerfile.x509 to prune
devDependencies before that COPY by running a production-only prune/install
(e.g., run pnpm prune --prod or reinstall production deps) so that node_modules
only contains production packages, then keep the existing COPY --from=build
/app/node_modules ./node_modules to pull the slimmed modules into the runtime
image.

---

Nitpick comments:
In `@Dockerfiles/Dockerfile.agent-provisioning`:
- Line 2: Replace the pinned base image string "FROM node:24-alpine3.21" with a
current Alpine variant such as "FROM node:24-alpine3.23" (or at minimum
"node:24-alpine3.22") to ensure upstream CVE/patch fixes are included; update
the same FROM string in any other Dockerfiles referencing "node:24-alpine3.21"
(e.g., the other Dockerfile noted as 21-21) and rebuild images to verify no
downstream breakages from the base image bump.

In `@Dockerfiles/Dockerfile.api-gateway`:
- Line 2: Replace the superseded base image tag "node:24-alpine3.21" used in the
Dockerfile (the FROM node:24-alpine3.21 AS build line) with the current Alpine
patch variant, e.g. "node:24-alpine3.22" (or 24-alpine3.23), and apply the same
change to other Dockerfiles that use the same tag (the occurrences noted as
14-14) so all Node 24 Alpine base images are updated consistently.

In `@Dockerfiles/Dockerfile.geolocation`:
- Line 2: Update the Docker base image reference FROM node:24-alpine3.21 to a
supported Alpine patch (e.g. node:24-alpine3.22 or node:24-alpine3.23) in the
Dockerfile where the FROM node:24-alpine3.21 line appears so the image receives
current OS-level security patches; change the image tag consistently for other
Dockerfiles that use the same FROM node:24-alpine3.21 reference.

In `@Dockerfiles/Dockerfile.notification`:
- Line 2: Update the pinned base image string "node:24-alpine3.21" to a current
Alpine variant (e.g., "node:24-alpine3.22" or "node:24-alpine3.23") wherever it
appears (the Dockerfile FROM line using that tag), and do the same for the
analogous legacy image tag (e.g., "node:14-alpine3.21") referenced in the other
Dockerfile; ensure both FROM lines are changed so the build uses the newer
alpine3.22/3.23 variant to improve OS-level CVE coverage.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between aaed3a4 and 4e06601.

📒 Files selected for processing (20)
  • Dockerfiles/Dockerfile.agent-provisioning
  • Dockerfiles/Dockerfile.agent-service
  • Dockerfiles/Dockerfile.api-gateway
  • Dockerfiles/Dockerfile.cloud-wallet
  • Dockerfiles/Dockerfile.connection
  • Dockerfiles/Dockerfile.ecosystem
  • Dockerfiles/Dockerfile.geolocation
  • Dockerfiles/Dockerfile.issuance
  • Dockerfiles/Dockerfile.ledger
  • Dockerfiles/Dockerfile.notification
  • Dockerfiles/Dockerfile.oid4vc-issuance
  • Dockerfiles/Dockerfile.oid4vc-verification
  • Dockerfiles/Dockerfile.organization
  • Dockerfiles/Dockerfile.seed
  • Dockerfiles/Dockerfile.user
  • Dockerfiles/Dockerfile.utility
  • Dockerfiles/Dockerfile.verification
  • Dockerfiles/Dockerfile.webhook
  • Dockerfiles/Dockerfile.x509
  • package.json

Comment on lines +22 to +29
RUN apk update && apk upgrade && apk add --no-cache \
openssl \
openssh-client \
aws-cli \
docker \
docker-compose \
jq \
&& rm -rf /var/cache/apk/* \
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

find apps/agent-provisioning -type f \( -name "*.ts" -o -name "*.js" -o -name "*.sh" \) | head -20

Repository: credebl/platform

Length of output: 655


🏁 Script executed:

rg -n '\b(docker|aws)\b' apps/agent-provisioning/ --type=ts -C2

Repository: credebl/platform

Length of output: 42


🏁 Script executed:

rg -n 'docker|docker-compose|aws' apps/agent-provisioning/AFJ/ -C2

Repository: credebl/platform

Length of output: 13892


🏁 Script executed:

rg -n '\bexec(Sync)?\(' apps/agent-provisioning/ --type=ts -A2 | grep -E '(docker|aws)'

Repository: credebl/platform

Length of output: 42


🏁 Script executed:

rg -n 'spawn|exec|shell' apps/agent-provisioning/src/ --type=ts -B2 -A2

Repository: credebl/platform

Length of output: 2358


🏁 Script executed:

rg -n "import.*child_process" apps/agent-provisioning/src/ --type=ts

Repository: credebl/platform

Length of output: 157


🏁 Script executed:

cat apps/agent-provisioning/src/agent-provisioning.service.ts | head -100

Repository: credebl/platform

Length of output: 4118


Confirm runtime dependency of aws-cli, docker, and docker-compose packages.

The agent-provisioning service invokes these tools at runtime via shell scripts (start_agent_ecs.sh, start_agent.sh) executed during wallet provisioning requests. The walletProvision method in agent-provisioning.service.ts calls exec() to spin up agent containers and register ECS task definitions. These packages are justified runtime dependencies, though they significantly increase final image size and CVE surface. Consider evaluating whether to use lightweight alternatives or if image size/security posture is acceptable for this service's operational model.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.agent-provisioning` around lines 22 - 29, The
Dockerfile currently installs heavy runtime packages (aws-cli, docker,
docker-compose) that are used by shell scripts (start_agent_ecs.sh,
start_agent.sh) and by the walletProvision method in
agent-provisioning.service.ts via exec(); confirm whether these commands truly
must run inside the container at runtime and if not remove them from the final
image or replace with lighter alternatives (use AWS SDK calls from
walletProvision instead of aws-cli, call remote Docker daemon or include only
the docker client binary, or move tooling to a sidecar/host or a build-stage so
final image size/CVE surface is reduced); update the Dockerfile and the
referenced scripts/service accordingly and document the chosen operational model
if you keep the packages.

&& mkdir -p ./agent-provisioning/AFJ/token
COPY --from=build /app/dist/apps/agent-provisioning/ ./dist/apps/agent-provisioning/
COPY --from=build /app/node_modules ./node_modules
COPY --from=build /app/node_modules ./node_modules
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Final image contains all devDependencies — prune to production only.

COPY --from=build /app/node_modules ./node_modules copies the full install (TypeScript, test frameworks, linters, etc.) into the runtime image, bloating its size and widening the vulnerability surface.

Use a production-only install in the final stage instead:

♻️ Proposed fix — production install in final stage
+COPY --from=build /app/package.json /app/pnpm-lock.yaml /app/pnpm-workspace.yaml ./
+RUN npm install -g pnpm@9.15.3 --ignore-scripts \
+    && pnpm install --frozen-lockfile --ignore-scripts --prod \
+    && npm uninstall -g pnpm
-COPY --from=build /app/node_modules ./node_modules
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.agent-provisioning` at line 38, The final image
currently copies the entire build-stage node_modules via the COPY --from=build
/app/node_modules ./node_modules line, which brings devDependencies into the
runtime image; replace that approach by installing only production deps in the
final stage: copy package.json (and package-lock.json/yarn.lock) into the final
stage and run a production install (e.g., npm ci --only=production or npm ci &&
npm prune --production) or use NODE_ENV=production during install so
devDependencies are excluded; update the Dockerfile to remove the COPY
--from=build /app/node_modules ./node_modules and perform the production-only
install in the final stage (referencing the Dockerfile final stage where
node_modules is populated).


# Set the command to run the microservice
CMD ["sh", "-c", "cd libs/prisma-service && npx prisma migrate deploy && npx prisma generate && cd ../.. && node dist/apps/api-gateway/main.js"]
COPY --from=build /app/node_modules ./node_modules
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Final image contains all devDependencies — same concern as other services in this PR.

COPY --from=build /app/node_modules ./node_modules pulls in the full workspace install. Production-only install in the final stage trims this down significantly.

♻️ Proposed fix — production install in final stage
+COPY --from=build /app/package.json /app/pnpm-lock.yaml /app/pnpm-workspace.yaml ./
+RUN npm install -g pnpm@9.15.3 --ignore-scripts \
+    && pnpm install --frozen-lockfile --ignore-scripts --prod \
+    && npm uninstall -g pnpm
-COPY --from=build /app/node_modules ./node_modules
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
COPY --from=build /app/node_modules ./node_modules
COPY --from=build /app/package.json /app/pnpm-lock.yaml /app/pnpm-workspace.yaml ./
RUN npm install -g pnpm@9.15.3 --ignore-scripts \
&& pnpm install --frozen-lockfile --ignore-scripts --prod \
&& npm uninstall -g pnpm
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.api-gateway` at line 22, The final image currently
copies the entire workspace node_modules via "COPY --from=build
/app/node_modules ./node_modules", pulling devDependencies into production;
instead, in the final stage remove that COPY and perform a production-only
install/prune there (e.g., run a production npm/yarn install or npm prune
--production) so only production deps are present—update the Dockerfile final
stage around the COPY --from=build /app/node_modules ./node_modules to replace
the copy with a production install/prune step.


# Set the command to run the microservice
CMD ["sh", "-c", "cd libs/prisma-service && npx prisma migrate deploy && npx prisma generate && cd ../.. && node dist/apps/cloud-wallet/main.js"]
COPY --from=build /app/node_modules ./node_modules
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n Dockerfiles/Dockerfile.cloud-wallet

Repository: credebl/platform

Length of output: 1123


Avoid copying unpruned node_modules into production image.

Line 22 copies all build-stage dependencies, including devDependencies. The build stage (line 8) installs via pnpm i --frozen-lockfile --ignore-scripts without a subsequent pruning step, so devDependencies are unnecessarily included in the final image.

🔧 Proposed fix
 RUN cd libs/prisma-service && npx prisma generate
 RUN pnpm run build cloud-wallet
+RUN pnpm prune --prod
 
 # Stage 2: Create the final image
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.cloud-wallet` at line 22, The Dockerfile copies the
entire build-stage node_modules (COPY --from=build /app/node_modules
./node_modules), which includes devDependencies because the build stage ran pnpm
i --frozen-lockfile --ignore-scripts without pruning; fix by pruning
devDependencies before copying or installing only production deps in the final
image—either run pnpm prune --prod (or pnpm prune --prod --offline as
appropriate) in the build stage and then copy the pruned /app/node_modules, or
replace the copy with a production install in the final stage (e.g., run pnpm
install --prod --frozen-lockfile in the final stage) so that node_modules in the
final image contains only production dependencies.


# Set the command to run the microservice
CMD ["sh", "-c", "cd libs/prisma-service && npx prisma migrate deploy && npx prisma generate && cd ../.. && node dist/apps/connection/main.js"]
COPY --from=build /app/node_modules ./node_modules
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
f="Dockerfiles/Dockerfile.connection"
rg -n "pnpm i|pnpm install|pnpm prune --prod|node_modules" "$f"

Repository: credebl/platform

Length of output: 161


🏁 Script executed:

cat -n Dockerfiles/Dockerfile.connection

Repository: credebl/platform

Length of output: 1115


Remove devDependencies from the final runtime image by adding pnpm prune.

Line 22 copies the full node_modules directory from the build stage, which includes devDependencies installed at line 8. Add RUN pnpm prune --prod after the build step to remove development-only packages before they are copied to the final image.

🔧 Proposed fix
 RUN cd libs/prisma-service && npx prisma generate
 RUN pnpm run build connection
+RUN pnpm prune --prod
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.connection` at line 22, The final image currently
copies the entire node_modules from the build stage (COPY --from=build
/app/node_modules ./node_modules), which includes devDependencies; fix it by
running pnpm prune --prod in the build stage before copying so dev-only packages
are removed (add a RUN pnpm prune --prod step in the build stage after
install/build and before the COPY --from=build reference) ensuring the final
image only contains production dependencies.

Comment on lines +14 to +18
FROM node:24-alpine3.21
RUN apk update && apk upgrade && apk add --no-cache openssl \
&& rm -rf /var/cache/apk/* \
&& addgroup -g 1001 -S nodejs \
&& adduser -S nextjs -u 1001
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

adduser missing -G nodejs — user won't belong to the created group.

Line 17 creates the nodejs group, but line 18 doesn't assign nextjs to it (missing -G nodejs). Compare with Dockerfile.oid4vc-verification line 18 which correctly uses -G nodejs. Files owned by nodejs group won't be accessible to this user.

Proposed fix
 RUN apk update && apk upgrade && apk add --no-cache openssl \
     && rm -rf /var/cache/apk/* \
     && addgroup -g 1001 -S nodejs \
-    && adduser -S nextjs -u 1001
+    && adduser -S nextjs -u 1001 -G nodejs
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
FROM node:24-alpine3.21
RUN apk update && apk upgrade && apk add --no-cache openssl \
&& rm -rf /var/cache/apk/* \
&& addgroup -g 1001 -S nodejs \
&& adduser -S nextjs -u 1001
FROM node:24-alpine3.21
RUN apk update && apk upgrade && apk add --no-cache openssl \
&& rm -rf /var/cache/apk/* \
&& addgroup -g 1001 -S nodejs \
&& adduser -S nextjs -u 1001 -G nodejs
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.oid4vc-issuance` around lines 14 - 18, The adduser
invocation for the nextjs user is not adding it to the nodejs group; update the
Dockerfile by modifying the adduser command (the adduser call that creates
"nextjs") to include the group flag "-G nodejs" so the nextjs user is a member
of the nodejs group created by the addgroup call (symbols to change: addgroup -g
1001 -S nodejs and adduser -S nextjs -u 1001 → ensure adduser includes -G
nodejs).

Comment on lines +14 to +18
FROM node:24-alpine3.21
RUN apk update && apk upgrade && apk add --no-cache openssl \
&& rm -rf /var/cache/apk/* \
&& addgroup -g 1001 -S nodejs \
&& adduser -S nextjs -u 1001
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

adduser missing -G nodejs.

Same inconsistency as the other Dockerfiles — the nodejs group is created but nextjs user isn't added to it.

Proposed fix
-    && adduser -S nextjs -u 1001
+    && adduser -S nextjs -u 1001 -G nodejs
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
FROM node:24-alpine3.21
RUN apk update && apk upgrade && apk add --no-cache openssl \
&& rm -rf /var/cache/apk/* \
&& addgroup -g 1001 -S nodejs \
&& adduser -S nextjs -u 1001
FROM node:24-alpine3.21
RUN apk update && apk upgrade && apk add --no-cache openssl \
&& rm -rf /var/cache/apk/* \
&& addgroup -g 1001 -S nodejs \
&& adduser -S nextjs -u 1001 -G nodejs
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.organization` around lines 14 - 18, The Dockerfile
creates the nodejs group with addgroup -g 1001 -S nodejs but then adds the
nextjs user without assigning it to that group; update the adduser invocation
(the one creating nextjs) to include the group flag so nextjs is added to nodejs
(use adduser -S nextjs -u 1001 -G nodejs) to match other Dockerfiles and ensure
correct group membership.

Comment on lines +1 to +8
FROM node:24-alpine3.21
RUN apk update && apk upgrade && apk add --no-cache \
postgresql-client \
openssl \
&& rm -rf /var/cache/apk/* \
&& addgroup -g 1001 -S nodejs \
&& adduser -S nextjs -u 1001 \
&& npm install -g pnpm@9.15.3 --ignore-scripts
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

adduser missing -G nodejschown nextjs:nodejs on line 16 won't grant group access as intended.

Line 6 creates the nodejs group and line 7 creates the nextjs user, but without -G nodejs the user's primary group defaults to a new auto-created group, not nodejs. The chown -R nextjs:nodejs /app on line 16 sets group ownership to nodejs, but the nextjs user won't be a member of that group.

Proposed fix
-    && adduser -S nextjs -u 1001 \
+    && adduser -S nextjs -u 1001 -G nodejs \
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.seed` around lines 1 - 8, The adduser invocation
currently creates the nextjs user without assigning it to the previously-created
nodejs group, so chown -R nextjs:nodejs won't give the user group membership;
update the adduser command (the line that calls adduser -S nextjs -u 1001) to
include the nodejs group (e.g., adduser -S nextjs -u 1001 -G nodejs) so the
nextjs user is created as a member of group nodejs and the subsequent chown -R
nextjs:nodejs will grant the intended access.

Comment on lines +14 to +18
FROM node:24-alpine3.21
RUN apk update && apk upgrade && apk add --no-cache openssl \
&& rm -rf /var/cache/apk/* \
&& addgroup -g 1001 -S nodejs \
&& adduser -S nextjs -u 1001
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

adduser missing -G nodejs.

Same inconsistency. Add -G nodejs to match Dockerfile.oid4vc-verification.

Proposed fix
-    && adduser -S nextjs -u 1001
+    && adduser -S nextjs -u 1001 -G nodejs
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
FROM node:24-alpine3.21
RUN apk update && apk upgrade && apk add --no-cache openssl \
&& rm -rf /var/cache/apk/* \
&& addgroup -g 1001 -S nodejs \
&& adduser -S nextjs -u 1001
FROM node:24-alpine3.21
RUN apk update && apk upgrade && apk add --no-cache openssl \
&& rm -rf /var/cache/apk/* \
&& addgroup -g 1001 -S nodejs \
&& adduser -S nextjs -u 1001 -G nodejs
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.user` around lines 14 - 18, The adduser invocation in
the Dockerfile is missing the group flag, causing the new user not to be placed
into the nodejs group; update the adduser command (the line that currently calls
adduser -S nextjs -u 1001) to include -G nodejs so the created user is assigned
to the addgroup-created nodejs group (refer to the addgroup and adduser commands
in the diff).


# Set the command to run the microservice
CMD ["sh", "-c", "cd libs/prisma-service && npx prisma migrate deploy && npx prisma generate && cd ../.. && node dist/apps/verification/main.js"]
COPY --from=build /app/node_modules ./node_modules
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
f="Dockerfiles/Dockerfile.verification"
# Check if file exists and view relevant content
if [ -f "$f" ]; then
  echo "=== Full Dockerfile Content ==="
  cat -n "$f"
  echo ""
  echo "=== Search for pnpm commands and node_modules ==="
  rg -n "pnpm i|pnpm install|pnpm prune --prod|node_modules" "$f"
else
  echo "File not found: $f"
fi

Repository: credebl/platform

Length of output: 1308


Production image should not include devDependencies.

Line 22 copies the full build-stage node_modules including dev dependencies. Add a pnpm prune --prod step before the final copy to reduce image size and security surface.

🔧 Proposed fix
 RUN cd libs/prisma-service && npx prisma generate
 RUN pnpm run build verification
+RUN pnpm prune --prod
 
 # Stage 2: Create the final image
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.verification` at line 22, The final image currently
copies the full build-stage node_modules (COPY --from=build /app/node_modules
./node_modules), which includes devDependencies; before that COPY run pnpm prune
--prod in the build stage (or create a dedicated pruned step) so devDependencies
are removed and only production deps remain, then copy the pruned
/app/node_modules into the final image.

Signed-off-by: DeepakNemad <deepak.nemade@ayanworks.com>
Signed-off-by: DeepakNemad <deepak.nemade@ayanworks.com>
@sonarqubecloud
Copy link

Copy link

@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: 1

♻️ Duplicate comments (2)
Dockerfiles/Dockerfile.x509 (2)

24-24: ⚠️ Potential issue | 🔴 Critical

Ensure Prisma migrations are executed before service startup.

Directly starting Node at Line 24 can skip prisma migrate deploy if your deployment pipeline does not run migrations elsewhere, which can break on schema drift.

#!/bin/bash
# Verify whether migrations are executed outside container startup (read-only checks).

rg -n --glob '!**/node_modules/**' 'prisma migrate deploy|prisma migrate|migrate deploy'
rg -n --glob '!**/node_modules/**' 'initContainers|helm\.sh/hook|pre-upgrade|pre-install'
rg -n '"start"\s*:\s*".*prisma migrate deploy' package.json
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.x509` at line 24, The Dockerfile currently starts the
service directly with CMD ["node", "dist/apps/x509/main.js"], which can skip
running Prisma migrations; change startup to run migrations first (e.g., run
`prisma migrate deploy` or `npm exec prisma migrate deploy`) before starting
Node by replacing the direct CMD with an ENTRYPOINT/CMD that executes a small
startup script or command sequence that runs migrations (using prisma via npm
exec/npx if Prisma binary isn't globally installed), then execs node
dist/apps/x509/main.js; ensure the startup script references the same
environment variables used by Prisma (DATABASE_URL, etc.) and that the image
includes/install Prisma tooling so migrate deploy can run at container start.

8-8: ⚠️ Potential issue | 🟠 Major

Prune dev dependencies before copying node_modules to the runtime image.

pnpm i in the build stage installs devDependencies, and Line 22 copies that full tree into production. That undermines the vulnerability-reduction goal and inflates runtime attack surface.

Suggested fix
 RUN pnpm i --frozen-lockfile --ignore-scripts
 COPY . .
 RUN cd libs/prisma-service && npx prisma generate
 RUN pnpm run build x509
+RUN pnpm prune --prod

Also applies to: 22-22

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.x509` at line 8, The build stage runs "RUN pnpm i
--frozen-lockfile --ignore-scripts" which installs devDependencies but later the
full node_modules tree is copied into the runtime image (the COPY of
node_modules from the build stage), so remove devDeps before that copy: either
run "pnpm install --frozen-lockfile --prod" in place of the current install or
run "pnpm prune --prod" immediately after "RUN pnpm i --frozen-lockfile
--ignore-scripts" so the subsequent COPY of node_modules only includes
production dependencies.
🧹 Nitpick comments (1)
Dockerfiles/Dockerfile.oid4vc-verification (1)

4-4: Consider upgrading to pnpm v10.

The current npm latest tag for pnpm is 10.30.2. pnpm@9.15.3 is the final v9 patch and pnpm v10 has been the actively maintained line for some time. Staying on v9 means missing security and performance improvements. Consider bumping to a pinned v10 release across all Dockerfiles.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.oid4vc-verification` at line 4, Update the RUN
installation to pin pnpm v10 instead of v9: replace the RUN line that installs
pnpm (currently "RUN npm install -g pnpm@9.15.3 --ignore-scripts") with a pinned
v10 release (e.g., "pnpm@10.x" or a specific v10 patch like "pnpm@10.30.2")
across all Dockerfiles so the installer uses the maintained v10 line and gets
security/performance fixes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@Dockerfiles/Dockerfile.oid4vc-verification`:
- Around line 21-22: The COPY commands that set --chmod=444 for node_modules and
libs strip execute bits and break native binaries (e.g., Prisma query engine)
and directory traversal; update the two COPY lines that reference "/app/libs/
./libs/" and "/app/node_modules ./node_modules" to avoid forcing 444 — either
remove the --chmod flag for those COPYs or use a mode that preserves exec bits
(e.g., 0755) so binaries and directories remain executable at runtime.

---

Duplicate comments:
In `@Dockerfiles/Dockerfile.x509`:
- Line 24: The Dockerfile currently starts the service directly with CMD
["node", "dist/apps/x509/main.js"], which can skip running Prisma migrations;
change startup to run migrations first (e.g., run `prisma migrate deploy` or
`npm exec prisma migrate deploy`) before starting Node by replacing the direct
CMD with an ENTRYPOINT/CMD that executes a small startup script or command
sequence that runs migrations (using prisma via npm exec/npx if Prisma binary
isn't globally installed), then execs node dist/apps/x509/main.js; ensure the
startup script references the same environment variables used by Prisma
(DATABASE_URL, etc.) and that the image includes/install Prisma tooling so
migrate deploy can run at container start.
- Line 8: The build stage runs "RUN pnpm i --frozen-lockfile --ignore-scripts"
which installs devDependencies but later the full node_modules tree is copied
into the runtime image (the COPY of node_modules from the build stage), so
remove devDeps before that copy: either run "pnpm install --frozen-lockfile
--prod" in place of the current install or run "pnpm prune --prod" immediately
after "RUN pnpm i --frozen-lockfile --ignore-scripts" so the subsequent COPY of
node_modules only includes production dependencies.

---

Nitpick comments:
In `@Dockerfiles/Dockerfile.oid4vc-verification`:
- Line 4: Update the RUN installation to pin pnpm v10 instead of v9: replace the
RUN line that installs pnpm (currently "RUN npm install -g pnpm@9.15.3
--ignore-scripts") with a pinned v10 release (e.g., "pnpm@10.x" or a specific
v10 patch like "pnpm@10.30.2") across all Dockerfiles so the installer uses the
maintained v10 line and gets security/performance fixes.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4e06601 and 24ad3df.

📒 Files selected for processing (2)
  • Dockerfiles/Dockerfile.oid4vc-verification
  • Dockerfiles/Dockerfile.x509

Comment on lines +21 to +22
COPY --chown=nextjs:nodejs --chmod=444 --from=build /app/libs/ ./libs/
COPY --chown=nextjs:nodejs --chmod=444 --from=build /app/node_modules ./node_modules
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# First, let's locate and examine the Dockerfile
find . -name "Dockerfile.oid4vc-verification" -type f

Repository: credebl/platform

Length of output: 104


🏁 Script executed:

# Read the Dockerfile to confirm lines 21-22
cat -n Dockerfiles/Dockerfile.oid4vc-verification | head -25

Repository: credebl/platform

Length of output: 1257


🏁 Script executed:

# Check if Prisma is used in the project
find . -name "package.json" -type f | head -5 | xargs grep -l "prisma" 2>/dev/null || true

Repository: credebl/platform

Length of output: 101


🏁 Script executed:

# Look for any Prisma schema files
find . -name "schema.prisma" -o -name ".prismarc*" 2>/dev/null || true

Repository: credebl/platform

Length of output: 102


🏁 Script executed:

# Check package.json to see if Prisma is a dependency
cat ./package.json | grep -A 5 -B 5 "prisma"

Repository: credebl/platform

Length of output: 3043


🏁 Script executed:

# Look for any .node files or query-engine binaries in the repo
find . -name "*.node" -o -name "*query-engine*" -type f 2>/dev/null | grep -v node_modules | head -20

Repository: credebl/platform

Length of output: 42


🏁 Script executed:

# Check Prisma client generation output location
cat ./libs/prisma-service/prisma/schema.prisma | head -30

Repository: credebl/platform

Length of output: 1588


🏁 Script executed:

# Look at what happens when prisma is installed - check if there's any reference to query engine binaries
# Check the actual Prisma client code dependencies
grep -r "query.engine\|query-engine\|libquery" . --include="*.ts" --include="*.js" 2>/dev/null | head -10 || true

Repository: credebl/platform

Length of output: 42


🏁 Script executed:

# Look for any shell scripts or configs that might show Prisma engine setup
find ./libs/prisma-service -type f \( -name "*.ts" -o -name "*.js" -o -name "*.json" \) 2>/dev/null | head -10

Repository: credebl/platform

Length of output: 384


🏁 Script executed:

# Check if there are any built artifacts that would show us what Prisma generates
ls -la ./libs/prisma-service/ 2>/dev/null || true

Repository: credebl/platform

Length of output: 408


🌐 Web query:

Prisma 5.22.0 query engine binary native executable requirements Docker

💡 Result:

For Prisma 5.22.0’s native query engine to run inside Docker, your container image must provide the Linux runtime libs that match the engine binary Prisma will download (glibc vs musl, plus OpenSSL version).

Native engine runtime requirements (Linux containers)

Prisma’s query engine expects these system libraries at runtime: OpenSSL (1.0.x / 1.1.x / 3.x), zlib (libz.so.1), libgcc (libgcc_s.so.1), and a compatible C standard library (glibc on Debian/Ubuntu/etc. or musl on Alpine). It also requires minimum glibc versions depending on the OpenSSL target (commonly glibc 2.24+ for OpenSSL 1.1/3 targets on Debian-family). [1]

What that means for common Docker base images

Debian/Ubuntu-based images (glibc)

  • Use a Debian/Ubuntu base (for example node:slim), and ensure OpenSSL is installed (some slim images may not include libssl by default). [2]

Alpine-based images (musl)

  • Use Alpine (node:alpine) and install OpenSSL as needed (e.g., openssl/openssl3 depending on Alpine version).
  • Do not add glibc compatibility layers (e.g., libc6-compat) to “make Prisma work”; Prisma’s Alpine support is intended to use musl engines, and adding glibc can break it. [2]
  • If OpenSSL/libssl isn’t installed/detected, Prisma can fail trying to load libssl.so.* (a common cause of “could not locate the Query Engine” errors on Alpine). [3]

Practical checklist

  1. Pick base image: Debian/Ubuntu (glibc) or Alpine (musl).
  2. Ensure runtime libs exist: libssl + libcrypto (OpenSSL), zlib, libgcc. [1]
  3. Generate Prisma Client inside the same OS family you will run (or set binaryTargets appropriately) so the downloaded engine matches the container runtime. [2]

Sources: Prisma system requirements [1], Prisma Docker guide (Alpine vs Debian notes) [2], Prisma Alpine OpenSSL detection issue showing libssl.so failures [3].


🌐 Web query:

Prisma query engine chmod execute permission Docker COPY node_modules

💡 Result:

This usually happens because you COPY node_modules from the host into the image and the Prisma engine file(s) end up without the executable bit (or with wrong ownership). Prisma’s Rust engines are binaries copied into your generated client during prisma generate (typically under node_modules/.prisma/client/), so if that binary isn’t executable you’ll see “permission denied” when Prisma tries to run it. (docs.prisma.io)

Best fix (recommended): don’t COPY node_modules; install + generate inside Docker

Prisma’s Docker guidance is to build in-container (so the correct Linux engine is downloaded and permissions are correct). (docs.prisma.io)

Example pattern:

FROM node:20-slim
WORKDIR /app

COPY package.json package-lock.json ./
RUN npm ci

COPY prisma ./prisma
RUN npx prisma generate

COPY . .
CMD ["node","dist/index.js"]

If you must COPY node_modules: re-add execute bit (and/or ownership) in the image

Prisma engine binaries are commonly here:

  • node_modules/.prisma/client/query-engine*
  • sometimes also under node_modules/@prisma/engines/*

Add:

COPY node_modules ./node_modules
RUN chmod +x node_modules/.prisma/client/query-engine* || true
RUN chmod +x node_modules/@prisma/engines/*query-engine* || true

If the container runs as a non-root user (e.g. node), you may also need:

RUN chown -R node:node node_modules/.prisma

(ownership issues can also present as EACCES). (stackoverflow.com)

If you want to fix permissions at COPY-time (BuildKit): COPY --chmod

Docker supports setting mode bits directly on copy: (docs.docker.com)

# syntax=docker/dockerfile:1.10
COPY --chmod=0o755 node_modules/.prisma/client/query-engine* node_modules/.prisma/client/

If you paste your Dockerfile (and whether you’re on Windows/macOS/Linux, and which base image: alpine vs slim), I can point to the exact Prisma engine path your build is producing and the minimal change.

Citations:


--chmod=444 on node_modules and libs strips execute bits — will cause runtime failures.

chmod=444 (r--r--r--) removes the execute bit from every file. Prisma 5.22.0's query engine is a native binary (stored in node_modules/.prisma/client/query-engine-*) that must be executable. The Dockerfile's line 10 (npx prisma generate) generates these binaries during the build stage, and when they're copied with --chmod=444, they become unexecutable. At container startup, Node/Prisma will fail with "permission denied" when trying to spawn the query engine.

The dist/ tree (line 20) is safe with 444 since it contains only JS files. Both libs/ and node_modules/ require execute permission for binaries and directories.

🐛 Proposed fix
-COPY --chown=root:nodejs --chmod=444 --from=build /app/libs/ ./libs/
-COPY --chown=root:nodejs --chmod=444 --from=build /app/node_modules ./node_modules
+COPY --chown=root:nodejs --chmod=755 --from=build /app/libs/ ./libs/
+COPY --chown=root:nodejs --chmod=755 --from=build /app/node_modules ./node_modules
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
COPY --chown=nextjs:nodejs --chmod=444 --from=build /app/libs/ ./libs/
COPY --chown=nextjs:nodejs --chmod=444 --from=build /app/node_modules ./node_modules
COPY --chown=nextjs:nodejs --chmod=755 --from=build /app/libs/ ./libs/
COPY --chown=nextjs:nodejs --chmod=755 --from=build /app/node_modules ./node_modules
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfiles/Dockerfile.oid4vc-verification` around lines 21 - 22, The COPY
commands that set --chmod=444 for node_modules and libs strip execute bits and
break native binaries (e.g., Prisma query engine) and directory traversal;
update the two COPY lines that reference "/app/libs/ ./libs/" and
"/app/node_modules ./node_modules" to avoid forcing 444 — either remove the
--chmod flag for those COPYs or use a mode that preserves exec bits (e.g., 0755)
so binaries and directories remain executable at runtime.

@ajile-in
Copy link
Member

@KambleSahil3 pls review

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.

2 participants