agentsclimarketplace

React security

Skill RadOrigin-LLC/RAD-Claude-Skills/archive/plugins/rad-react/skills/react-security

Marketplace of plugins and skills for Claude Code

Install
npx -y skills add RadOrigin-LLC/RAD-Claude-Skills --skill react-security

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 5 stars5 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

This skill should be used when the user is securing a React application, asking about "XSS in React", "dangerouslySetInnerHTML security", "Server Actions security", "React data exposure", "sensitive data in React", "auth token storage", "IDOR in Next.js", "React security audit", "secure React forms", "Server Component secrets", "server-only package", "React taint API", "DOMPurify React", "prototype pollution React", "hardcoded secrets React", or reviewing React code for security vulnerabilities.

SKILL.md

6.7 KB, ~1.4k tokens by cl100k_base, as published. Nobody here has run it

React Security

Security patterns for React applications — XSS prevention, Server Actions authorization, sensitive data protection, and client-side security. These issues cause real breaches; treat each section as mandatory for production code.

XSS — Cross-Site Scripting

React automatically escapes string values rendered in JSX. The primary XSS risk is intentionally bypassing that protection.

dangerouslySetInnerHTML

Every use requires sanitization. No exceptions.

import DOMPurify from 'dompurify'; // or isomorphic-dompurify for SSR

// BAD: XSS if content contains <script> or event attributes
<div dangerouslySetInnerHTML={{ __html: userContent }} />

// GOOD: sanitize before rendering
<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(userContent) }} />

Sanitize at the point of use, not earlier. Data transforms lose sanitization guarantees.

Other XSS Vectors

  • eval(), new Function(string), setTimeout(string) — Never pass strings. Use function references.
  • URL injection: Validate href values — javascript: URLs are XSS vectors. Use URL parsing and allow-lists for external links.
  • innerHTML via refs — Same risk as dangerouslySetInnerHTML. Use textContent for text-only updates.

Server Actions — Authorization

Server Actions are public HTTP POST endpoints. They run on the server but are callable by anyone — treat them like API routes.

Required Pattern: Auth + Authorization in Every Action

// app/actions.ts
'use server'
import { auth } from '@/lib/auth';
import { db } from '@/lib/db';

export async function deletePost(postId: string) {
  // 1. Verify the user is authenticated
  const session = await auth();
  if (!session?.user) throw new Error('Unauthorized');

  // 2. Verify the user owns THIS resource (prevents IDOR)
  const post = await db.post.findUnique({ where: { id: postId } });
  if (!post || post.authorId !== session.user.id) {
    throw new Error('Forbidden');
  }

  await db.post.delete({ where: { id: postId } });
}

IDOR (Insecure Direct Object Reference): If you skip the ownership check, any authenticated user can delete any post by guessing IDs. Page-level auth does NOT protect actions.

Server Action Security Rules

  1. Authenticate — verify session inside the action, not only in middleware
  2. Authorize — verify the user has rights to the specific resource being modified
  3. Validate inputs — parse all FormData through Zod before using it
  4. Sanitize errors — return generic messages to clients; log details server-side
  5. Never return raw DB records, stack traces, or internal field names

Sensitive Data Exposure

Data Access Layer (DAL) Pattern

// lib/dal.ts — SERVER ONLY
import 'server-only';
import { auth } from './auth';

export async function getCurrentUser() {
  const session = await auth();
  if (!session) return null;
  // Return minimal DTO — never the full DB record
  return { id: session.user.id, name: session.user.name, role: session.user.role };
}
// Any server-only file
import 'server-only'; // Build error if imported from a Client Component

The server-only package causes a build-time error if the module is accidentally imported into a Client Component. Use it on every file that accesses secrets, env vars, or the database.

React Taint APIs (Experimental)

Explicitly mark objects and values as un-passable to Client Components:

import { experimental_taintObjectReference, experimental_taintUniqueValue } from 'react';

// Mark entire object — prevents passing to Client Component
experimental_taintObjectReference('Do not pass user record to client', user);

// Mark specific value — prevents passing token to client
experimental_taintUniqueValue('Do not pass token to client', process, process.env.API_SECRET);

Environment Variables

  • NEXT_PUBLIC_* variables are exposed to the browser. Use for non-secret config only.
  • All other process.env.* variables stay server-side — never read them in Client Components.
  • Never hardcode API keys, tokens, or credentials in source code.

Authentication Token Storage

StorageRiskRecommendation
localStorageAccessible to any JS on the page — XSS attack steals tokenNever for auth tokens
sessionStorageSame XSS risk as localStorageNever for auth tokens
httpOnly cookieJS cannot read it — XSS cannot steal itUse this
// BAD: XSS can steal the token
localStorage.setItem('auth_token', token);

// GOOD: set from server response with httpOnly flag
// res.cookie('session', token, { httpOnly: true, secure: true, sameSite: 'lax' });

Prototype Pollution

// BAD: deep merging user-controlled objects can inject __proto__ keys
import merge from 'lodash.merge';
const config = merge({}, userInput); // if userInput contains __proto__

// GOOD: validate schema before merging
import { z } from 'zod';
const schema = z.object({ theme: z.string(), language: z.string() });
const safe = schema.parse(userInput);
const config = Object.assign({}, defaults, safe);

Always validate JSON.parse results against a Zod schema before using user-controlled data.

Hardcoded Secrets Detection

Patterns that indicate hardcoded secrets in React code (flag in every code review):

  • apiKey = "...", api_key: "...", API_KEY = "..."
  • token = "Bearer ...", authorization: "...", password = "..."
  • Strings starting with sk-, pk_, ghp_, xoxb-, AKIA
  • Long alphanumeric strings (32+ chars) assigned directly in component files

These must be moved to environment variables and accessed via process.env on the server.

Sensitive Data in console.log

// BAD: user PII and tokens visible in browser DevTools
console.log('User:', user); // may include email, address, token

// GOOD: guard dev-only logging
if (process.env.NODE_ENV === 'development') {
  console.log('User ID:', user.id); // log only what you need
}

Additional Resources

Reference Files

  • references/detailed-patterns.md — Complete Server Action auth patterns, Zod validation for form inputs, Content Security Policy headers, and Electron-specific React security

What ships with it: 1 file

6.6 KB alongside SKILL.md

references/

Gives 0 of the 12 instructions most security skills give in ~1.4k tokens

Counted across 648 of the 828 authors here whose files we hold, read 2026-08-07

  • Parameterize all database queriesin 68 of 648, across 51 files
  • Hash passwords using bcrypt, scrypt, or argon2in 49 of 648, across 36 files
  • Apply rate limiting to authentication endpointsin 48 of 648, across 24 files
  • Configure security headersin 35 of 648, across 19 files
  • Validate all inputsin 32 of 648, across 24 files
  • Validate all external input at the system boundaryin 29 of 648, across 19 files
  • Run containers as a non-root userin 28 of 648, across 15 files
  • Use httponly secure samesite cookies for sessionsin 26 of 648, across 15 files
  • Run dependency audits before every releasein 21 of 648, across 10 files
  • Encode output to prevent cross-site scriptingin 21 of 648, across 11 files
  • Copy dependencies before source codein 20 of 648, across 9 files
  • Store secrets in environment variablesin 20 of 648, across 18 files

Said here and by no other author read

  • validate href values against javascript URLs
  • import the server-only package in data access files
  • move hardcoded secrets to environment variables
  • guard sensitive data inside console log statements

Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.

Keep looking

Skills are one crate of 327,069. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.