React Security Best Practices for AI-Built Apps: Fixing Common Vibe-Coding Vulnerabilities

Quick answer: Keep secret credentials out of browser-delivered code, enforce backend permissions, and handle untrusted output safely. React escapes ordinary text rendering, but raw HTML and other unsafe sinks need separate review. Use database controls appropriate to the backend and test the deployed behavior.

By Gabriel CA · Kraftwire Software

· 7 min read

Review a React app's source, dependencies, and deployed configuration independently of whether its visible features work. Keep secret credentials server-side, and test the permissions and data returned by backend operations.

These live figures describe all scanned sites. They do not establish prevalence for an AI-built subgroup, compare development methods, or attribute findings to AI generation.

28% of the 103 live sites SimplyScan has scanned (29 sites) have at least one high or critical security issue.

Which Boundaries Should You Review In Generated React Code?

Check where components execute, which values reach the browser, and how user input reaches backend operations. A working component does not establish that its data access or output handling is safe.

If a browser-executed React component makes a fetch() request with a secret key, the browser user can inspect that credential. A referenced client-facing variable such as VITE_STRIPE_SECRET can be included in the build. Environment-variable syntax does not make a value private, and server-rendered code must be distinguished from code sent to the browser.

The Client-Side Fetching Trap

10% of the 103 live sites SimplyScan has scanned (10 sites) have at least one medium-severity architecture issue, such as a library with a known vulnerability or no rate limiting.

Test the relevant configuration and access paths in your application; the aggregate corpus does not measure the prevalence of this specific cause. Enforce authorization on the server or database regardless of the client component that initiates a request, including a request started in useEffect.

How Do I Secure API Keys In A React Frontend?

Keep long-lived secret provider credentials on the server. Some services also issue public client identifiers or support scoped, short-lived browser credentials; follow the provider's documented flow rather than treating every API key as equivalent.

Using Next.js Server Components

A Next.js App Router Server Component can access a server-side credential without sending that credential in its code to the browser. Data it renders or passes to client components is still exposed to the recipient. Server Actions also need authentication and authorization for protected operations.

The following fragment assumes a Server Component module and an endpoint returning a message approved for public display. The comments refer only to server execution and credential placement. It is not a complete private-data access pattern: it omits authentication, response validation, timeouts, error handling, and cache policy. Do not move it into a client component or use it for private user data without those controls.

Implementing Protected Backend Routes

For a browser app, calls requiring a secret provider credential can run through your backend. Authenticate callers where required, enforce permissions, validate operations, and limit usage. Inspect responses and logs for accidental disclosure. A proxy does not become secure merely because the browser calls your URL. See environment-variable handling.

What Is The React Security Checklist For 2026?

Securing a React application requires a multi-layered approach. While React provides built-in protection against some attacks, it is not a "set and forget" solution.

Sanitize Dynamic Content

React escapes ordinary text children, but dangerouslySetInnerHTML inserts raw HTML. Avoid that path unless the feature needs HTML; then use an appropriate maintained sanitizer and test the allowed markup. Escaping text is not a complete defense for every URL, script, or DOM sink.

Validate Props and State

Use runtime schema validation for untrusted data; TypeScript types alone do not validate runtime input.

Secure Authentication Flow

Avoid storing session credentials in localStorage, where scripts executing in the origin can read them. An httpOnly cookie prevents direct JavaScript reads, but the session design still needs appropriate Secure and SameSite settings, CSRF defenses where applicable, expiry, and server-side validation. XSS may still perform actions through the browser.

Audit Dependencies

Review installed dependency versions and provenance. npm audit reports supported known-vulnerability matches; SimplyScan repository checks use supported lockfiles and advisory lookups rather than proving every entry in package.json is safe. See the repository scanning guide.

Implement Content Security Policy (CSP)

CSP restricts supported browser behavior according to its configured directives. Test it against the app's resource needs and use it alongside safe output handling; it does not prove that all XSS paths are blocked.

How To Prevent XSS In React AI Code?

Cross-Site Scripting (XSS) occurs when an attacker injects malicious scripts into your web pages. Review input handling and output use, and test how untrusted data reaches interpreters or the browser.

The Danger of dangerouslySetInnerHTML

Review any use of dangerouslySetInnerHTML, including HTML produced from Markdown or model output. Untrusted markup with an event handler, such as an <img onerror> pattern, can execute script if inserted through an unsafe sink. The exact result depends on the markup, sanitizer, and browser policy.

A Browser-Side Sanitization Example

The following browser React fragment uses DOMPurify to sanitize an HTML string immediately before insertion. It assumes a maintained DOMPurify version and a browser DOM. Server rendering needs the library's documented server setup. Review the allowed HTML policy and avoid modifying sanitized markup afterward; this example does not validate every downstream use of the content.

Review database queries and command execution separately; HTML sanitization does not make data safe for every interpreter. See injection prevention.

Is Supabase Or Firebase Safe For React Apps?

Supabase and Firebase provide different access-control mechanisms. Review the backend you actually use and test both allowed and denied requests. A provider integration alone does not establish correct application permissions.

Supabase RLS And Grants

A public Supabase anon key identifies access under the applicable role; it does not itself grant access to every table. Review grants, RLS state, policies, and bypass roles. Firebase uses Security Rules rather than Postgres RLS.

For an owner-only Postgres policy, auth.uid() may identify the requesting user. Match the policy to the schema and intended sharing, then test it with different accounts. The aggregate scan figures do not establish the prevalence of a particular configuration. See the Supabase security checklist.

How To Handle Environment Variables Securely?

In Vite, variables with the VITE_ prefix are made available to client code under its environment-variable conventions. When a value is included in browser output, recipients can inspect it. Review references and build output rather than assuming all environment variables behave the same way.

Public vs. Private Values

  • Intended public values: A project URL or a provider-issued publishable key can be appropriate for client code. Names such as VITE_SUPABASE_URL and VITE_STRIPE_PUBLIC_KEY are examples; verify the actual value and permissions.
  • Secret values: Keep credentials such as those stored in STRIPE_SECRET_KEY, OPENAI_API_KEY, or a credential-bearing DATABASE_URL on the backend. Do not expose them through VITE_ or NEXT_PUBLIC_ variables.

A .env file can feed either server or client configuration, depending on the build. Check where a value is used and what is delivered to the browser. If a secret was exposed, revoke it and investigate usage; removing it from a file is not enough. See exposed-key remediation.

Why Should You Use A Security Scanner For React?

Automated checks complement source review and tests of the deployed app. They are useful for supported exposure patterns, but they do not replace understanding the authorization and data flow of each feature.

SimplyScan reports across 8 dimensions, including security and domain health. A free scan exposes selected findings, subject to usage limits. URL checks can inspect recognized secret patterns, returned headers, and selected backend exposure signals; they do not verify every private policy or authenticated workflow.

For platform-specific guidance, see:

Run relevant checks against a scanner-reachable staging deployment when available, investigate findings, and test behavior outside the scan's coverage before release.

Summary Of React Security Best Practices

Securing a React app in 2026 requires moving away from the "frontend-only" mindset. Even if you are building a simple MVP with an AI agent, you must respect the boundary between public client code and private server logic.

  • Keep secrets out of VITE_ or NEXT_PUBLIC_ values delivered to the browser.
  • Protect server-side operations and inspect what data they return.
  • Configure and test database permissions, including RLS where applicable.
  • Use safe text rendering, or appropriate sanitization where HTML is required.
  • Use a React security checklist to organize tests of the deployment.

The impact of a leaked credential depends on its permissions and the services it can access. Investigate exposure, revoke compromised credentials, and retest relevant controls. A scan can contribute findings without establishing that all risks are resolved.

Frequently asked questions

Is React secure by default for AI-generated apps?

React escapes ordinary text rendering, but this does not secure every DOM sink or backend operation. Review raw HTML, URL handling, secret exposure, authentication, and data permissions. Test the actual implementation whether it was generated or written manually.

How do I hide an API key in a React app?

Keep a secret provider key on the backend and perform the required call there. Authenticate and authorize callers where appropriate and limit usage. A public client identifier or a provider-supported short-lived browser credential has a different role; follow its documented restrictions and inspect what the client receives.

What is RLS and why does my React app need it?

Postgres RLS applies row-level policies to roles subject to it, alongside table privileges and other controls. It can help a Supabase design, but it is not required by every React architecture. Firebase uses Security Rules. Test the intended public, owner, shared, and privileged access for your app.

Are .env variables safe in a React frontend?

A file name or environment-variable syntax does not guarantee privacy. Values exposed through client-facing framework conventions can appear in browser output. Keep secret credentials in server-side configuration and inspect the generated bundle, responses, and logs for disclosure.

How can I prevent XSS when rendering AI-generated content?

Prefer rendering untrusted content as text. If the feature needs HTML, use an appropriate maintained sanitizer for the intended markup and runtime, avoid modifying the sanitized result, and test relevant unsafe sinks. React escaping and CSP alone do not establish complete XSS protection.

Why should I scan my React app for vulnerabilities?

SimplyScan can identify supported public-resource secret patterns, returned-header issues, and selected backend exposure signals. Use these findings alongside source review and tests of private permissions and authenticated workflows; a clean scan does not prove the app is secure.

Related guides

  • Beyond the Vibe: Fixing the Architecture Gap in AI-Built Apps · Vibe coding can speed up implementation, but release readiness requires a separate assessment. Before deployment, review server-side authorization, data access, dependency risks, and configuration, then combine automated checks with manual testing of the application.
  • Fixing Cursor Login Vulnerabilities: Secure Auth Patterns for AI-Built Apps · Review authentication in apps built with Cursor, including server-side session validation, Supabase access policies, secret handling, and OAuth redirects. Combine code review and authenticated tests with bounded scans of publicly observable issues.
  • Next.js Security: Fixing the Architecture Gaps in AI-Generated Apps · Review generated code and deployment configuration independently of whether the visible features work. Key fixes include securing Server Actions with manual authorization, preventing data leaks in component props, and auditing environment variables to avoid exposing sensitive API keys.
  • OWASP Top 10 for AI-Built Apps: What Vibe Coders Need to Know · Use the OWASP Top 10 to organize a review of your app's access controls, input handling, dependencies, configuration, and failure behavior. Generated code needs these checks too. The appropriate controls depend on the architecture; a scan or one database setting does not cover every category.

All security guides · Free security tools · Platform scanners · Security checklist