fix(docker): entrypoint integrity check for 0-byte server.js (#3542)#3543
Conversation
A corrupt or incomplete image pull can leave dist/server/server.js as a 0-byte file. Node exits 0 immediately, supervisord retries to FATAL, and the container crash-loops with no actionable message beyond "exited: meshmonitor (exit status 0; not expected)". Add an entrypoint integrity check before the supervisord handoff: if /app/dist/server/server.js is missing or empty, print a clear error with the remediation (docker rmi + pull) and exit non-zero so the real cause shows up in `docker compose logs`. Runs ahead of both the root and non-root exec paths. Fixes #3542 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Claude finished @Yeraze's task —— View job PR Review:
|
…3542) The remediation message hardcoded ghcr.io/yeraze/meshmonitor, which would be misleading for custom builds or self-hosted registries. Use a generic <meshmonitor image> placeholder instead (Claude review feedback). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Thanks for the review! Addressed the substantive suggestion in
Declining the rest as noted (all flagged minor/optional by the review):
|
|
Claude encountered an error —— View job I'll analyze this and get back to you. |
|
Claude finished @Yeraze's task —— View job PR Review:
|
…#152/153/155/156) (#3544) * fix(security): use RE2 for user-supplied regexes to eliminate ReDoS (#3543) Resolves the two high-severity CodeQL js/regex-injection alerts (#153, #155) by compiling all user/admin-supplied regular expressions with RE2, a linear-time engine immune to catastrophic backtracking. The previous heuristic guards (length caps + nested-quantifier checks) reduced but could not eliminate the risk, and CodeQL (correctly) kept flagging the user→RegExp dataflow. - New src/utils/safeRegex.ts: compileUserRegex(pattern, flags) wraps RE2 and returns a RegExp-compatible matcher (test/exec/match/replace). RE2 rejects backreferences and lookaround — the intended trade-off — so callers keep their existing try/catch to treat unsupported patterns as "invalid regex". - Convert every user-supplied regex site, validation AND execution: - server.ts: remote(-localstats) name-filter validation (2 sites). - services/database.ts: the name-filter execution sites that actually match node names (traceroute + localstats union filters) — the real ReDoS surface CodeQL didn't reach through the settings store. - routes/scriptRoutes.ts + meshtasticManager.ts: auto-responder trigger and auto-acknowledge pattern matching. - Dockerfile: add build-base + python3 to the builder stage so re2 (native) can compile from source where no prebuilt exists (Alpine/musl arm). Builder stage only — not in the runtime image. Tests: new safeRegex suite asserts linear-time behaviour on the classic (a+)+$ ReDoS pattern and rejection of backreference/lookaround. Full suite green. The two non-regex alerts are handled separately: #152 (frontend routing, not a security gate) dismissed as false-positive; #156 (authenticated admin script import, path-sanitized) dismissed as by-design. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * address review: convert remaining regex sites to RE2; harden tests/docs (#3544) Claude review feedback on the RE2 security PR: 1. autoAckRegex.ts:69 — convert the MeshCore auto-ack pattern compile to compileUserRegex (the charset allowlist/length/shape guards stay as a fast pre-rejection). Residual ReDoS surface CodeQL may not flag through the barrier, now closed for consistency. 2. settingsRoutes.ts:215 — convert the regex-validation compile to compileUserRegex so stored patterns are guaranteed RE2-compatible. 3. safeRegex.ts — document that the result is not `instanceof RegExp` and that length bounding stays the caller's responsibility; add a test asserting `.source`/`.flags` behave. 4. safeRegex.test.ts — raise the ReDoS timing threshold to 1000ms and use a larger input, so the assertion can't flake on loaded CI runners. 5. Dockerfile — clarify the builder comment (build-base is the new compiler; python3 is node-gyp's other requirement). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Summary
Fixes #3542. A corrupt or incomplete
docker compose pullcan leavedist/server/server.jsas a 0-byte file. Node then exits0immediately, supervisord retries until FATAL, and the container crash-loops with no actionable message beyondexited: meshmonitor (exit status 0; not expected).This adds the recommended entrypoint integrity check: before handing off to supervisord, verify
/app/dist/server/server.jsexists and is non-empty. If not, print a clear error with the remediation and exit non-zero so the real cause is visible indocker compose logs.Why this approach
Per the issue's analysis, the entrypoint check is the lowest-friction option — actionable error, zero ongoing maintenance (vs. SHA digest pinning) and it explains why (vs. a bare healthcheck).
Details
docker/docker-entrypoint.shimmediately before the supervisordexec, so it runs ahead of both the root and non-root execution paths.npm start→node dist/server/server.js(working dir/app).sh([ ! -s … ]);sh -nsyntax-clean.Testing
sh -npasses.✓ Server bundle present (N bytes)); CI's system tests exercise normal container startup.🤖 Generated with Claude Code