Skip to content

fix(web): extend S3 endpoint policy and frame headers to remaining routes - #3037

Merged
richiemcilroy merged 2 commits into
mainfrom
fix/web-ssrf-and-framing-followup
Oct 24, 2026
Merged

richiemcilroy merged 2 commits into
mainfrom
fix/web-ssrf-and-framing-followup

Conversation

@richiemcilroy

@richiemcilroy richiemcilroy commented Oct 24, 2026 •

Copy link
Copy Markdown
Member

Follow-up to #1932 and #2997.

S3 endpoint policy

#1932 added apps/web/lib/s3-endpoint-policy.ts and applied it to the desktop S3 config save and /test routes. The same server-side request path existed in two more places, so this applies the same policy there:

  • apps/web/actions/organization/storage.ts: saveOrganizationS3Config and testOrganizationS3Config
  • apps/web/app/api/v1/[...route]/route.ts: PUT /organizations/:id/storage/s3 and POST /organizations/:id/storage/s3/test (both go through resolveAgentS3Config and testAgentS3Config)

Behaviour matches #1932:

  • Only enforced when NEXT_PUBLIC_IS_CAP=true and NODE_ENV=production. Self-hosted and dev keep localhost and LAN MinIO.
  • An empty endpoint (AWS default) is allowed.
  • Endpoints that are private IPs, localhost, *.localhost, *.internal, contain credentials, use a non-http(s) scheme, or resolve to any private address are rejected with the same message as the desktop route, before any S3 request is made.
  • Connection tests on Cap Cloud use the publicOnlyLookup agents, so a hostname that changes its DNS answer between the check and the connection is still refused.

To avoid a third copy of the gate, isDisallowedS3Endpoint, publicOnlyS3Agents and blockedS3EndpointMessage now live in the policy module, and the desktop route uses them too. The desktop route's behaviour is unchanged. publicOnlyS3Agents() returns undefined outside Cap Cloud, so self-hosted S3 clients keep the SDK default request handler exactly as before.

Frame headers

/admin, /signup and /verify-otp are added to FRAME_PROTECTED_PATHS in apps/web/proxy.ts, so they get X-Frame-Options: SAMEORIGIN and frame-ancestors https://cap.so like /dashboard and /login. /embed, /s and /c are unchanged and stay frameable.

Tests

  • __tests__/unit/organization-storage-s3-endpoint.test.ts (new): save and test server actions reject private endpoints on Cap Cloud without writing or connecting, accept public and empty endpoints, use public-only agents for the test connection, and allow local endpoints on self-hosted and dev.
  • __tests__/unit/agent-s3-endpoint-policy.test.ts (new): drives the real v1 handler for PUT and POST /storage/s3, checks a 400 INVALID_REQUEST with no S3 client created for private endpoints (including a padded [::1] endpoint), public-only agents for public endpoints, and no change on self-hosted.
  • __tests__/unit/s3-endpoint-policy.test.ts: covers the new helpers.
  • __tests__/unit/proxy-frame-headers.test.ts: adds /admin, /admin/*, /signup and /verify-otp to the protected list, and /administrator, /signups and /verify-otp-help to the unprotected list to check prefix matching.

The new storage and v1 tests fail on main and pass on this branch.

RetriggerView in GreptileConfidence Score: 5/5

The PR appears safe to merge; no actionable new issues were found.

Summary

Extends the existing S3 endpoint policy to organization storage actions and the v1 API.

  • Organization S3 settings and agent requests now block private endpoints.
  • Admin and account setup pages now block outside framing.

No actionable new issues were found. Tests were reviewed but not run.

Reviews (2) · Last reviewed commit: "fix(web): set frame headers on admin, si..." · Reviewed by Greptile

@capy-ai capy-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Capy found no issues.

Open in Capy

@richiemcilroy

Copy link
Copy Markdown
Member Author

@greptileai review

@richiemcilroy
richiemcilroy merged commit 81942f8 into main Oct 24, 2026
39 checks passed

This branch was successfully deployed

1 active and 1 inactive deployments
Preview – cap-web — 4c4e9d54 Deployed Oct 24, 2026 by vercel[bot]
Preview – cap-status — 4c4e9d54 Deployed Oct 24, 2026 by vercel[bot]
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