UNPKG

ubon

Version:

Security scanner for AI-generated React/Next.js and Python apps. Catches hardcoded secrets, accessibility issues, and vulnerabilities that traditional linters miss.

95 lines (94 loc) 19.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.RULES = void 0; // Central registry of rules used across scanners. exports.RULES = { // Accessibility A11Y001: { id: 'A11Y001', category: 'accessibility', severity: 'medium', message: 'Image without alt attribute', fix: 'Add descriptive alt attribute to images', helpUri: 'https://webaim.org/techniques/alttext/', impact: 'Screen readers cannot describe images to visually impaired users' }, A11Y002: { id: 'A11Y002', category: 'accessibility', severity: 'medium', message: 'Input without label or aria-label', fix: 'Add proper labeling to form inputs', helpUri: 'https://web.dev/labels-and-text-alternatives/', impact: 'Users with disabilities cannot understand what the input field is for' }, A11Y003: { id: 'A11Y003', category: 'accessibility', severity: 'high', message: 'Empty button without aria-label', fix: 'Add descriptive text or aria-label to buttons', helpUri: 'https://dequeuniversity.com/rules/axe/4.7/button-name', impact: 'Screen readers cannot announce button purpose, blocking critical actions' }, A11Y004: { id: 'A11Y004', category: 'accessibility', severity: 'medium', message: 'Div with onClick (not keyboard accessible)', fix: 'Use button element or add keyboard event handlers', helpUri: 'https://developer.mozilla.org/docs/Web/Accessibility/ARIA/Roles/button_role', impact: 'Keyboard-only users cannot activate this interactive element' }, A11Y005: { id: 'A11Y005', category: 'accessibility', severity: 'low', message: 'Link without href attribute', fix: 'Add href attribute or use button element', helpUri: 'https://dequeuniversity.com/rules/axe/4.7/link-name' }, A11Y006: { id: 'A11Y006', category: 'accessibility', severity: 'low', message: 'Image missing width/height attributes', fix: 'Specify width and height to avoid layout shifts', helpUri: 'https://web.dev/optimize-cls/' }, A11Y007: { id: 'A11Y007', category: 'accessibility', severity: 'low', message: 'next/image used without width and height', fix: 'Provide width and height props to <Image>', helpUri: 'https://nextjs.org/docs/pages/api-reference/components/image' }, // Security (JS/TS) SEC001: { id: 'SEC001', category: 'security', severity: 'high', message: 'Potential API key or secret token exposed', fix: 'Move sensitive keys to environment variables', impact: 'Exposed credentials can be stolen from source code and used to access your services', helpUri: 'https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html' }, SEC002: { id: 'SEC002', category: 'security', severity: 'medium', message: 'Supabase URL hardcoded (should use env var)', fix: 'Use NEXT_PUBLIC_SUPABASE_URL environment variable', impact: 'Hardcoded URLs make it difficult to manage different environments securely' }, SEC003: { id: 'SEC003', category: 'security', severity: 'high', message: 'Supabase anon key hardcoded (JWT token pattern)', fix: 'Use NEXT_PUBLIC_SUPABASE_ANON_KEY environment variable', impact: 'Exposed database keys allow unauthorized access to your Supabase instance' }, SEC004: { id: 'SEC004', category: 'security', severity: 'medium', message: 'Supabase URL hardcoded in variable', fix: 'Use process.env.NEXT_PUBLIC_SUPABASE_URL', impact: 'Hardcoded configuration prevents secure environment management' }, SEC005: { id: 'SEC005', category: 'security', severity: 'high', message: 'Supabase key hardcoded in variable', fix: 'Use process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY', impact: 'Database credentials in code can be extracted and misused' }, SEC006: { id: 'SEC006', category: 'security', severity: 'high', message: 'Hardcoded password detected', fix: 'Use environment variables for passwords', impact: 'Passwords in source code can be stolen by anyone with access to the codebase' }, SEC007: { id: 'SEC007', category: 'security', severity: 'high', message: 'Database URL hardcoded', fix: 'Use environment variable for database connection', impact: 'Database credentials allow complete access to your data if compromised' }, SEC008: { id: 'SEC008', category: 'security', severity: 'medium', message: 'Environment variable with hardcoded fallback', fix: 'Remove hardcoded fallback values', impact: 'Fallbacks can leak sensitive defaults and bypass environment-based security' }, SEC009: { id: 'SEC009', category: 'security', severity: 'high', message: 'AWS Access Key ID exposed', fix: 'Move AWS credentials to environment variables', impact: 'AWS credentials can be used to access and bill your cloud resources' }, SEC010: { id: 'SEC010', category: 'security', severity: 'high', message: 'Google OAuth token exposed', fix: 'Use secure token storage', impact: 'OAuth tokens can be used to impersonate users and access their Google data' }, SEC011: { id: 'SEC011', category: 'security', severity: 'high', message: 'GitHub token exposed', fix: 'Use environment variables for GitHub tokens', impact: 'GitHub tokens allow access to repositories and can be used for supply chain attacks' }, SEC012: { id: 'SEC012', category: 'security', severity: 'high', message: 'Stripe live secret key exposed', fix: 'Move Stripe live keys to secure environment', impact: 'Live Stripe keys can be used to process payments and access customer data' }, SEC013: { id: 'SEC013', category: 'security', severity: 'medium', message: 'Stripe live publishable key exposed', fix: 'Use environment variable for Stripe keys', impact: 'Exposed payment keys can be used to initiate unauthorized transactions' }, SEC014: { id: 'SEC014', category: 'security', severity: 'high', message: 'OpenAI API key exposed', fix: 'Use OPENAI_API_KEY environment variable', impact: 'OpenAI keys can be stolen and used to run up charges on your account', helpUri: 'https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html' }, SEC015: { id: 'SEC015', category: 'security', severity: 'low', message: 'Console statement found (may leak sensitive info)', fix: 'Remove console statements before production', impact: 'Console logs can expose sensitive data in browser developer tools' }, SEC016: { id: 'SEC016', category: 'security', severity: 'high', message: 'Use of eval() detected (security risk)', fix: 'Replace eval() with safer alternatives', impact: 'eval() can execute malicious code and is a common vector for code injection attacks', helpUri: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/eval' }, SEC017: { id: 'SEC017', category: 'security', severity: 'medium', message: 'dangerouslySetInnerHTML usage (XSS risk)', fix: 'Sanitize HTML content or use safer alternatives', impact: 'Unsanitized HTML can inject malicious scripts that steal user data', helpUri: 'https://react.dev/reference/react-dom/components/common#dangerously-setting-the-inner-html' }, SEC018: { id: 'SEC018', category: 'security', severity: 'high', message: 'High-entropy string literal (possible secret)', fix: 'Move secrets to environment variables; rotate credentials', impact: 'High-entropy strings often contain API keys or tokens that can be misused', helpUri: 'https://owasp.org/Top10/A02_2021-Cryptographic_Failures' }, SEC019: { id: 'SEC019', category: 'security', severity: 'high', message: 'React component injection via createElement', fix: 'Disallow dynamic element types from untrusted input', impact: 'Component injection can lead to XSS attacks and arbitrary code execution' }, LOG001: { id: 'LOG001', category: 'security', severity: 'medium', message: 'Potential secret logged to console/logger', fix: 'Avoid logging secrets; redact values before logging', impact: 'Secrets in logs can be exposed through log aggregation systems or error tracking', helpUri: 'https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html' }, OSV001: { id: 'OSV001', category: 'security', severity: 'high', message: 'Vulnerable dependency detected', fix: 'Upgrade to a patched version' }, // Networking (JS) JSNET001: { id: 'JSNET001', category: 'security', severity: 'medium', message: 'HTTP request without timeout/retry policy', fix: 'Add timeout/backoff to axios/fetch calls', helpUri: 'https://developer.mozilla.org/docs/Web/API/AbortController' }, // Cookies / headers COOKIE001: { id: 'COOKIE001', category: 'security', severity: 'medium', message: 'Set-Cookie missing HttpOnly/Secure/SameSite', fix: 'Add HttpOnly; Secure; SameSite=Lax (or Strict) to cookies', impact: 'Insecure cookies can be stolen via XSS attacks or intercepted over insecure connections', helpUri: 'https://owasp.org/www-community/controls/SecureCookieAttributes' }, COOKIE002: { id: 'COOKIE002', category: 'security', severity: 'high', message: 'JWT token exposed in client-side cookie without security flags', fix: 'Add HttpOnly and Secure flags to JWT cookies', impact: 'JWT tokens in insecure cookies can be stolen and used to impersonate users', helpUri: 'https://owasp.org/www-community/controls/SecureCookieAttributes' }, COOKIE003: { id: 'COOKIE003', category: 'security', severity: 'high', message: 'Sensitive data returned in JSON response (potential token leak)', fix: 'Avoid returning tokens/secrets in API responses; use secure cookies instead', impact: 'Tokens in JSON responses are visible to client-side JavaScript and can be stolen' }, COOKIE004: { id: 'COOKIE004', category: 'security', severity: 'medium', message: 'Cookie used without domain/path restrictions', fix: 'Set appropriate domain and path attributes for cookies', impact: 'Overly broad cookie scope can lead to unintended exposure to subdomains' }, // Env ENV001: { id: 'ENV001', category: 'security', severity: 'high', message: '.env file may not be in .gitignore', fix: 'Add .env files to .gitignore to prevent accidental commits' }, ENV002: { id: 'ENV002', category: 'security', severity: 'high', message: 'Potential API key in .env file', fix: 'Ensure this .env file is in .gitignore and not committed' }, ENV004: { id: 'ENV004', category: 'security', severity: 'high', message: 'Secret value in .env file', fix: 'Verify .env is in .gitignore and use .env.example for documentation' }, ENV005: { id: 'ENV005', category: 'security', severity: 'medium', message: 'Supabase credentials in .env', fix: 'Ensure this .env file is not committed to version control' }, ENV006: { id: 'ENV006', category: 'security', severity: 'low', message: 'Missing .env.example file for documentation', fix: 'Create .env.example with placeholder values for team setup' }, // Links LINK001: { id: 'LINK001', category: 'links', severity: 'low', message: 'Link checking requires puppeteer installation', fix: 'Install with: npm install puppeteer' }, LINK002: { id: 'LINK002', category: 'links', severity: 'medium', message: 'External link unreachable or 4xx/5xx', fix: 'Update URL or ensure target is reachable' }, LINK003: { id: 'LINK003', category: 'links', severity: 'medium', message: 'Internal link or resource broken', fix: 'Fix route or asset; check server logs' }, NEXT001: { id: 'NEXT001', category: 'links', severity: 'low', message: 'next/link used without anchor or child text (legacyBehavior)', fix: 'Wrap link content with <a> or set proper child' }, NEXT002: { id: 'NEXT002', category: 'links', severity: 'medium', message: 'In-page <a> used for client navigation; prefer next/link', fix: 'Use <Link href="..."><a>…</a></Link> or modern API' }, NEXT003: { id: 'NEXT003', category: 'security', severity: 'medium', message: 'Next.js API route uses request params without validation', fix: 'Validate input with zod/yup/ajv before usage' }, NEXT004: { id: 'NEXT004', category: 'security', severity: 'high', message: 'Dynamic import with user-controlled path', fix: 'Avoid dynamic import sources from untrusted input' }, NEXT005: { id: 'NEXT005', category: 'accessibility', severity: 'low', message: 'External <img> used in Next.js app (consider next/image)', fix: 'Use next/image for external sources with proper config' }, NEXT006: { id: 'NEXT006', category: 'security', severity: 'high', message: 'Sensitive data exposed via getStaticProps/getServerSideProps', fix: 'Do not include secrets/env in returned props' }, // Python PYSEC001: { id: 'PYSEC001', category: 'security', severity: 'high', message: 'Potential API key exposed', fix: 'Move secrets to environment variables' }, PYSEC002: { id: 'PYSEC002', category: 'security', severity: 'high', message: 'Use of exec() detected', fix: 'Avoid exec(); use safer alternatives' }, PYSEC003: { id: 'PYSEC003', category: 'security', severity: 'high', message: 'Use of eval() detected', fix: 'Avoid eval(); use safer alternatives' }, PYSEC004: { id: 'PYSEC004', category: 'security', severity: 'high', message: 'subprocess with shell=True', fix: 'Avoid shell=True; pass args as list' }, PYSEC005: { id: 'PYSEC005', category: 'security', severity: 'medium', message: 'yaml.load() unsafe without Loader', fix: 'Use yaml.safe_load()' }, PYSEC006: { id: 'PYSEC006', category: 'security', severity: 'medium', message: 'Insecure pickle usage', fix: 'Avoid pickle with untrusted data' }, PYSEC007: { id: 'PYSEC007', category: 'security', severity: 'medium', message: 'TLS verification disabled', fix: 'Remove verify=False' }, PYSEC009: { id: 'PYSEC009', category: 'security', severity: 'medium', message: 'DEBUG=True in settings', fix: 'Disable DEBUG in production' }, PYSEC010: { id: 'PYSEC010', category: 'security', severity: 'low', message: 'ALLOWED_HOSTS includes *', fix: 'Restrict ALLOWED_HOSTS' }, PYNET001: { id: 'PYNET001', category: 'security', severity: 'medium', message: 'requests call without timeout', fix: 'Add timeout= to requests.* calls' }, // Docker / CI DOCKER001: { id: 'DOCKER001', category: 'security', severity: 'medium', message: 'Dockerfile runs as root (USER root or no USER)', fix: 'Add a non-root USER' }, DOCKER002: { id: 'DOCKER002', category: 'security', severity: 'high', message: 'Secrets defined via ENV in Dockerfile', fix: 'Avoid embedding secrets in Docker images' }, DOCKER003: { id: 'DOCKER003', category: 'security', severity: 'low', message: 'Docker base image uses :latest tag', fix: 'Pin to a specific version tag' }, DOCKER004: { id: 'DOCKER004', category: 'security', severity: 'low', message: 'apt-get install without cleaning apt cache', fix: 'Run rm -rf /var/lib/apt/lists/* after apt-get' }, // Env drift ENV007: { id: 'ENV007', category: 'security', severity: 'low', message: 'Environment variable drift between .env and .env.example', fix: 'Align keys in .env and .env.example' }, // Vue VUE001: { id: 'VUE001', category: 'security', severity: 'high', message: 'v-html binding (XSS risk)', fix: 'Avoid v-html or sanitize input before binding' }, // CI GHA001: { id: 'GHA001', category: 'security', severity: 'high', message: 'Secrets may be echoed in GitHub Actions workflow', fix: 'Do not print secrets to logs; remove echo/printf of secrets' }, // Next.js JWT/Cookie security rules NEXT007: { id: 'NEXT007', category: 'security', severity: 'high', message: 'JWT token exposed in Next.js API response', fix: 'Use httpOnly cookies instead of returning tokens in JSON', impact: 'JWT tokens in API responses can be stolen via XSS and used for session hijacking' }, NEXT008: { id: 'NEXT008', category: 'security', severity: 'medium', message: 'Missing security headers in Next.js API route', fix: 'Add security headers like X-Content-Type-Options, X-Frame-Options', impact: 'Missing security headers expose the application to various client-side attacks' }, NEXT009: { id: 'NEXT009', category: 'security', severity: 'high', message: 'Unsafe redirect in Next.js API route', fix: 'Validate redirect URLs against allowlist', impact: 'Open redirects can be used for phishing attacks and credential theft', helpUri: 'https://owasp.org/www-community/attacks/Unvalidated_Redirects_and_Forwards_Cheat_Sheet' }, NEXT010: { id: 'NEXT010', category: 'security', severity: 'medium', message: 'CORS configuration too permissive', fix: 'Restrict CORS to specific origins instead of using wildcard', impact: 'Overly permissive CORS allows malicious sites to make requests on behalf of users', helpUri: 'https://developer.mozilla.org/docs/Web/HTTP/CORS' }, NEXT011: { id: 'NEXT011', category: 'security', severity: 'high', message: 'Environment variable leaked in client-side code', fix: 'Use NEXT_PUBLIC_ prefix only for truly public variables', impact: 'Server-side environment variables exposed to client reveal sensitive configuration', helpUri: 'https://nextjs.org/docs/app/building-your-application/configuring/environment-variables#bundling-environment-variables-for-the-browser' }, // Next.js routing & structure (experimental P5) NEXT201: { id: 'NEXT201', category: 'links', severity: 'low', message: 'Missing 404/not-found page', fix: 'Add pages/404.tsx (Pages Router) or app/not-found.tsx (App Router)', helpUri: 'https://nextjs.org/docs/app/api-reference/file-conventions/not-found', impact: 'Improves UX and SEO by handling missing routes gracefully' }, NEXT202: { id: 'NEXT202', category: 'links', severity: 'low', message: 'Missing error boundary page', fix: 'Add pages/_error.tsx (Pages Router) or app/error.tsx (App Router)', helpUri: 'https://nextjs.org/docs/app/building-your-application/routing/error-handling', impact: 'Prevents blank screens and surfaces friendly errors to users' }, NEXT203: { id: 'NEXT203', category: 'links', severity: 'low', message: 'Missing _document.tsx while using next/head or next/script', fix: 'Add pages/_document.tsx when customizing <Head> or <Script> in Pages Router', helpUri: 'https://nextjs.org/docs/pages/building-your-application/routing/custom-document', impact: 'Ensures consistent <html>/<body> structure and script handling in Pages Router' }, NEXT205: { id: 'NEXT205', category: 'security', severity: 'medium', message: 'API route may be accessible without authentication', fix: 'Require auth (NextAuth getServerSession/JWT/cookie checks) for sensitive endpoints', helpUri: 'https://next-auth.js.org/configuration/nextjs#api-routes', impact: 'Unauthenticated access to sensitive APIs can leak data or allow abuse' }, NEXT208: { id: 'NEXT208', category: 'security', severity: 'medium', message: 'router.push() to external URL', fix: 'Validate and restrict redirect targets to an allowlist or same-origin', helpUri: 'https://owasp.org/www-community/attacks/Unvalidated_Redirects_and_Forwards_Cheat_Sheet', impact: 'Open redirects facilitate phishing and credential theft' }, NEXT209: { id: 'NEXT209', category: 'security', severity: 'medium', message: 'API route missing HTTP method validation', fix: 'Validate req.method in Pages API or export method handlers (GET/POST/...) in App Router', helpUri: 'https://nextjs.org/docs/app/building-your-application/routing/route-handlers', impact: 'Accepting unintended methods broadens attack surface and leads to undefined behavior' } };