Skip to content

fix: security headers, DOMPurify sanitization, and localStorage audit#37

Open
teeschima wants to merge 1 commit into
StepFi-app:mainfrom
teeschima:main
Open

fix: security headers, DOMPurify sanitization, and localStorage audit#37
teeschima wants to merge 1 commit into
StepFi-app:mainfrom
teeschima:main

Conversation

@teeschima

Copy link
Copy Markdown

Closes #27

Summary

Implements comprehensive security hardening for the StepFi-Web application across 5 areas.

Changes

1. Security Headers (vercel.json, netlify.toml)

  • Content-Security-Policy: Restrictive policy allowing only self sources, with explicit allowlists for styles (unsafe-inline for Tailwind/Framer Motion), images (data:), API connections (stepfi-api.onrender.com), and fonts. Sets frame-ancestors 'none' and base-uri 'self'.
  • X-Frame-Options: DENY
  • X-Content-Type-Options: nosniff
  • Referrer-Policy: strict-origin-when-cross-origin
  • Permissions-Policy: camera, microphone, geolocation all disabled
  • Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

2. DOMPurify Sanitization (src/lib/sanitize.ts)

  • Created utility with sanitizeText() (strips all HTML) and sanitizeHtml() (safe HTML)
  • Applied to all 5 user-generated content fields:
    • vouch.message in LearnerProfile
    • product.name, product.description in VendorDashboard
    • key.label in VendorDashboard
    • loan.product in VendorDashboard

3. HTTPS Enforcement

  • HSTS header added to both deployment configs
  • Platform-level HTTPS enforcement on Vercel and Netlify

4. localStorage Audit

  • api.ts: Replaced direct localStorage.getItem('accessToken') with reader that parses the zustand-persisted store (stepfi-user), eliminating duplicate storage keys
  • user.store.ts: Removed redundant localStorage.setItem/removeItem calls (zustand persist middleware already handles persistence)
  • Standardized on single storage key via zustand persist

5. Subresource Integrity

  • No external CDN assets exist — all scripts bundled via Vite, so SRI is not applicable

Verification

  • npm run build passes (tsc + vite build)

…orage usage

- Add Content-Security-Policy, HSTS, X-Frame-Options, and other security headers to vercel.json and netlify.toml
- Install DOMPurify and create src/lib/sanitize.ts for user content sanitization
- Sanitize all user-generated content in LearnerProfile.tsx and VendorDashboard.tsx
- Consolidate localStorage token access through zustand persist store in api.ts
- Remove redundant direct localStorage calls from user.store.ts
@EmeditWeb

Copy link
Copy Markdown
Member

@teeschima fix CI issues

The Navbar.tsx fix is already in another open PR.

Before working on your branch, pull the latest main:

git checkout main
git pull origin main
git checkout your-branch-name
git rebase main

Then run:
npm run lint 2>&1 | tail -5

If the error is gone, push:
git push origin your-branch-name --force-with-lease

If the error still shows after rebasing, apply this fix
manually in src/components/layout/Navbar.tsx:

Remove this useEffect:
useEffect(() => {
setMobileOpen(false)
}, [pathname])

Replace with onClick on each mobile nav Link:

setMobileOpen(false)} ... >

Then:
npm run lint 2>&1 | tail -5
npm run build 2>&1 | tail -5

Both must exit 0 before pushing.

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.

core: implement CSP headers and security hardening

2 participants