Skip to content

fix(commerce): harden demo server for public deployment#189

Merged
mohamedmansour merged 9 commits intomainfrom
chore/demo-secure
Apr 8, 2026
Merged

fix(commerce): harden demo server for public deployment#189
mohamedmansour merged 9 commits intomainfrom
chore/demo-secure

Conversation

@mohamedmansour
Copy link
Copy Markdown
Contributor

Security audit identified 7 findings; all are now resolved to make the demo site safer:

  1. Security headers — Add DefaultHeaders middleware with CSP, X-Content-Type-Options, X-Frame-Options, Referrer-Policy, and Permissions-Policy on every response (security.rs).

  2. Cache-Control / Vary — Set 'Cache-Control: private, no-store' and 'Vary: Accept, Cookie' on all dynamic HTML and JSON responses to prevent CDN/proxy cache poisoning of personalized content.

  3. CSRF protection — Validate Origin (or Referer) header on /cart/add and /cart/update POST endpoints. Rejects cross-origin requests with 403 while allowing same-origin form submissions and test harnesses that omit both headers (OWASP double-submit approach).

  4. Rate limiting — Add in-memory IP-based fixed-window rate limiter (60 req/IP/min) stored in AppState. Applied to cart mutation endpoints. Returns 429 when exceeded. Fails open on missing peer IP. Expired entries pruned opportunistically.

  5. Open redirect hardening — Reject backslashes, control characters (< 0x20), and DEL (0x7f) in sanitize_redirect() to close browser-dependent redirect edge cases.

  6. HMAC cookie signing — Sign cart cookie with HMAC-SHA256 (hmac + sha2 crates). Cookie format is now '<hex_payload>.<hex_sig>'. Unsigned or tampered cookies are rejected and cart is reset.

  7. Static asset cache headers — Add 'Cache-Control: public, max-age=86400' to CSS and asset responses in serve_asset().

Security audit identified 7 findings; all are now resolved:

1. Security headers — Add DefaultHeaders middleware with CSP,
   X-Content-Type-Options, X-Frame-Options, Referrer-Policy, and
   Permissions-Policy on every response (security.rs).

2. Cache-Control / Vary — Set 'Cache-Control: private, no-store' and
   'Vary: Accept, Cookie' on all dynamic HTML and JSON responses to
   prevent CDN/proxy cache poisoning of personalized content.

3. CSRF protection — Validate Origin (or Referer) header on /cart/add
   and /cart/update POST endpoints. Rejects cross-origin requests with
   403 while allowing same-origin form submissions and test harnesses
   that omit both headers (OWASP double-submit approach).

4. Rate limiting — Add in-memory IP-based fixed-window rate limiter
   (60 req/IP/min) stored in AppState. Applied to cart mutation
   endpoints. Returns 429 when exceeded. Fails open on missing peer
   IP. Expired entries pruned opportunistically.

5. Open redirect hardening — Reject backslashes, control characters
   (< 0x20), and DEL (0x7f) in sanitize_redirect() to close
   browser-dependent redirect edge cases.

6. HMAC cookie signing — Sign cart cookie with HMAC-SHA256 (hmac +
   sha2 crates). Cookie format is now '<hex_payload>.<hex_sig>'.
   Unsigned or tampered cookies are rejected and cart is reset.

7. Static asset cache headers — Add 'Cache-Control: public,
   max-age=86400' to CSS and asset responses in serve_asset().

New files: security.rs, rate_limit.rs, EXPLOIT.md (audit report).
New deps: hmac 0.12, sha2 0.10 (MIT, passes cargo deny).
All 40 tests pass (11 new tests across the security modules).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@mohamedmansour mohamedmansour requested a review from Copilot April 8, 2026 19:02
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Hardens the commerce demo server for safer public deployment by adding standard security headers, preventing caching of personalized responses, adding CSRF checks and rate limiting on cart mutations, and signing cart cookies to prevent tampering.

Changes:

  • Add security middleware (CSP + related headers), CSRF origin/referer validation, and IP-based rate limiting for cart mutation endpoints.
  • Add cache headers for dynamic responses and static assets; tighten redirect sanitization.
  • Sign cart cookies with HMAC-SHA256 and add an audit writeup documenting findings/resolutions.

Reviewed changes

Copilot reviewed 11 out of 12 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
examples/app/commerce/server/src/server.rs Adds CSRF + rate-limit checks to cart mutations; adds Cache-Control/Vary to dynamic JSON/HTML responses.
examples/app/commerce/server/src/security.rs Introduces security headers middleware and CSRF validation helpers + tests.
examples/app/commerce/server/src/rate_limit.rs Adds in-memory fixed-window IP rate limiter + tests.
examples/app/commerce/server/src/main.rs Wires security headers middleware and new modules into the server.
examples/app/commerce/server/src/frontend.rs Adds Cache-Control for CSS and other static asset responses.
examples/app/commerce/server/src/error.rs Adds CsrfRejected (403) and RateLimited (429) error variants.
examples/app/commerce/server/src/cart.rs Adds redirect hardening and HMAC-signed cart cookie format + tests.
examples/app/commerce/server/src/app.rs Stores RateLimiter in AppState and exposes accessor.
examples/app/commerce/server/Cargo.toml Adds hmac/sha2 deps (workspace) for cookie signing.
examples/app/commerce/EXPLOIT.md Adds security audit report describing the findings and fixes.
Cargo.toml Adds a new workspace member and workspace deps for hmac/sha2.

Comment thread examples/app/commerce/server/src/cart.rs Outdated
Comment thread examples/app/commerce/server/src/cart.rs Outdated
Comment thread examples/app/commerce/server/src/security.rs Outdated
Comment thread examples/app/commerce/server/src/server.rs Outdated
Comment thread examples/app/commerce/server/src/server.rs Outdated
Comment thread Cargo.toml Outdated
Comment thread examples/benchmarks/mail-react/server.mjs Fixed
Comment thread examples/benchmarks/mail-rsc/src/MailApp.tsx Fixed
Comment thread examples/benchmarks/todo-react/server.mjs Fixed
Comment thread examples/benchmarks/mail-astro/src/components/MailApp.tsx Fixed
Comment thread examples/benchmarks/mail-astro/src/components/MailApp.tsx Fixed
Comment thread examples/benchmarks/mail-react/src/App.tsx Fixed
Comment thread examples/benchmarks/mail-rsc/src/MailApp.tsx Fixed
Comment thread examples/benchmarks/tests/mail-benchmark.spec.ts Fixed
Comment thread examples/benchmarks/tests/mail-benchmark.spec.ts Fixed
Comment thread examples/benchmarks/todo-webui/tests/todo-webui.spec.ts Fixed
Comment thread examples/benchmarks/todo-webui/tests/todo-webui.spec.ts Fixed
- Use constant-time HMAC verification via verify_slice instead of
  string equality for cookie signature checks
- Fix CSRF to fail closed when Origin/Referer is present but Host
  header is missing, preventing validation bypass
- Apply Cache-Control and Vary headers to both JSON and redirect
  response branches in cart mutations
- Remove non-existent examples/benchmarks/teams/server workspace member
- Add regression tests for CSRF Host-missing scenarios

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
mohamedmansour and others added 2 commits April 8, 2026 12:32
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
janechu
janechu previously approved these changes Apr 8, 2026
1. Constant-time HMAC verification — Replace string equality with
   hmac::verify_slice for timing-safe signature validation.

2. Runtime cookie secret — Move HMAC key from hardcoded constant to
   CART_COOKIE_SECRET env var via OnceLock. Falls back to ephemeral
   per-process key when unset. Dockerfile sets a default placeholder.

3. CSP nonce support — Replace 'unsafe-inline' for script-src with
   per-request nonces using the framework's existing RenderOptions
   .with_nonce() API. CSP header is now set per-response with the
   matching nonce value.

4. Cache headers on all cart responses — Move Cache-Control/Vary
   headers outside the JSON-only branch so redirect responses are
   also marked private/no-store.

5. Proxy-aware rate limiting — Add client_ip() helper that reads
   X-Forwarded-For before falling back to peer_addr(), so rate
   limiting works correctly behind Docker/CDN reverse proxies.

6. CSRF fail-closed — Reject requests when Origin or Referer is
   present but Host is missing (validation impossible). Only allow
   when all three headers are absent.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment thread examples/app/commerce/server/src/security.rs Dismissed
@mohamedmansour mohamedmansour merged commit 5666109 into main Apr 8, 2026
21 checks passed
@mohamedmansour mohamedmansour deleted the chore/demo-secure branch April 8, 2026 22:19
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.

4 participants