CVE-2026-53472
This stored XSS in migration-planner stems from a validation failure at the storage API layer, not the rendering layer. The `AgentStatusUpdate.CredentialUrl` field accepts URLs without enforcing a scheme allowlist, allowing `javascript:` to be stored directly into the database. When other users view this credential, the renderer treats it as a clickable link and the browser executes the injected script. The core problem is that the field is typed as a plain string rather than a structured URL type. This creates a false assumption that URL scheme validation happens somewhere upstream — but no team actually owns it. The storage API passes the string through, assuming rendering will sanitize; the display code assumes storage already validated. This is a trust-boundary failure hidden by interface compartmentalization. An authenticated attacker can exploit this because the storage operation itself is legitimate. The audit trail shows a valid credential URL being stored — the malicious payload only becomes active when composed with the render operation. Standard security logging that treats storage and display as separate atomic events will miss this causal chain. The attacker has legitimate credentials, so the action doesn't trigger anomaly detection. To remediate, implement scheme validation at the storage API layer using an explicit allowlist (`http`, `https` only). Reject any URL with `javascript:`, `data:`, `vbscript:`, or other executable schemes at the point of entry. This is more effective than relying on output encoding downstream, which should be a secondary defense. Audit your codebase for other string-typed fields that represent structured data types — URL, email, IP address — and evaluate whether they have explicit type invariants or just runtime validation that may have been forgotten.
Reviewed through automated stages and approved by a human before publication.