SOC 2 Controls for React Frontends: What Auditors Look For
Learn which SOC 2 controls apply to React frontends — covering XSS prevention, authentication token handling, CSP headers, third-party script governance, and dependency scanning.
- React auto-escapes JSX expressions, but auditors still check for unsafe HTML rendering patterns — audit your codebase and require DOMPurify for any dynamic HTML.
- Store access tokens in memory (Zustand or React context), not localStorage, to prevent XSS-based token theft.
- Implement a Content Security Policy header via your CDN or server to restrict script sources and prevent injected scripts from executing.
- Run npm audit and Snyk in CI to catch vulnerable frontend dependencies before they reach production.
- Govern third-party scripts with a vendor inventory and CSP hash allowlisting — rogue scripts are a common SOC 2 audit finding.
In this guide
Does SOC 2 apply to the frontend?
SOC 2 auditors scope the entire system that processes or stores customer data — including the frontend. CC6 (logical access) applies to authentication flows, token handling, and session management. CC6.6 covers input validation. CC7 covers monitoring, which includes frontend error tracking.
Frontend-specific audit findings are less common than backend findings, but they do occur. The most frequent: access tokens stored in localStorage (visible to any XSS payload), missing Content Security Policy headers, and third-party analytics scripts loaded without a vendor review.
React's architecture is inherently XSS-resistant because JSX expressions are auto-escaped by the renderer. The main risks are React's unsafe HTML rendering prop (explicit opt-out of escaping), third-party scripts injected into the DOM, and prototype pollution from untrusted JSON.
XSS prevention in React
React auto-escapes JSX expressions, but audit your codebase for usage of the unsafe HTML rendering prop: `grep -r 'dangerousHTML' src/`. Any usage must sanitize the HTML with DOMPurify before rendering — pass the sanitized string to the __html property.
Add ESLint rules to prevent unsafe patterns: eslint-plugin-security and eslint-plugin-no-unsanitized catch the unsafe HTML rendering prop used without sanitization and other dangerous dynamic code execution patterns.
For rendering markdown or rich text from user input, use a sanitizing renderer (rehype-sanitize, DOMPurify) rather than raw HTML injection. Document approved rendering libraries in your secure coding standard.
Secure token storage patterns
Store access tokens in JavaScript memory — Zustand store, React context, or a module-level variable. Memory storage means the token is cleared on page refresh and tab close, and is inaccessible to XSS payloads that can only read DOM and storage APIs.
Use httpOnly, Secure, SameSite=Strict cookies for refresh tokens. The browser sends these cookies automatically with same-origin requests, and JavaScript cannot read them. Implement a silent refresh: on page load, call a /auth/refresh endpoint that reads the httpOnly cookie and returns a new access token into memory.
Never store access tokens in localStorage or sessionStorage. Both are accessible to any JavaScript running on the page. If an XSS payload executes, it can exfiltrate the token. This is a direct CC6.1 finding and one of the most common frontend audit failures.
Content Security Policy headers
A Content Security Policy (CSP) header instructs the browser to only execute scripts from approved sources. A strict React CSP: `Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-{RANDOM}'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; connect-src 'self' https://api.yourapp.com`.
For nonce-based CSP with Next.js, generate a cryptographically random nonce per request in middleware and inject it into the CSP header and into script tags. This allows your bundle to execute while blocking injected scripts that lack the nonce.
Start with `Content-Security-Policy-Report-Only` to collect violations without breaking the app. Use a reporting endpoint (report-uri.com or your own endpoint) to collect violations for 2-4 weeks, then tighten the policy based on real traffic patterns.
Third-party script governance
Maintain a vendor inventory of every third-party script loaded by the frontend: analytics (Google Analytics, Segment), support widgets (Intercom, Drift), error tracking (Sentry), and A/B testing tools. Each vendor must have a completed vendor security questionnaire before the script is added.
Load third-party scripts with the `integrity` attribute (Subresource Integrity) when possible. SRI hashes ensure the browser rejects any script that has been tampered with in transit or at the CDN. Generate hashes with `openssl dgst -sha384 -binary script.js | openssl base64 -A`.
Include third-party script domains in your CSP `script-src` directive. Removing a vendor from the frontend should also trigger removal from the CSP and the vendor inventory. Review the vendor list quarterly as part of CC9 (vendor management).
Frontend dependency scanning
Run `npm audit --audit-level=high` in CI and fail the build on high or critical findings. For more detailed reporting, add Snyk (`snyk test`) with a project token. Both tools check transitive dependencies, not just direct ones.
Frontend dependency trees are large (often 1000+ packages). Prioritise vulnerabilities in packages that handle user input, cryptography, or HTTP requests. A CVE in a pure development dependency (like a test runner) is lower risk than one in a request parsing library.
Pin exact dependency versions with a lockfile (`package-lock.json` or `yarn.lock`) committed to git. Use Dependabot or Renovate for automated patch PRs. Configure Renovate to auto-merge patch updates for non-breaking changes and require review for minor/major bumps.
React SOC 2 checklist
Before your audit window: (1) Grep for unsafe HTML rendering prop usage — any found must use DOMPurify. (2) Access tokens stored in memory only, not localStorage. (3) httpOnly refresh token cookie with SameSite=Strict. (4) CSP header deployed with nonce or hash-based script allowlist. (5) Third-party vendor inventory current and reviewed. (6) npm audit or Snyk passes in CI with zero high/critical findings. (7) Frontend error monitoring (Sentry) configured with PII scrubbing.
Map each item to a Trust Service Criteria code for your evidence package: XSS prevention → CC6.6, token storage → CC6.1, CSP → CC6.6, vendor inventory → CC9.2, dependency scanning → CC7.1, error monitoring → CC7.2.
Frequently Asked Questions
Does SOC 2 require a bug bounty programme for the frontend?
Is localStorage always prohibited for token storage?
Do CSP violations count as security incidents?
How does React Query / SWR affect SOC 2?
Does server-side rendering (Next.js) change the SOC 2 scope?
Automate your compliance today
AuditPath runs 86+ automated checks across AWS, GitHub, Okta, and 14 more integrations. SOC 2 and DPDP Act. Free plan available.
Start for free