ctrlshiftleft
Version:
AI-powered toolkit for embedding QA and security testing into development workflows
179 lines (167 loc) • 8.07 kB
text/typescript
/**
* 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];
};