UNPKG

ctrlshiftleft

Version:

AI-powered toolkit for embedding QA and security testing into development workflows

179 lines (167 loc) 8.07 kB
/** * React Security Patterns * * This module provides pattern-matching rules for detecting React-specific * security vulnerabilities and code quality issues. */ export interface SecurityPattern { pattern: RegExp; severity: 'CRITICAL' | 'HIGH' | 'MEDIUM' | 'LOW' | 'INFO'; title: string; description: string; remediation: string; category?: string; } /** * Core React security patterns for detecting common security issues in React applications */ export const REACT_SECURITY_PATTERNS: SecurityPattern[] = [ // React State Management Issues { pattern: /setState\s*\(\s*{.*?['"]\s*__html\s*['"]\s*:|dangerouslySetInnerHTML\s*=\s*{.*?__html/, severity: 'CRITICAL', title: 'Unsafe HTML Injection in React State', description: 'Setting state with dangerouslySetInnerHTML or __html properties can lead to XSS attacks', remediation: 'Use a sanitization library like DOMPurify before setting HTML content in state', category: 'react-state' }, { pattern: /useRef\s*\(\s*null\s*\)[^]*?\.current\.innerHTML\s*=/, severity: 'CRITICAL', title: 'Direct DOM Manipulation with useRef', description: 'Directly manipulating DOM with useRef and innerHTML bypasses React security features', remediation: 'Use React state and dangerouslySetInnerHTML with properly sanitized content if HTML is required', category: 'react-refs' }, // useEffect Dependency Issues { pattern: /useEffect\s*\(\s*\(\s*\)\s*=>\s*{[^}]*}\s*,\s*\[\s*\]\s*\)/, severity: 'MEDIUM', title: 'useEffect with Empty Dependencies', description: 'Using useEffect with empty dependency array may cause stale closures or outdated state references', remediation: 'Add all dependencies used within the effect to the dependency array or consider if effect should actually run on every render', category: 'react-hooks' }, { pattern: /useEffect\s*\(\s*\(\s*\)\s*=>\s*{(?!.*\breturn\b).*?(?:fetch|axios|\.then).*?}\s*,/, severity: 'HIGH', title: 'Missing Cleanup in useEffect with API Calls', description: 'API calls in useEffect without cleanup can lead to memory leaks and race conditions', remediation: 'Add a cleanup function that cancels the request or prevents state update when the component unmounts', category: 'react-hooks' }, // Props & Context Vulnerabilities { pattern: /<Component\s+(?:.*?\s+)?{...props}/, severity: 'HIGH', title: 'Unsafe Props Spreading', description: 'Spreading all props to child components can leak sensitive data or create injection vectors', remediation: 'Explicitly pass only the required props instead of spreading all props', category: 'react-props' }, { pattern: /createContext\s*\(\s*(?:null|undefined|\{\})\s*\)/, severity: 'MEDIUM', title: 'Context without Default Value Type', description: 'Creating context without a properly typed default value can lead to type errors and undefined behavior', remediation: 'Provide a properly typed default value that matches the expected context shape', category: 'react-context' }, // Event Handler Issues { pattern: /on(?:Click|Change|Submit)={\s*\([^)]*\)\s*=>\s*{.*?(?:eval|Function).*}/, severity: 'CRITICAL', title: 'Unsafe Code Execution in Event Handler', description: 'Using eval or Function constructor in event handlers can lead to code injection vulnerabilities', remediation: 'Never use eval or Function constructor in event handlers, use safe state update methods instead', category: 'react-events' }, { pattern: /on(?:Click|Change|Submit)={\s*e\s*=>\s*{.*?(?:innerHTML|outerHTML).*}/, severity: 'CRITICAL', title: 'DOM Manipulation in Event Handler', description: 'Direct DOM manipulation in event handlers bypasses React security model', remediation: 'Use React state and controlled components instead of direct DOM manipulation', category: 'react-events' }, // Key and ID vulnerabilities { pattern: /key={\s*(?:Math\.random|new Date|index|idx|i)\s*}/, severity: 'MEDIUM', title: 'Unsafe React Key Usage', description: 'Using random values, dates, or array indices as React keys can cause performance issues and bugs', remediation: 'Use stable, unique identifier from your data for keys, such as database IDs or unique slugs', category: 'react-keys' }, // useState Issues { pattern: /const\s+\[\s*(\w+)\s*,\s*set\1\s*\]\s*=\s*useState\s*\([^)]*\)[^]*?set\1\s*\(\s*(?:\w+)\s*=>/, severity: 'MEDIUM', title: 'Potential Stale State in useState Updater', description: 'Using useState updater without function form can lead to stale state references', remediation: 'Use the functional update form: setState(prevState => ({ ...prevState, ... }))', category: 'react-state' }, // JSX Injection Vulnerabilities { pattern: /{(?!\s*\/\*)[^}]*?(?:\w+\.innerHTML|\w+\.__html|\w+\.dangerouslySetInnerHTML)[^}]*}/, severity: 'CRITICAL', title: 'JSX Expression with Unsafe HTML', description: 'Using raw HTML in JSX expressions can lead to XSS vulnerabilities', remediation: 'Sanitize any HTML content before rendering and prefer using React components over raw HTML', category: 'react-jsx' } ]; /** * Next.js specific security patterns for detecting security issues in Next.js applications */ export const NEXTJS_SECURITY_PATTERNS: SecurityPattern[] = [ // Next.js API Route Vulnerabilities { pattern: /export\s+(?:default|async)\s+function\s+handler\s*\(\s*req\s*,\s*res\s*\)[^]*?(?:req\.body|req\.query).*?(?!sanitize|validate|escape)/, severity: 'HIGH', title: 'Unvalidated Data in API Route', description: 'API route using request data without validation can lead to injection attacks', remediation: 'Validate all input data using a library like Joi, Zod, or class-validator before processing', category: 'nextjs-api' }, { pattern: /export\s+(?:default|async)\s+function\s+handler\s*\(\s*req\s*,\s*res\s*\)[^]*?res\.status\s*\(\s*200\s*\)\.(?:json|send)\s*\(\s*{.*?(?:password|token|key|secret).*?}/i, severity: 'CRITICAL', title: 'Sensitive Data Exposure in API Response', description: 'API route returning sensitive data like passwords or tokens in response', remediation: 'Never return sensitive fields in API responses, filter them out before sending response', category: 'nextjs-api' }, { pattern: /export\s+(?:default|async)\s+function\s+handler\s*\(\s*req\s*,\s*res\s*\)[^]*?res\.setHeader\s*\(\s*['"]Access-Control-Allow-Origin['"]\s*,\s*['"]\*['"]\s*\)/, severity: 'HIGH', title: 'Permissive CORS in API Route', description: 'Setting Access-Control-Allow-Origin to * in API routes allows any origin to access your API', remediation: 'Restrict CORS to specific origins that need access to your API', category: 'nextjs-api' }, // Next.js Data Fetching Vulnerabilities { pattern: /export\s+(?:const|async)\s+function\s+getServerSideProps\s*\([^)]*\)[^]*?params\.(?:\w+).*?(?!sanitize|validate|escape)/, severity: 'HIGH', title: 'Unvalidated URL Parameters in getServerSideProps', description: 'Using URL parameters in getServerSideProps without validation can lead to injection attacks', remediation: 'Validate all URL parameters before using them in database queries or API calls', category: 'nextjs-data' }, { pattern: /getStaticPaths\s*\([^)]*\)[^]*?return\s*{[^}]*fallback\s*:\s*true/, severity: 'MEDIUM', title: 'Unvalidated fallback in getStaticPaths', description: 'Using fallback: true without proper validation can lead to rendering malicious or unexpected content', remediation: 'Add validation in getStaticProps for fallback pages to ensure only valid data is rendered', category: 'nextjs-data' } ]; /** * Combines all React and Next.js security patterns into a single array */ export const getAllReactPatterns = (): SecurityPattern[] => { return [...REACT_SECURITY_PATTERNS, ...NEXTJS_SECURITY_PATTERNS]; };