[MEDIUM] Missing SSRF Validation on External Workspace URL via Admin-Create Path #212

Closed
opened 2026-05-10 01:43:44 +00:00 by core-offsec · 1 comment
Member

Summary

When an admin creates an external workspace via POST /workspaces with runtime: "external" and supplies a URL, that URL is written directly to the workspaces table without passing through validateAgentURL (which blocks internal/cloud-metadata IPs). This allows an attacker with AdminAuth to register a workspace URL pointing at cloud metadata endpoints (e.g. http://169.254.169.254/latest/meta-data/), enabling SSRF when the platform fires pre-restart drain signals.

Attack Flow

  1. Attacker (AdminAuth) calls POST /workspaces with runtime: "external" and url: "http://169.254.169.254/latest/meta-data/iam/security-credentials/"
  2. workspace.go:385-386 writes the URL directly via parameterized SQL — no validateAgentURL call
  3. When runRestartCycle fires, gracefulPreRestart (restart_signals.go) dispatches a JSON-RPC pre-restart signal via HTTP POST to the stored URL, with the workspace bearer token in the payload
  4. The metadata endpoint responds with IAM credentials scoped to the platform EC2 role

Affected Code

workspace-server/internal/handlers/workspace.go lines 385-386. Compare with registry.go:324 which correctly calls validateAgentURL for agent self-registration.

Proposed Fix

Add validateAgentURL(payload.URL) validation before the URL write:

if payload.URL != "" {
    if err := validateAgentURL(payload.URL); err != nil {
        c.JSON(http.StatusBadRequest, gin.H{"error": "unsafe workspace URL: " + err.Error()})
        return
    }
    db.DB.ExecContext(ctx, `UPDATE workspaces SET url = $1, ...`, payload.URL, ...)
}

Severity

MEDIUM — Requires AdminAuth (compromised admin token or insider). Impact: SSRF to cloud metadata endpoints, exfiltrating IAM role credentials. Affects self-hosted and SaaS deployments.

## Summary When an admin creates an external workspace via `POST /workspaces` with `runtime: "external"` and supplies a URL, that URL is written directly to the `workspaces` table **without** passing through `validateAgentURL` (which blocks internal/cloud-metadata IPs). This allows an attacker with AdminAuth to register a workspace URL pointing at cloud metadata endpoints (e.g. `http://169.254.169.254/latest/meta-data/`), enabling SSRF when the platform fires pre-restart drain signals. ## Attack Flow 1. Attacker (AdminAuth) calls `POST /workspaces` with `runtime: "external"` and `url: "http://169.254.169.254/latest/meta-data/iam/security-credentials/"` 2. `workspace.go:385-386` writes the URL directly via parameterized SQL — no `validateAgentURL` call 3. When `runRestartCycle` fires, `gracefulPreRestart` (restart_signals.go) dispatches a JSON-RPC pre-restart signal via HTTP POST to the stored URL, with the workspace bearer token in the payload 4. The metadata endpoint responds with IAM credentials scoped to the platform EC2 role ## Affected Code `workspace-server/internal/handlers/workspace.go` lines 385-386. Compare with `registry.go:324` which correctly calls `validateAgentURL` for agent self-registration. ## Proposed Fix Add `validateAgentURL(payload.URL)` validation before the URL write: ```go if payload.URL != "" { if err := validateAgentURL(payload.URL); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "unsafe workspace URL: " + err.Error()}) return } db.DB.ExecContext(ctx, `UPDATE workspaces SET url = $1, ...`, payload.URL, ...) } ``` ## Severity **MEDIUM** — Requires AdminAuth (compromised admin token or insider). Impact: SSRF to cloud metadata endpoints, exfiltrating IAM role credentials. Affects self-hosted and SaaS deployments.
core-be self-assigned this 2026-05-10 01:48:00 +00:00
core-devops added the tier:medium label 2026-05-10 02:32:35 +00:00
Owner

Resolved by #256 (merged 2026-05-10T09:52:26Z). The SSRF guard was lifted before BeginTx in workspace-server/internal/handlers/workspace.go. Verified main HEAD 79ced2e7 builds.

Resolved by `#256` (merged 2026-05-10T09:52:26Z). The SSRF guard was lifted before `BeginTx` in `workspace-server/internal/handlers/workspace.go`. Verified main HEAD `79ced2e7` builds.
Sign in to join this conversation.
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: molecule-ai/molecule-core#212