Skip to content

Add CORS recommendation for browser-based clients (section 2)#14

Open
mwiesen wants to merge 1 commit into
masterfrom
cors-recommendation
Open

Add CORS recommendation for browser-based clients (section 2)#14
mwiesen wants to merge 1 commit into
masterfrom
cors-recommendation

Conversation

@mwiesen

@mwiesen mwiesen commented Apr 6, 2026

Copy link
Copy Markdown
Member

Closes #12

Summary

Adds a SHOULD-level recommendation for SPXP servers to include the Access-Control-Allow-Origin: * HTTP response header on all endpoints.

Motivation

Browser-based SPXP clients (e.g. web viewers, web UIs) cannot access SPXP endpoints cross-origin without CORS headers. Currently, such clients must route all requests through a server-side proxy — a significant barrier that contradicts the protocol's design goal of direct client-server communication.

Adding this as a SHOULD (not MUST) keeps existing server implementations valid while signalling best practice for new implementations and hosting providers.

Changes

  • SPXP-Spec.md, section 2 (Communication protocols): Added one sentence recommending Access-Control-Allow-Origin: * on all SPXP endpoints.

SPXP servers SHOULD send Access-Control-Allow-Origin: * to allow
browser-based clients to access SPXP endpoints without a server-side
proxy.

Closes #12
@mwiesen

mwiesen commented Apr 8, 2026

Copy link
Copy Markdown
Member Author

Security Analysis: CORS and Authentication

Since there have been questions about whether enabling CORS could open up security vulnerabilities, here's a structured analysis of the relevant scenarios.

Preliminary: CORS vs. CSRF

The concern that a malicious website could use existing browser credentials to perform actions on behalf of a user is a classic CSRF (Cross-Site Request Forgery) attack — not a direct consequence of CORS. The two are related but distinct:

  • CORS controls whether a browser allows a script to read the response of a cross-origin request
  • CSRF is the question of whether a server accepts requests triggered from a foreign origin

A critical detail: Access-Control-Allow-Origin: * (as proposed in this PR) and Access-Control-Allow-Credentials: true are mutually exclusive by the browser spec — browsers refuse this combination. This means that with ACAO: *, browsers will never attach cookies or session credentials to cross-origin requests.


Block 1: Read access — public endpoints

# Scenario With CORS * Without CORS Risk
1.1 Malicious page reads public profile via XHR ✅ allowed ❌ browser blocks Low — content is public anyway
1.2 Malicious page reads posts feed via XHR ✅ allowed ❌ browser blocks Low — public content
1.3 Direct access via curl / server-to-server ✅ always possible ✅ always possible CORS provides no protection here

Takeaway: CORS never protects against server-to-server access. Anyone who wants to scrape public data doesn't need CORS.


Block 2: Read access — authenticated / private content

# Scenario Attack path Protection
2.1 Malicious page reads private posts, auth via cookie/session Page makes XHR with credentials: 'include' With ACAO: *, browser refuses to attach cookies — attack fails
2.2 Auth via Authorization header (bearer token) Malicious page would need to know the token — it doesn't Not a CORS issue; token theft would require XSS
2.3 Auth via SPXP signed request (cryptographic signature) Malicious page cannot sign without the private key Immune to CSRF regardless of CORS

Block 3: Write access — management endpoints

# Scenario Analysis
3.1 Malicious page posts on behalf of user, auth via cookie With ACAO: * → browser does not attach cookies cross-origin → fails
3.2 Malicious page posts, auth via signed request No access to private key in browser → fails
3.3 Malicious page posts, token stored in LocalStorage Token could be stolen via XSS — but that is an XSS problem, not a CORS problem
3.4 ACAO: * combined with ACAC: true Browser rejects this combination per spec → not possible

Block 4: Preflight and header control

# Test Expected behavior
4.1 OPTIONS preflight on management endpoints Server should only allow GET/POST, no dangerous methods
4.2 Access-Control-Allow-Headers Only permit headers actually needed by SPXP
4.3 Access-Control-Allow-Methods Do not use * — enumerate only what SPXP requires
4.4 Credentials header Ensure Access-Control-Allow-Credentials: true is never set

Block 5: Edge cases

# Scenario Assessment
5.1 Server reflects the Origin header instead of * Dangerous — circumvents the */credentials incompatibility; avoid this pattern
5.2 Reverse proxy and server both set CORS headers Can lead to unexpected combinations; only one layer should set them
5.3 Browser extensions with elevated privileges CORS does not apply to extensions — separate threat model
5.4 WebSocket connections CORS does not apply to WebSockets — separate topic

Conclusion

Access-Control-Allow-Origin: * is precisely the safe variant for public APIs. It enables browser-based clients from any origin to read public SPXP data, but the browser spec explicitly prevents credentials from being attached to such requests. The attack scenario where a malicious tab leverages an authenticated session only applies if the server sets Access-Control-Allow-Credentials: true — which this PR does not propose and which should be explicitly avoided by implementations.

Furthermore, if management requests are cryptographically signed (as in SPXP), the entire threat model is inherently immune to CSRF: without the private key, no attacker can produce a valid signed request regardless of CORS configuration.

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.

Spec suggestion: Add CORS recommendation for SPXP servers

1 participant