Backend Engineer's PR #729 introduces ADMIN_TOKEN — when set, only that value is accepted on /admin/* and /approvals/* routes, replacing the vulnerable workspace-bearer fallback. Without the env var wired into deployments the fix is code-only and the vulnerability stays open in every running instance. Changes: - `docker-compose.yml`: adds ADMIN_TOKEN env var to the platform service (blank default = backward-compat fallback, i.e. still vulnerable until set). NOTE: docker-compose.infra.yml has no platform service — the platform lives only in the full-stack docker-compose.yml, so that is the correct file. - `.env.example`: documents ADMIN_TOKEN with generation instructions and a clear warning that it must be set to close #684. - `infra/scripts/setup.sh`: prints a visible warning when ADMIN_TOKEN is unset so operators know the vulnerability is still open in that deployment. - `CLAUDE.md`: adds ADMIN_TOKEN to the env vars reference section. No Go code changed — go build ./... passes clean. Part of fix for #684 / PR #729 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
00ef832e33
commit
aa38fc55ed
@ -9,6 +9,13 @@ REDIS_URL=redis://redis:6379
|
||||
|
||||
# Platform
|
||||
PORT=8080
|
||||
# ---- Admin credential — REQUIRED to close issue #684 (AdminAuth bearer bypass) ----
|
||||
# When ADMIN_TOKEN is set, only this value is accepted on /admin/* and /approvals/* routes.
|
||||
# Without it, any valid workspace bearer token can call admin endpoints (backward compat
|
||||
# fallback, still vulnerable). Set this in every environment, rotate when compromised.
|
||||
# Generate: openssl rand -base64 32
|
||||
# Store in fly secrets / deployment env — NEVER commit the actual value here.
|
||||
ADMIN_TOKEN=
|
||||
SECRETS_ENCRYPTION_KEY= # 32-byte key (raw or base64). Leave empty for plaintext (dev only).
|
||||
CONFIGS_DIR= # Path to workspace-configs-templates/ (auto-discovered if empty)
|
||||
PLUGINS_DIR= # Path to plugins/ directory (default: /plugins in container)
|
||||
|
||||
@ -143,7 +143,7 @@ go run ./cmd/server # Run server (requires Postgres + Redis running)
|
||||
go build -o molecli ./cmd/cli # Build TUI dashboard
|
||||
./molecli # Run TUI dashboard (requires platform running)
|
||||
```
|
||||
Must run from `platform/` directory (not repo root). Env vars: `DATABASE_URL`, `REDIS_URL`, `PORT`, `PLATFORM_URL` (default `http://host.docker.internal:PORT` — passed to agent containers so they can reach the platform), `SECRETS_ENCRYPTION_KEY` (optional AES-256, 32 bytes), `CONFIGS_DIR` (auto-discovered), `PLUGINS_DIR` (deprecated — plugins are now installed per-workspace via API; the `plugins/` registry at repo root is auto-discovered), `ACTIVITY_RETENTION_DAYS` (default `7`), `ACTIVITY_CLEANUP_INTERVAL_HOURS` (default `6`), `CORS_ORIGINS` (comma-separated, default `http://localhost:3000,http://localhost:3001`), `RATE_LIMIT` (requests/min, default `600`), `WORKSPACE_DIR` (optional — global fallback host path for `/workspace` bind-mount; overridden by per-workspace `workspace_dir` column in DB; if neither is set, each workspace gets an isolated Docker named volume), `AWARENESS_URL` (optional — if set, injected into workspace containers along with a deterministic `AWARENESS_NAMESPACE` derived from workspace ID), `MOLECULE_IN_DOCKER` (optional — set to `1` when the platform itself runs inside Docker so the A2A proxy rewrites `127.0.0.1:<port>` URLs to container hostnames; auto-detected via `/.dockerenv`), `MOLECULE_ENV` (optional — set to `production` to hide the `/admin/workspaces/:id/test-token` E2E helper endpoint; unset or any other value leaves it enabled), `MOLECULE_ENABLE_TEST_TOKENS` (optional — set to `1` to force-enable the test-token endpoint even when `MOLECULE_ENV=production`; intended for staging runs only), `MOLECULE_ORG_ID` (optional — the public repo's only SaaS hook. When set to a UUID, every non-allowlisted request must carry a matching `X-Molecule-Org-Id` header or gets a 404; when unset, the guard is a passthrough so self-hosted / dev / CI are unaffected. Set only by the private `molecule-controlplane` provisioner on Fly Machines tenant instances — never by self-hosters).
|
||||
Must run from `platform/` directory (not repo root). Env vars: `DATABASE_URL`, `REDIS_URL`, `PORT`, `ADMIN_TOKEN` (**required to close issue #684** — when set, only this exact value is accepted on all `/admin/*` and `/approvals/*` routes; without it, any valid workspace bearer token passes AdminAuth, which is the #684 vulnerability. Generate: `openssl rand -base64 32`. Never commit the actual value — inject via `fly secrets set` or deployment env. PR #729), `PLATFORM_URL` (default `http://host.docker.internal:PORT` — passed to agent containers so they can reach the platform), `SECRETS_ENCRYPTION_KEY` (optional AES-256, 32 bytes), `CONFIGS_DIR` (auto-discovered), `PLUGINS_DIR` (deprecated — plugins are now installed per-workspace via API; the `plugins/` registry at repo root is auto-discovered), `ACTIVITY_RETENTION_DAYS` (default `7`), `ACTIVITY_CLEANUP_INTERVAL_HOURS` (default `6`), `CORS_ORIGINS` (comma-separated, default `http://localhost:3000,http://localhost:3001`), `RATE_LIMIT` (requests/min, default `600`), `WORKSPACE_DIR` (optional — global fallback host path for `/workspace` bind-mount; overridden by per-workspace `workspace_dir` column in DB; if neither is set, each workspace gets an isolated Docker named volume), `AWARENESS_URL` (optional — if set, injected into workspace containers along with a deterministic `AWARENESS_NAMESPACE` derived from workspace ID), `MOLECULE_IN_DOCKER` (optional — set to `1` when the platform itself runs inside Docker so the A2A proxy rewrites `127.0.0.1:<port>` URLs to container hostnames; auto-detected via `/.dockerenv`), `MOLECULE_ENV` (optional — set to `production` to hide the `/admin/workspaces/:id/test-token` E2E helper endpoint; unset or any other value leaves it enabled), `MOLECULE_ENABLE_TEST_TOKENS` (optional — set to `1` to force-enable the test-token endpoint even when `MOLECULE_ENV=production`; intended for staging runs only), `MOLECULE_ORG_ID` (optional — the public repo's only SaaS hook. When set to a UUID, every non-allowlisted request must carry a matching `X-Molecule-Org-Id` header or gets a 404; when unset, the guard is a passthrough so self-hosted / dev / CI are unaffected. Set only by the private `molecule-controlplane` provisioner on Fly Machines tenant instances — never by self-hosters).
|
||||
|
||||
**Workspace tier resource limits** (issue #14 — override the per-tier memory/CPU caps in `provisioner.ApplyTierConfig`; CPU_SHARES follows Docker's 1024 = 1 CPU convention, translated to NanoCPUs for a hard cap):
|
||||
- `TIER2_MEMORY_MB` / `TIER2_CPU_SHARES` — Standard tier (defaults `512` / `1024`)
|
||||
|
||||
@ -136,6 +136,14 @@ services:
|
||||
GITHUB_APP_ID: "${GITHUB_APP_ID:-}"
|
||||
GITHUB_APP_INSTALLATION_ID: "${GITHUB_APP_INSTALLATION_ID:-}"
|
||||
GITHUB_APP_PRIVATE_KEY_FILE: "/secrets/github-app.pem"
|
||||
# ADMIN_TOKEN — required to fully close issue #684 (AdminAuth bearer bypass, PR #729).
|
||||
# When set, only this exact value is accepted on all /admin/* and /approvals/* routes;
|
||||
# workspace bearer tokens are no longer accepted as admin credentials.
|
||||
# Unset (default) → backward-compat fallback: any valid workspace token passes AdminAuth
|
||||
# (same behaviour as before PR #729, still vulnerable to #684).
|
||||
# Generate: openssl rand -base64 32
|
||||
# Store in fly secrets / deployment env — NEVER commit the actual value.
|
||||
ADMIN_TOKEN: "${ADMIN_TOKEN:-}"
|
||||
volumes:
|
||||
- ./workspace-configs-templates:/configs
|
||||
- ./org-templates:/org-templates:ro
|
||||
|
||||
@ -43,3 +43,14 @@ echo "==> Infrastructure ready!"
|
||||
echo " Postgres: localhost:5432"
|
||||
echo " Redis: localhost:6379"
|
||||
echo " Langfuse: localhost:3001"
|
||||
|
||||
# Security check — issue #684 (AdminAuth bearer bypass, PR #729).
|
||||
# Without ADMIN_TOKEN, any valid workspace bearer token can call /admin/* routes.
|
||||
if [ -z "${ADMIN_TOKEN:-}" ]; then
|
||||
echo ""
|
||||
echo " ⚠ WARNING: ADMIN_TOKEN is not set."
|
||||
echo " Until it is, AdminAuth falls back to accepting any workspace bearer token"
|
||||
echo " — the #684 vulnerability is NOT closed in this deployment."
|
||||
echo " Generate one: openssl rand -base64 32"
|
||||
echo " Then export ADMIN_TOKEN=<value> or add it to your .env before starting the platform."
|
||||
fi
|
||||
|
||||
Loading…
Reference in New Issue
Block a user