Skip to content

fix(security): remediate review 08 findings - #1

Merged
mattDev0 merged 15 commits into
mainfrom
fix/review-08-remediation
Aug 22, 2026
Merged

fix(security): remediate review 08 findings#1
mattDev0 merged 15 commits into
mainfrom
fix/review-08-remediation

Conversation

@mattDev0

Copy link
Copy Markdown
Owner

Remediates the findings in docs/reviews/review_08_workspace-engineering-review.md, following docs/implementation-plans/implementation_plan_15_review-08-remediation.md and the correction pass in plan 16.

Critical

  • C-1 — Anonymous users could stop any container on the host. POST /api/servers/docker/containers/{id}/{action} matched no ADMIN rule and fell through to the ROLE_GUEST tier, and guest tokens are issued to anyone via POST /api/auth/guest. The only gate was a disabled button in the UI. Adds the server-side matcher plus regression tests on every mutating route.
  • C-2 — Production Compose supplied working default secrets. docker-compose.yml is the production base, so a missing .env booted with a published admin password and JWT signing key. Fallbacks removed; scripts/deploy.sh now loads .env and refuses to deploy without JWT_SECRET, ADMIN_PASSWORD and AGENT_SECRET_KEY.

High

  • H-1/api/servers/logs and the Docker log stream were readable with a guest token. Now ROLE_ADMIN.
  • H-2 — The authorization chain ended in permitAll(), making any future endpoint outside /api/** public by default. Now denyAll().
  • H-3 — The rate limiter trusted the attacker-supplied leftmost X-Forwarded-For value, so the login limiter (the only brute-force protection on the admin password) was bypassable by randomising a header.

Medium / Low

  • M-1 — Constant-time comparison for the agent shared secret.
  • M-2 — The agent refuses Docker actions targeting caddy-proxy, devops-orchestrator, devops-agent and devops-frontend. A denylist rather than an allowlist, because the dashboard exists to manage arbitrary containers.
  • M-3 — Container and deployment path parameters are validated at the controller boundary.
  • M-5 — Grafana secure cookies forced on in production.
  • M-6 — Prometheus now scrapes the orchestrator and ships target-down and host-resource alert rules. Delivery still needs an Alertmanager, which is not deployed.
  • L-1 — Build-toolchain advisories patched (npm audit fix, no --force).

Validation

apps/agent          cargo test    3 passed
apps/orchestrator   mvn test      20 passed (19 security + 1 context)
apps/frontend       eslint        0 errors, 1 pre-existing warning
apps/frontend       vite build    OK

Notes

  • OrchestratorSecurityTest grew from 6 to 19 tests. Eleven of those had been written and then silently deleted by 85e0f84; they are restored here along with two new path-validation tests.
  • The App.jsx:285 exhaustive-deps warning is pre-existing and untouched.
  • Before the next deploy, confirm /opt/devops-control-center/.env exists on the VM with all three secrets. If production ever ran without it, rotate JWT_SECRET, ADMIN_PASSWORD and AGENT_SECRET_KEY.
  • The Kubernetes architecture drift (H-4) is documented in docs/adr/adr_01_compose-migration-and-cloud-split.md and left as an open decision. No code change here.

Docker container start/stop/restart fell through to the ROLE_GUEST tier
because the security rules were never extended when the Docker dashboard
shipped. Guest tokens are issued to anonymous callers, so any visitor
could stop containers on the host. The only gate was a disabled button
in the UI.

Adds server-side authorization plus regression tests covering every
mutating route.
… routes

Guest tokens could read system and container logs, which expose IPs,
upstream API responses and internal configuration. The authorization
chain also ended in permitAll, making any future endpoint outside
/api/** public by default.
…issing env

docker-compose.yml supplied working defaults for ADMIN_PASSWORD,
JWT_SECRET and AGENT_SECRET_KEY. Since the Compose migration this file
is the production base, so a missing .env booted the platform with
publicly-known credentials and a known JWT signing key.

Removes the fallbacks and adds a deploy.sh preflight assertion.
…e limiter

The login limiter is the only brute-force protection on the admin
password and was bypassable by randomising the header.
Commit 85e0f84 reverted OrchestratorSecurityTest to its baseline while
adding path-parameter validation, silently deleting eleven regression
tests covering C-1, H-1, H-2 and H-3. Without them nothing prevents the
Docker authorization gap from reappearing.

Restores the 17-test version from 02c70c7, adds the two M-3 validation
tests that were never written, and renames the production-shaped test
credentials.
The fallback removal appended duplicate environment entries rather than
editing the originals, leaving the published default secrets in the file
and making the authoritative value ambiguous.
@mattDev0
mattDev0 merged commit 9cc71c9 into main Aug 22, 2026
1 check passed
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