UNPKG

vibesec

Version:

Security scanner for AI-generated code - detects vulnerabilities in vibe-coded projects

477 lines (434 loc) 13.6 kB
# HTTP Security Headers Rules # Detects missing or misconfigured HTTP security headers rules: - id: missing-csp-header name: Missing Content Security Policy description: Content-Security-Policy header is missing, allowing XSS and data injection attacks severity: high category: headers languages: - javascript - typescript - python - php enabled: true patterns: - regex: "app\\.(use|get|post)\\s*\\((?!.*Content-Security-Policy)" flags: gi - regex: "express\\(\\)(?!.*helmet|.*csp)" flags: gi fix: template: | Implement Content-Security-Policy header using helmet or manually. Before: const app = express(); After: const helmet = require('helmet'); const app = express(); app.use(helmet.contentSecurityPolicy({ directives: { defaultSrc: ["'self'"], scriptSrc: ["'self'"], styleSrc: ["'self'", "'unsafe-inline'"], imgSrc: ["'self'", "data:", "https:"], connectSrc: ["'self'"], fontSrc: ["'self'"], objectSrc: ["'none'"], mediaSrc: ["'self'"], frameSrc: ["'none'"] } })); // Or manually: app.use((req, res, next) => { res.setHeader( 'Content-Security-Policy', "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'" ); next(); }); references: - https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP - https://owasp.org/www-project-secure-headers/#content-security-policy metadata: cwe: CWE-693 owasp: "A05:2021" tags: - headers - csp - xss - id: missing-hsts-header name: Missing HTTP Strict Transport Security description: HSTS header missing, allowing protocol downgrade attacks severity: high category: headers languages: - javascript - typescript - python - php enabled: true patterns: - regex: "https\\.createServer|createServer\\([^)]*https(?!.*Strict-Transport-Security|.*hsts)" flags: gi - regex: "app\\.listen\\(443(?!.*Strict-Transport-Security|.*helmet)" flags: gi fix: template: | Add HSTS header to enforce HTTPS connections. Before: const app = express(); After: const helmet = require('helmet'); app.use(helmet.hsts({ maxAge: 31536000, // 1 year in seconds includeSubDomains: true, preload: true })); // Or manually: app.use((req, res, next) => { res.setHeader( 'Strict-Transport-Security', 'max-age=31536000; includeSubDomains; preload' ); next(); }); references: - https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security - https://owasp.org/www-project-secure-headers/#http-strict-transport-security metadata: cwe: CWE-319 owasp: "A02:2021" tags: - headers - hsts - https - id: missing-x-frame-options name: Missing X-Frame-Options Header description: Missing clickjacking protection header severity: medium category: headers languages: - javascript - typescript - python - php enabled: true patterns: - regex: "app\\.use\\((?!.*X-Frame-Options|.*frameguard|.*helmet)" flags: gi - regex: "res\\.render\\((?!.*X-Frame-Options)" flags: gi fix: template: | Add X-Frame-Options header to prevent clickjacking. Before: const app = express(); After: const helmet = require('helmet'); app.use(helmet.frameguard({ action: 'deny' })); // Or manually: app.use((req, res, next) => { res.setHeader('X-Frame-Options', 'DENY'); // Or: res.setHeader('X-Frame-Options', 'SAMEORIGIN'); next(); }); references: - https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options - https://owasp.org/www-project-secure-headers/#x-frame-options metadata: cwe: CWE-1021 owasp: "A04:2021" tags: - headers - clickjacking - x-frame-options - id: missing-x-content-type-options name: Missing X-Content-Type-Options Header description: Missing MIME type sniffing protection severity: medium category: headers languages: - javascript - typescript - python - php enabled: true patterns: - regex: "app\\.use\\((?!.*X-Content-Type-Options|.*noSniff|.*helmet)" flags: gi fix: template: | Add X-Content-Type-Options header to prevent MIME sniffing. Before: const app = express(); After: const helmet = require('helmet'); app.use(helmet.noSniff()); // Or manually: app.use((req, res, next) => { res.setHeader('X-Content-Type-Options', 'nosniff'); next(); }); references: - https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options - https://owasp.org/www-project-secure-headers/#x-content-type-options metadata: cwe: CWE-693 owasp: "A05:2021" tags: - headers - mime-sniffing - x-content-type-options - id: missing-referrer-policy name: Missing Referrer-Policy Header description: Referrer-Policy header missing, potentially leaking sensitive information severity: low category: headers languages: - javascript - typescript - python - php enabled: true patterns: - regex: "app\\.use\\((?!.*Referrer-Policy|.*referrerPolicy|.*helmet)" flags: gi fix: template: | Add Referrer-Policy header to control referrer information. Before: const app = express(); After: const helmet = require('helmet'); app.use(helmet.referrerPolicy({ policy: 'strict-origin-when-cross-origin' })); // Or manually: app.use((req, res, next) => { res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin'); next(); }); references: - https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy - https://owasp.org/www-project-secure-headers/#referrer-policy metadata: cwe: CWE-200 owasp: "A01:2021" tags: - headers - referrer-policy - privacy - id: missing-permissions-policy name: Missing Permissions-Policy Header description: Permissions-Policy (formerly Feature-Policy) header missing severity: low category: headers languages: - javascript - typescript - python - php enabled: true patterns: - regex: "app\\.use\\((?!.*Permissions-Policy|.*Feature-Policy|.*helmet)" flags: gi fix: template: | Add Permissions-Policy header to control browser features. Before: const app = express(); After: const helmet = require('helmet'); app.use(helmet.permittedCrossDomainPolicies()); // Or manually: app.use((req, res, next) => { res.setHeader( 'Permissions-Policy', 'geolocation=(), microphone=(), camera=()' ); next(); }); references: - https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Permissions-Policy - https://owasp.org/www-project-secure-headers/#permissions-policy metadata: cwe: CWE-693 owasp: "A05:2021" tags: - headers - permissions-policy - privacy - id: weak-csp-policy name: Weak Content Security Policy description: CSP allows 'unsafe-inline' or 'unsafe-eval' which weakens XSS protection severity: medium category: headers languages: - javascript - typescript - python - php enabled: true patterns: - regex: "Content-Security-Policy[\"'].*[\"']unsafe-inline[\"']" flags: gi - regex: "Content-Security-Policy[\"'].*[\"']unsafe-eval[\"']" flags: gi - regex: "scriptSrc\\s*:\\s*\\[[^\\]]*[\"']unsafe-inline[\"']" flags: gi - regex: "scriptSrc\\s*:\\s*\\[[^\\]]*[\"']unsafe-eval[\"']" flags: gi fix: template: | Remove 'unsafe-inline' and 'unsafe-eval' from CSP. Use nonces or hashes. Before: app.use(helmet.contentSecurityPolicy({ directives: { scriptSrc: ["'self'", "'unsafe-inline'"] } })); After: // Option 1: Use nonces app.use((req, res, next) => { res.locals.nonce = crypto.randomBytes(16).toString('base64'); next(); }); app.use(helmet.contentSecurityPolicy({ directives: { scriptSrc: ["'self'", (req, res) => `'nonce-${res.locals.nonce}'`] } })); // In your template: // <script nonce="<%= nonce %>">...</script> // Option 2: Use hashes for inline scripts app.use(helmet.contentSecurityPolicy({ directives: { scriptSrc: ["'self'", "'sha256-xyz...'"] } })); references: - https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP - https://content-security-policy.com/ metadata: cwe: CWE-693 owasp: "A05:2021" tags: - headers - csp - unsafe-inline - id: x-powered-by-header name: X-Powered-By Header Exposure description: X-Powered-By header reveals technology stack information severity: low category: headers languages: - javascript - typescript - python - php enabled: true patterns: - regex: "express\\(\\)(?!.*app\\.disable\\([\"']x-powered-by[\"']\\)|.*helmet\\.hidePoweredBy)" flags: gi - regex: "X-Powered-By" flags: gi fix: template: | Remove or disable X-Powered-By header. Before: const app = express(); After: const app = express(); app.disable('x-powered-by'); // Or use helmet: app.use(helmet.hidePoweredBy()); references: - https://owasp.org/www-project-secure-headers/ - https://expressjs.com/en/advanced/best-practice-security.html metadata: cwe: CWE-200 owasp: "A05:2021" tags: - headers - information-disclosure - x-powered-by - id: cors-allow-all-origins name: Permissive CORS Configuration description: CORS allows all origins (*), potentially exposing sensitive data severity: medium category: headers languages: - javascript - typescript - python - php enabled: true patterns: - regex: "Access-Control-Allow-Origin[\"']\\s*,\\s*[\"']\\*[\"']" flags: gi - regex: "cors\\s*\\(\\s*\\{[^}]*origin\\s*:\\s*[\"']\\*[\"']" flags: gi fix: template: | Specify allowed origins instead of using wildcard. Before: app.use(cors({ origin: '*' })); After: const allowedOrigins = ['https://example.com', 'https://app.example.com']; app.use(cors({ origin: (origin, callback) => { if (!origin || allowedOrigins.includes(origin)) { callback(null, true); } else { callback(new Error('Not allowed by CORS')); } } })); references: - https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS - https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/11-Client-side_Testing/07-Testing_Cross_Origin_Resource_Sharing metadata: cwe: CWE-346 owasp: "A05:2021" tags: - headers - cors - access-control - id: cache-control-sensitive-data name: Missing Cache-Control for Sensitive Data description: Sensitive endpoints lack proper Cache-Control headers severity: medium category: headers languages: - javascript - typescript - python - php enabled: true patterns: - regex: "app\\.(get|post)\\s*\\([\"']/api/(user|account|payment|auth)[^\"']*[\"'](?!.*Cache-Control|.*no-store)" flags: gi - regex: "res\\.json\\([^)]*password[^)]*\\)(?!.*no-cache|.*no-store)" flags: gi fix: template: | Add proper Cache-Control headers for sensitive data. Before: app.get('/api/user/profile', (req, res) => { res.json({ user: userData }); }); After: app.get('/api/user/profile', (req, res) => { res.setHeader('Cache-Control', 'no-store, no-cache, must-revalidate, private'); res.setHeader('Pragma', 'no-cache'); res.setHeader('Expires', '0'); res.json({ user: userData }); }); references: - https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control - https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/04-Authentication_Testing/06-Testing_for_Browser_Cache_Weaknesses metadata: cwe: CWE-524 owasp: "A04:2021" tags: - headers - cache-control - sensitive-data