Skip to content

agent-kanban: validate artifact media Content-Type before forwarding#11

Open
rushitgit wants to merge 1 commit into
cursor:mainfrom
rushitgit:validate-artifact-content-type
Open

agent-kanban: validate artifact media Content-Type before forwarding#11
rushitgit wants to merge 1 commit into
cursor:mainfrom
rushitgit:validate-artifact-content-type

Conversation

@rushitgit

Copy link
Copy Markdown

The artifact media proxy in sdk/agent-kanban just pipes whatever Content-Type the upstream CDN sends straight to the browser. Normally fine, but ArtifactTile wraps every preview in <a href={mediaUrl} target="_blank"> — so if a CDN serves an artifact with Content-Type: image/svg+xml, clicking the thumbnail opens it as a top-level SVG document on the app's own origin, where <script> tags run freely.

SVG-as-image (inside <img>) is sandboxed. SVG-as-document is not. That distinction is what makes this worth closing.

What the fix does:

Adds a small allowlist of image/video MIME types that are actually safe to reflect. Anything not on the list falls back to contentTypeForArtifactPath() extension sniffing — and image/svg+xml is intentionally left out of both so SVGs land as application/octet-stream instead of executing. Both the URL-fetch path and the Blob path in readArtifactContent go through the same sanitizer.

No behaviour change for normal PNG/JPEG/GIF/WebP/AVIF/MP4/WebM artifacts.

The artifact media proxy mirrored the upstream CDN's Content-Type into
the response. Opening an SVG artifact via the existing thumbnail link
(<a target="_blank"> in ArtifactTile) renders it as a top-level document
in the app origin and executes embedded scripts.

Allowlist the MIME types the proxy can claim, fall back to the path-based
guess otherwise, and drop image/svg+xml from that fallback so SVG
artifacts are served as application/octet-stream.
@rushitgit

Copy link
Copy Markdown
Author

@cursor

@rushitgit

Copy link
Copy Markdown
Author

Bumping this after two months with no response.

The vulnerability is still present on current HEAD (checked 2026-06-25):

  • contentTypeForArtifactPath (server.ts line 966) returns image/svg+xml for .svg artifacts
  • The media proxy at /api/agents/[agentId]/artifacts/media reflects this directly in Content-Type
  • ArtifactTile wraps preview thumbnails in <a target="_blank"> pointing at that proxy URL
  • Clicking a .svg artifact renders it as a top-level document on the app's own origin, where <script> executes freely

An agent (or a compromised artifact CDN) can plant an SVG with <script>alert(document.cookie)</script>. One click by the user runs JS in the agent-kanban origin.

The fix in this PR is two lines: remove image/svg+xml from contentTypeForArtifactPath and add a MIME allowlist for the URL-fetch path. No behavior change for PNG/JPEG/GIF/WebP/MP4/WebM.

If you'd prefer a private report channel, I can refile this as a GitHub private vulnerability report. Otherwise I'll treat the 90-day window as starting from the original submission date (2026-04-29) and plan to disclose publicly around 2026-07-28.

cc @cursor

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