Skip to content

fix(docker): resolve KICS alerts on lido-governance-monitor Dockerfile#3526

Merged
kyzooghost merged 3 commits into
mainfrom
fix/lido-governance-monitor-dockerfile-kics
Jul 8, 2026
Merged

fix(docker): resolve KICS alerts on lido-governance-monitor Dockerfile#3526
kyzooghost merged 3 commits into
mainfrom
fix/lido-governance-monitor-dockerfile-kics

Conversation

@kyzooghost

Copy link
Copy Markdown
Contributor

Summary

Resolves the 11 open KICS code-scanning alerts on operations/native-yield/lido-governance-monitor/Dockerfile (alert query).

The KICS workflow is currently disabled (.github/workflows/dockerfile-security-scan.yml, if: false) due to the Checkmarx/KICS supply-chain compromise (2026-04-22), so these alerts no longer auto-close on re-scan. Stale alerts are dismissed via the code-scanning API with reasons referencing this PR.

Alert handling

Alert(s) Rule Handling
18912 NPM Install Without Pinned Version Fixed: pin corepack@0.35.0 (was @latest)
20308-20311 Chown Flag Exists Fixed: drop --chown=node:node on runtime COPYs; files stay root-owned (node user only needs read/execute; prevents tampering)
18909-18911, 20307 Apt Get Install Pin Version Not Defined Suppressed (kics-scan ignore-line): packages track node:slim; pinning breaks builds on base refresh for negligible gain
18913 NPM Install Without Pinned Version Suppressed: pnpm install --frozen-lockfile pins versions via pnpm-lock.yaml (false positive)
20312 Healthcheck Instruction Missing Suppressed: one-shot batch job (run.ts exits after a single execution), not a long-running server; HEALTHCHECK N/A

Notes

  • The writable Prisma cache (/home/node/.cache/prisma) is still chown'd to node since it is written at runtime; only the read-only runtime files (dist, prompts, migrations) are root-owned.
  • Sibling Dockerfiles (automation-service, postman) share the same patterns but are intentionally out of scope for this PR.

Test plan

  • Docker image builds successfully (docker build against the updated Dockerfile)
  • Container starts, runs the one-shot job, and exits cleanly as the node user
  • Prisma migrate deploy can read the root-owned migrations directory
  • Re-running KICS (when re-enabled) reports 0 findings on this Dockerfile

Made with Cursor

Address the 11 open KICS findings on the lido-governance-monitor Dockerfile.
KICS scan is currently disabled (.github/workflows/dockerfile-security-scan.yml)
due to the Checkmarx supply-chain compromise, so these alerts no longer auto-close.

Genuine fixes:
- Pin corepack to 0.35.0 instead of @latest (NPM Install Without Pinned Version)
- Drop --chown=node:node on runtime COPYs so files stay root-owned; the node user
  only needs read/execute and root ownership prevents tampering (Chown Flag Exists)

Suppressed with kics-scan ignore-line + documented justification:
- apt-get install (ca-certificates, bash, curl, openssl): not pinned; versions track
  the node:slim base image and pinning would break builds on base refresh for
  negligible gain (Apt Get Install Pin Version Not Defined)
- pnpm install --frozen-lockfile: versions are pinned by pnpm-lock.yaml; this is a
  workspace install, not a single-package add (NPM Install Without Pinned Version)
- HEALTHCHECK: not applicable, this image is a one-shot batch job (run.ts exits
  after a single execution), not a long-running server (Healthcheck Instruction Missing)

Co-authored-by: Cursor <cursoragent@cursor.com>
@codecov

codecov Bot commented Jul 7, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@eloi010
eloi010 self-requested a review July 7, 2026 11:35
… migrate

The previous commit dropped --chown=node:node on runtime COPYs, leaving all of
node_modules root-owned. That broke the production init container, which runs
`prisma migrate deploy` before app start (docs/db-migration.md): prisma extracts
the schema-engine binary into node_modules/.pnpm/@prisma+engines@*/.../engines on
first run and needs write access there. With root ownership, migrate deploy fails
with "Can't write to .../@prisma/engines" and the pod will not start.

Fix: keep runtime files root-owned (security benefit + KICS Chown alerts resolved)
but chown only the prisma engines subdir to node via RUN chown. KICS "Chown Flag
Exists" targets the COPY --chown flag, not RUN chown, so this does not re-trigger
the rule.

Verified locally:
- Image builds; prisma migrate deploy from the container as the node user now
  succeeds against the test DB (was failing).
- dist/run.js stays root-owned; engines dir and prisma cache are node-owned.
- App boots to expected config validation; jest suite still passes (229 tests).

Co-authored-by: Cursor <cursoragent@cursor.com>
@kyzooghost

Copy link
Copy Markdown
Contributor Author

E2E validation update

Ran the full README "E2E Local Test" pipeline against live APIs inside the production container (with the Dockerfile changes from this PR) to confirm the runtime changes don't break the pipeline.

Scope reduction (cost control): INITIAL_LDO_VOTING_CONTRACT_VOTEID=202 (latest on-chain vote only; votesLength=203) and MAX_TOPICS_PER_POLL=2, so ~3 proposals went through the pipeline instead of the full ~70 (53 on-chain + 20 Discourse) - each triggers a paid Claude call. This is enough to exercise every pipeline stage.

Result: full pipeline passes end-to-end, exit 0.

Stage Result
prisma migrate deploy from container (init-container step, docs/db-migration.md) ✅ applied
DB connect (Prisma client, root-owned node_modules + node-owned engines dir)
Discourse fetch ✅ 2 proposals
On-chain LDO fetch (Alchemy RPC) ✅ vote #202
DB persist ✅ all 3
Claude AI analysis (claude-haiku-4-5-20251001) ✅ 3/3 (riskScore 22, 0, 8)
Notification threshold logic
Slack POST to dead link (http://localhost:9000) fetch failed → caught, retried, gave up gracefully (no crash)
One-shot completion ✅ exit 0

Pre-existing app issues found (NOT related to this Dockerfile PR - flagging for a separate issue):

  • The default model claude-sonnet-4-20250514 (src/application/main/config/index.ts:99) is deprecated/EOL since 2025-06-15 and returns HTTP 404 from Anthropic. Out of the box the E2E fails at AI analysis unless CLAUDE_MODEL is overridden to a current model (e.g. claude-haiku-4-5-20251001). Recommend updating the default.
  • claude-haiku-4-5 occasionally emits malformed JSON (1 of 6 analyses across runs); the app handles this gracefully (logs + transitions to ANALYSIS_FAILED for retry).

No Dockerfile/runtime regressions. The --chown removal + targeted prisma-engines RUN chown fix is verified working in the full E2E.

Three changes from code review:

- corepack: `npm i` -> `npm install` (KICS only whitelists the literal
  word `install`, not the `i` alias, so the finding survived the pin)

- HEALTHCHECK: replace `kics-scan ignore-line` on the production FROM
  with an explicit `HEALTHCHECK NONE` near CMD; ignore-line would also
  silence any future rules anchored to that FROM line, and NONE is the
  correct declaration for a one-shot batch job anyway

- apt pinning: replace two per-block `kics-scan ignore-line` comments
  with a single file-global `kics-scan disable=965a08d7-...` at the top
  of the file, so other apt checks (--no-install-recommends, list
  cleanup) remain active

Co-authored-by: Cursor <cursoragent@cursor.com>

@eloi010 eloi010 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM ✅

@kyzooghost
kyzooghost merged commit 3ce842a into main Jul 8, 2026
45 checks passed
@kyzooghost
kyzooghost deleted the fix/lido-governance-monitor-dockerfile-kics branch July 8, 2026 08:02
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