fix: add slug validation to prevent SSRF (OFFSEC-006) #930
Merged
devops-engineer
merged 1 commits from 2026-05-14 02:22:15 +00:00
fix/offsec-006-slug-validation into main
1 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
9153a2e464 |
fix: add slug validation to prevent SSRF (OFFSEC-006)
sop-checklist / all-items-acked (pull_request) injected
Block internal-flavored paths / Block forbidden paths (pull_request) Successful in 17s
E2E Staging Canvas (Playwright) / detect-changes (pull_request) Successful in 55s
Runtime PR-Built Compatibility / detect-changes (pull_request) Successful in 39s
CI / Detect changes (pull_request) Successful in 58s
E2E API Smoke Test / detect-changes (pull_request) Successful in 56s
Handlers Postgres Integration / detect-changes (pull_request) Successful in 49s
Secret scan / Scan diff for credential-shaped strings (pull_request) Successful in 28s
qa-review / approved (pull_request) Successful in 13s
gate-check-v3 / gate-check (pull_request) Successful in 33s
sop-checklist-gate / gate (pull_request) Successful in 13s
security-review / approved (pull_request) Successful in 15s
sop-tier-check / tier-check (pull_request) Successful in 20s
lint-required-no-paths / lint-required-no-paths (pull_request) Successful in 1m17s
audit-force-merge / audit (pull_request) Successful in 10s
Ops Scripts Tests / Ops scripts (unittest) (pull_request) Successful in 1m42s
CI / Platform (Go) (pull_request) Successful in 7s
Runtime PR-Built Compatibility / PR-built wheel + import smoke (pull_request) Successful in 6s
CI / Canvas (Next.js) (pull_request) Successful in 7s
CI / Python Lint & Test (pull_request) Successful in 6s
E2E Staging Canvas (Playwright) / Canvas tabs E2E (pull_request) Successful in 8s
E2E API Smoke Test / E2E API Smoke Test (pull_request) Successful in 8s
Handlers Postgres Integration / Handlers Postgres Integration (pull_request) Successful in 7s
CI / Shellcheck (E2E scripts) (pull_request) Successful in 22s
CI / Canvas Deploy Reminder (pull_request) Successful in 8s
CI / all-required (pull_request) Successful in 3s
OFFSEC-006 (HIGH): promote-tenant-image.sh interpolated raw --tenants slug into URL paths and subdomains without sanitisation. Four injection points were vulnerable: • cp_redeploy_tenant (line 193): /cp/admin/tenants/$slug/redeploy • tenant_buildinfo (line 209): https://${slug}.moleculesai.app/buildinfo • tenant_health (line 217): https://${slug}.moleculesai.app/health • resolve_tenant_instance_id (line 263): /cp/admin/tenants/$slug Attack vectors: --tenants 'a?url=https://evil.com' → curl splits on ? as query separator --tenants 'evil.com@legitimate' → subdomain takeover via @ Fix: • Add validate_slug() function with regex ^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$ before any URL interpolation. Exit 64 on invalid slug. • Call validate_slug() in main() before any operations (up-front guard). • Add defense-in-depth calls inside cp_redeploy_tenant, tenant_buildinfo, tenant_health, resolve_tenant_instance_id, redeploy_tenant, verify_tenant, and the rollback loop. • Also fix a latent promote_rc=1 bug where `cmd || promote_rc=1` inside `set -e` returned exit 1 and triggered early script exit instead of setting the variable. Replaced with `if ! cmd; then promote_rc=1; fi`. Test additions (test-promote-tenant-image.sh): • Test 9: 8 invalid slug variants rejected with exit 64 (?, &, @, /, \, space, etc.) • Test 10: 6 valid slugs accepted (chloe-dong, ab, a, etc.) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |