Skip to content

Fix static path traversal, improve first-run UX, add Docker/Hub docs#20

Merged
mrhegemon merged 1 commit into
mainfrom
chore/deep-test-fixes
Jun 10, 2026
Merged

Fix static path traversal, improve first-run UX, add Docker/Hub docs#20
mrhegemon merged 1 commit into
mainfrom
chore/deep-test-fixes

Conversation

@mrhegemon

Copy link
Copy Markdown
Member

Deep-test pass on the published ghcr.io/companionintelligence/ci-local-bench:latest container. Three fixes, all verified against a rebuilt image.

Security (high): static-file path traversal

The static handler resolved requests as '.' + req.url with no containment check. Against the live container, GET /../../../etc/passwd (raw, --path-as-is) returned HTTP 200 with the contents of /etc/passwd.

Fix: resolve each request against a fixed STATIC_ROOT (= process.cwd()), URL-decode and path.normalize first, and reject anything that escapes the root. After the fix the same request returns 404 and the real file is never read. Adds a regression test asserting the resolved path stays inside the root.

First-run UX

A fresh Hub install (no benchmark data, no Ollama) rendered a red ⚠️ Error: No benchmark results found banner at the top of the page — the first thing every new user sees, for an entirely expected empty state. Replaced with a neutral, welcoming info message that points to the Run Benchmark flow. The model picker / specs / chart already degraded gracefully; only the error banner was alarming.

Docs

README had no container section. Added a Docker / Companion Intelligence Hub section: public image, internal port 3000, the real OLLAMA_API_URL env var (with host.docker.internal and LAN examples), the graceful no-Ollama / first-run behavior, and where results are written for persistence.

Verification

  • npm ci && npm test111/111 jest tests pass (110 original + 1 new traversal test); tsc build clean.
  • Container test spec (tests/container, APP_URL=...) passes; playwright console sweep shows no JS errors (only the expected /api/models 503 when Ollama is absent).
  • Rebuilt image: GET / 200, all GET endpoints behave, traversal closed, logs clean, restart OK.

No redesigns; minimal, on-brand changes only.

🤖 Generated with Claude Code

Deep-test findings on the published ci-local-bench container:

Security: the static file handler resolved request paths with `'.' + req.url`
and no containment check, so `GET /../../../etc/passwd` returned 200 with the
file contents. Resolve requests against a fixed STATIC_ROOT (process.cwd()),
normalize + decode first, and reject anything that escapes the root. Adds a
regression test proving the real /etc/passwd is never read.

First-run UX: a fresh Hub install (no benchmark data) showed a red "⚠️ Error:
No benchmark results found" banner — alarming for the expected empty state that
every new user sees. Replace it with a neutral, welcoming empty-state message
that points the user at the Run Benchmark flow.

Docs: README had no container section. Add a Docker / Companion Intelligence Hub
section documenting the public image, port 3000, the OLLAMA_API_URL env var (the
real var the code reads) with host.docker.internal/LAN examples, the graceful
no-Ollama / first-run behavior, and result persistence.

All 111 jest tests pass; tsc build clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@mrhegemon mrhegemon merged commit fd94ccc into main Jun 10, 2026
1 check passed
@mrhegemon mrhegemon deleted the chore/deep-test-fixes branch June 10, 2026 14:18
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.

1 participant