- YAML 규칙 파일 4개 신규 생성 (html_css, accessibility, seo, performance_security) W3C, WCAG 2.0/2.1/2.2, OWASP, Google Search Essentials 공식 표준 기반 - rules/__init__.py: YAML 로더 + 캐싱 + 리로드 모듈 - html_css.py: 30개 폐기 요소, 100+개 폐기 속성을 YAML에서 동적 로드 - accessibility.py: WCAG 버전 선택 지원 (wcag_version 파라미터) - seo.py: title/description 길이, OG 필수 태그 등 임계값 YAML 로드 - performance_security.py: COOP/COEP/CORP 검사 추가, 정보 노출 헤더 검사 추가, TTFB/페이지 크기 임계값 YAML 로드 - PyYAML 의존성 추가 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
731 lines
26 KiB
YAML
731 lines
26 KiB
YAML
# ============================================================
|
|
# Performance & Security Rules
|
|
# Based on: Core Web Vitals, Lighthouse, OWASP, Mozilla Observatory
|
|
# ============================================================
|
|
|
|
metadata:
|
|
name: "Performance & Security Standards"
|
|
version: "1.0.0"
|
|
last_updated: "2026-02-13"
|
|
sources:
|
|
- name: "Google Core Web Vitals"
|
|
url: "https://developers.google.com/search/docs/appearance/core-web-vitals"
|
|
- name: "Lighthouse Performance Audits"
|
|
url: "https://developer.chrome.com/docs/lighthouse/performance/"
|
|
- name: "OWASP Secure Headers Project"
|
|
url: "https://owasp.org/www-project-secure-headers/"
|
|
- name: "OWASP HTTP Headers Cheat Sheet"
|
|
url: "https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html"
|
|
- name: "Mozilla Observatory"
|
|
url: "https://observatory.mozilla.org/"
|
|
- name: "OWASP Top 10 (2021)"
|
|
url: "https://owasp.org/www-project-top-ten/"
|
|
|
|
# ============================================================
|
|
# PERFORMANCE RULES
|
|
# ============================================================
|
|
|
|
performance:
|
|
# --- Core Web Vitals ---
|
|
core_web_vitals:
|
|
- id: "perf-lcp"
|
|
name: "Largest Contentful Paint (LCP)"
|
|
description: "Measures loading performance - time to render the largest content element"
|
|
severity: "critical"
|
|
category: "loading"
|
|
standard: "Google Core Web Vitals"
|
|
thresholds:
|
|
good: 2500 # ms
|
|
needs_improvement: 4000
|
|
poor: 4001 # above this
|
|
unit: "milliseconds"
|
|
tips:
|
|
- "Optimize and compress images (WebP/AVIF format)"
|
|
- "Preload critical resources"
|
|
- "Remove render-blocking resources"
|
|
- "Use a CDN for static assets"
|
|
- "Optimize server response time (TTFB < 800ms)"
|
|
|
|
- id: "perf-inp"
|
|
name: "Interaction to Next Paint (INP)"
|
|
description: "Measures responsiveness - latency of all user interactions"
|
|
severity: "critical"
|
|
category: "interactivity"
|
|
standard: "Google Core Web Vitals"
|
|
note: "Replaced FID (First Input Delay) in March 2024"
|
|
thresholds:
|
|
good: 200 # ms
|
|
needs_improvement: 500
|
|
poor: 501
|
|
unit: "milliseconds"
|
|
tips:
|
|
- "Break up long tasks (> 50ms)"
|
|
- "Reduce JavaScript execution time"
|
|
- "Use web workers for heavy computation"
|
|
- "Minimize main thread work"
|
|
- "Optimize event handlers"
|
|
|
|
- id: "perf-cls"
|
|
name: "Cumulative Layout Shift (CLS)"
|
|
description: "Measures visual stability - unexpected layout shifts during page life"
|
|
severity: "critical"
|
|
category: "visual_stability"
|
|
standard: "Google Core Web Vitals"
|
|
thresholds:
|
|
good: 0.1
|
|
needs_improvement: 0.25
|
|
poor: 0.26
|
|
unit: "score"
|
|
tips:
|
|
- "Set explicit width/height on images and video"
|
|
- "Reserve space for ads and embeds"
|
|
- "Avoid inserting content above existing content"
|
|
- "Use CSS contain for dynamic content"
|
|
- "Preload web fonts and use font-display: swap"
|
|
|
|
# --- Additional Performance Metrics ---
|
|
additional_metrics:
|
|
- id: "perf-fcp"
|
|
name: "First Contentful Paint (FCP)"
|
|
description: "Time to render the first piece of DOM content"
|
|
severity: "major"
|
|
category: "loading"
|
|
standard: "Lighthouse"
|
|
thresholds:
|
|
good: 1800 # ms
|
|
needs_improvement: 3000
|
|
poor: 3001
|
|
unit: "milliseconds"
|
|
|
|
- id: "perf-ttfb"
|
|
name: "Time to First Byte (TTFB)"
|
|
description: "Time from request to first byte of response"
|
|
severity: "major"
|
|
category: "server"
|
|
standard: "Lighthouse"
|
|
thresholds:
|
|
good: 800 # ms
|
|
needs_improvement: 1800
|
|
poor: 1801
|
|
unit: "milliseconds"
|
|
tips:
|
|
- "Use a CDN"
|
|
- "Optimize server-side rendering"
|
|
- "Enable HTTP/2 or HTTP/3"
|
|
- "Optimize database queries"
|
|
|
|
- id: "perf-si"
|
|
name: "Speed Index"
|
|
description: "How quickly content is visually displayed during page load"
|
|
severity: "major"
|
|
category: "loading"
|
|
standard: "Lighthouse"
|
|
thresholds:
|
|
good: 3400 # ms
|
|
needs_improvement: 5800
|
|
poor: 5801
|
|
unit: "milliseconds"
|
|
|
|
- id: "perf-tbt"
|
|
name: "Total Blocking Time (TBT)"
|
|
description: "Total time where main thread was blocked for > 50ms between FCP and TTI"
|
|
severity: "major"
|
|
category: "interactivity"
|
|
standard: "Lighthouse"
|
|
thresholds:
|
|
good: 200 # ms
|
|
needs_improvement: 600
|
|
poor: 601
|
|
unit: "milliseconds"
|
|
|
|
# --- Resource Optimization ---
|
|
resource_checks:
|
|
- id: "perf-total-page-size"
|
|
name: "Total Page Size"
|
|
description: "Total size of all resources loaded by the page"
|
|
severity: "major"
|
|
category: "resources"
|
|
standard: "Web Performance Best Practice"
|
|
thresholds:
|
|
good: 1500 # KB
|
|
needs_improvement: 3000
|
|
poor: 5000
|
|
unit: "kilobytes"
|
|
|
|
- id: "perf-total-requests"
|
|
name: "Total HTTP Requests"
|
|
description: "Total number of HTTP requests made by the page"
|
|
severity: "major"
|
|
category: "resources"
|
|
standard: "Web Performance Best Practice"
|
|
thresholds:
|
|
good: 50
|
|
needs_improvement: 80
|
|
poor: 100
|
|
unit: "count"
|
|
|
|
- id: "perf-image-optimization"
|
|
name: "Image Optimization"
|
|
description: "Images should be properly optimized"
|
|
severity: "major"
|
|
category: "resources"
|
|
standard: "Lighthouse"
|
|
checks:
|
|
- id: "uses-webp-avif"
|
|
description: "Use modern image formats (WebP, AVIF)"
|
|
severity: "minor"
|
|
- id: "responsive-images"
|
|
description: "Use srcset for responsive images"
|
|
severity: "minor"
|
|
- id: "lazy-loading"
|
|
description: "Offscreen images should use lazy loading"
|
|
severity: "minor"
|
|
- id: "image-dimensions"
|
|
description: "Images should have explicit width and height"
|
|
severity: "major"
|
|
- id: "oversized-images"
|
|
description: "Images should not be larger than their display size"
|
|
severity: "minor"
|
|
|
|
- id: "perf-js-optimization"
|
|
name: "JavaScript Optimization"
|
|
description: "JavaScript should be properly optimized"
|
|
severity: "major"
|
|
category: "resources"
|
|
standard: "Lighthouse"
|
|
checks:
|
|
- id: "minified-js"
|
|
description: "JavaScript should be minified"
|
|
severity: "minor"
|
|
- id: "no-render-blocking-js"
|
|
description: "Non-critical JS should use async or defer"
|
|
severity: "major"
|
|
- id: "unused-js"
|
|
description: "Remove unused JavaScript"
|
|
severity: "minor"
|
|
- id: "js-bundle-size"
|
|
description: "Individual JS bundles should be under 250KB (compressed)"
|
|
max_size_kb: 250
|
|
severity: "major"
|
|
|
|
- id: "perf-css-optimization"
|
|
name: "CSS Optimization"
|
|
description: "CSS should be properly optimized"
|
|
severity: "minor"
|
|
category: "resources"
|
|
standard: "Lighthouse"
|
|
checks:
|
|
- id: "minified-css"
|
|
description: "CSS should be minified"
|
|
severity: "minor"
|
|
- id: "no-render-blocking-css"
|
|
description: "Non-critical CSS should be deferred"
|
|
severity: "major"
|
|
- id: "unused-css"
|
|
description: "Remove unused CSS rules"
|
|
severity: "minor"
|
|
- id: "critical-css-inlined"
|
|
description: "Critical CSS should be inlined"
|
|
severity: "info"
|
|
|
|
- id: "perf-font-optimization"
|
|
name: "Font Optimization"
|
|
description: "Web fonts should be properly optimized"
|
|
severity: "minor"
|
|
category: "resources"
|
|
standard: "Web Performance Best Practice"
|
|
checks:
|
|
- id: "font-display"
|
|
description: "Use font-display: swap or optional"
|
|
severity: "minor"
|
|
- id: "preload-fonts"
|
|
description: "Preload critical fonts"
|
|
severity: "minor"
|
|
- id: "font-subsetting"
|
|
description: "Use font subsetting for CJK fonts"
|
|
severity: "info"
|
|
- id: "woff2-format"
|
|
description: "Use WOFF2 format for web fonts"
|
|
severity: "minor"
|
|
|
|
# --- Caching & Compression ---
|
|
caching:
|
|
- id: "perf-compression"
|
|
name: "Text Compression"
|
|
description: "Text resources should be served with compression"
|
|
severity: "major"
|
|
category: "network"
|
|
standard: "Lighthouse"
|
|
details:
|
|
supported_encodings:
|
|
- "gzip"
|
|
- "br (Brotli - preferred)"
|
|
- "zstd"
|
|
applies_to:
|
|
- "text/html"
|
|
- "text/css"
|
|
- "application/javascript"
|
|
- "application/json"
|
|
- "image/svg+xml"
|
|
|
|
- id: "perf-cache-headers"
|
|
name: "Cache Headers"
|
|
description: "Static resources should have proper cache headers"
|
|
severity: "major"
|
|
category: "network"
|
|
standard: "HTTP Caching (RFC 7234)"
|
|
details:
|
|
checks:
|
|
- id: "has-cache-control"
|
|
description: "Static assets should have Cache-Control header"
|
|
- id: "long-cache-lifetime"
|
|
description: "Static assets should have cache lifetime >= 1 year"
|
|
recommended: "Cache-Control: public, max-age=31536000, immutable"
|
|
- id: "etag"
|
|
description: "Resources should have ETag for validation"
|
|
|
|
- id: "perf-http2"
|
|
name: "HTTP/2 or HTTP/3"
|
|
description: "Site should use HTTP/2 or HTTP/3 protocol"
|
|
severity: "minor"
|
|
category: "network"
|
|
standard: "IETF RFC 9113 (HTTP/2), RFC 9114 (HTTP/3)"
|
|
details:
|
|
description: "HTTP/2+ provides multiplexing, header compression, and server push"
|
|
|
|
# ============================================================
|
|
# SECURITY RULES
|
|
# ============================================================
|
|
|
|
security:
|
|
# --- HTTP Security Headers (OWASP) ---
|
|
headers:
|
|
- id: "sec-strict-transport-security"
|
|
name: "Strict-Transport-Security (HSTS)"
|
|
description: "Enforces HTTPS-only access to prevent protocol downgrade attacks"
|
|
severity: "critical"
|
|
category: "transport"
|
|
standard: "OWASP Secure Headers Project"
|
|
standard_ref: "RFC 6797"
|
|
check_type: "header_check"
|
|
details:
|
|
header: "Strict-Transport-Security"
|
|
recommended_value: "max-age=63072000; includeSubDomains; preload"
|
|
directives:
|
|
- name: "max-age"
|
|
description: "Time in seconds browser should remember HTTPS-only"
|
|
recommended: 63072000 # 2 years
|
|
minimum: 31536000 # 1 year
|
|
- name: "includeSubDomains"
|
|
description: "Apply to all subdomains"
|
|
recommended: true
|
|
- name: "preload"
|
|
description: "Allow inclusion in browser HSTS preload list"
|
|
recommended: true
|
|
note: "Only effective over HTTPS connections"
|
|
|
|
- id: "sec-content-security-policy"
|
|
name: "Content-Security-Policy (CSP)"
|
|
description: "Restricts content origins to prevent XSS and injection attacks"
|
|
severity: "critical"
|
|
category: "injection"
|
|
standard: "OWASP Secure Headers Project"
|
|
standard_ref: "W3C CSP Level 3"
|
|
check_type: "header_check"
|
|
details:
|
|
header: "Content-Security-Policy"
|
|
recommended_directives:
|
|
- directive: "default-src"
|
|
description: "Fallback for other directives"
|
|
recommended: "'self'"
|
|
- directive: "script-src"
|
|
description: "Valid sources for JavaScript"
|
|
recommended: "'self'"
|
|
avoid: "'unsafe-inline', 'unsafe-eval'"
|
|
- directive: "style-src"
|
|
description: "Valid sources for stylesheets"
|
|
recommended: "'self'"
|
|
- directive: "img-src"
|
|
description: "Valid sources for images"
|
|
recommended: "'self' data:"
|
|
- directive: "font-src"
|
|
description: "Valid sources for fonts"
|
|
recommended: "'self'"
|
|
- directive: "connect-src"
|
|
description: "Valid targets for XMLHttpRequest, Fetch, WebSocket"
|
|
recommended: "'self'"
|
|
- directive: "frame-ancestors"
|
|
description: "Valid parents for embedding (replaces X-Frame-Options)"
|
|
recommended: "'none'"
|
|
- directive: "base-uri"
|
|
description: "Restricts URLs for base element"
|
|
recommended: "'self'"
|
|
- directive: "form-action"
|
|
description: "Restricts form submission targets"
|
|
recommended: "'self'"
|
|
- directive: "object-src"
|
|
description: "Valid sources for plugins"
|
|
recommended: "'none'"
|
|
- directive: "upgrade-insecure-requests"
|
|
description: "Upgrade HTTP requests to HTTPS"
|
|
recommended: true
|
|
|
|
- id: "sec-x-frame-options"
|
|
name: "X-Frame-Options"
|
|
description: "Prevents page from being displayed in frames (clickjacking protection)"
|
|
severity: "critical"
|
|
category: "clickjacking"
|
|
standard: "OWASP Secure Headers Project"
|
|
standard_ref: "RFC 7034"
|
|
check_type: "header_check"
|
|
details:
|
|
header: "X-Frame-Options"
|
|
recommended_value: "DENY"
|
|
valid_values:
|
|
- value: "DENY"
|
|
description: "Page cannot be displayed in any frame"
|
|
- value: "SAMEORIGIN"
|
|
description: "Page can only be displayed in frame on same origin"
|
|
note: "CSP frame-ancestors is the modern replacement"
|
|
|
|
- id: "sec-x-content-type-options"
|
|
name: "X-Content-Type-Options"
|
|
description: "Prevents MIME type sniffing attacks"
|
|
severity: "major"
|
|
category: "injection"
|
|
standard: "OWASP Secure Headers Project"
|
|
check_type: "header_check"
|
|
details:
|
|
header: "X-Content-Type-Options"
|
|
recommended_value: "nosniff"
|
|
description: "Blocks browsers from guessing MIME types, preventing XSS via MIME confusion"
|
|
|
|
- id: "sec-referrer-policy"
|
|
name: "Referrer-Policy"
|
|
description: "Controls referrer information sent with requests"
|
|
severity: "major"
|
|
category: "privacy"
|
|
standard: "OWASP Secure Headers Project"
|
|
standard_ref: "W3C Referrer Policy"
|
|
check_type: "header_check"
|
|
details:
|
|
header: "Referrer-Policy"
|
|
recommended_value: "strict-origin-when-cross-origin"
|
|
valid_values:
|
|
- value: "no-referrer"
|
|
description: "Never send referrer"
|
|
security: "highest"
|
|
- value: "no-referrer-when-downgrade"
|
|
description: "Don't send referrer on HTTPS → HTTP"
|
|
security: "medium"
|
|
- value: "origin"
|
|
description: "Only send the origin"
|
|
security: "high"
|
|
- value: "origin-when-cross-origin"
|
|
description: "Full URL for same-origin, origin for cross-origin"
|
|
security: "medium"
|
|
- value: "same-origin"
|
|
description: "Only send referrer for same-origin requests"
|
|
security: "high"
|
|
- value: "strict-origin"
|
|
description: "Send origin when protocol stays same"
|
|
security: "high"
|
|
- value: "strict-origin-when-cross-origin"
|
|
description: "Full URL for same-origin, origin for cross-origin (same protocol)"
|
|
security: "medium-high"
|
|
- value: "unsafe-url"
|
|
description: "Always send full URL"
|
|
security: "none"
|
|
|
|
- id: "sec-permissions-policy"
|
|
name: "Permissions-Policy"
|
|
description: "Controls browser feature access (geolocation, camera, etc.)"
|
|
severity: "major"
|
|
category: "privacy"
|
|
standard: "OWASP Secure Headers Project"
|
|
standard_ref: "W3C Permissions Policy"
|
|
check_type: "header_check"
|
|
details:
|
|
header: "Permissions-Policy"
|
|
recommended_value: "geolocation=(), camera=(), microphone=(), payment=(), usb=(), magnetometer=(), gyroscope=(), accelerometer=()"
|
|
controllable_features:
|
|
- feature: "geolocation"
|
|
description: "Access to user's location"
|
|
default_recommendation: "()" # deny all
|
|
- feature: "camera"
|
|
description: "Access to device camera"
|
|
default_recommendation: "()"
|
|
- feature: "microphone"
|
|
description: "Access to device microphone"
|
|
default_recommendation: "()"
|
|
- feature: "payment"
|
|
description: "Payment Request API"
|
|
default_recommendation: "()"
|
|
- feature: "usb"
|
|
description: "WebUSB API"
|
|
default_recommendation: "()"
|
|
- feature: "magnetometer"
|
|
description: "Magnetometer sensor"
|
|
default_recommendation: "()"
|
|
- feature: "gyroscope"
|
|
description: "Gyroscope sensor"
|
|
default_recommendation: "()"
|
|
- feature: "accelerometer"
|
|
description: "Accelerometer sensor"
|
|
default_recommendation: "()"
|
|
- feature: "autoplay"
|
|
description: "Auto-play media"
|
|
default_recommendation: "(self)"
|
|
- feature: "fullscreen"
|
|
description: "Fullscreen API"
|
|
default_recommendation: "(self)"
|
|
- feature: "interest-cohort"
|
|
description: "FLoC / Topics API (ad tracking)"
|
|
default_recommendation: "()"
|
|
|
|
- id: "sec-cross-origin-opener-policy"
|
|
name: "Cross-Origin-Opener-Policy (COOP)"
|
|
description: "Isolates browsing context to prevent Spectre-type attacks"
|
|
severity: "minor"
|
|
category: "isolation"
|
|
standard: "OWASP Secure Headers Project"
|
|
check_type: "header_check"
|
|
details:
|
|
header: "Cross-Origin-Opener-Policy"
|
|
recommended_value: "same-origin"
|
|
valid_values:
|
|
- "unsafe-none"
|
|
- "same-origin-allow-popups"
|
|
- "same-origin"
|
|
|
|
- id: "sec-cross-origin-embedder-policy"
|
|
name: "Cross-Origin-Embedder-Policy (COEP)"
|
|
description: "Restricts cross-origin resource loading"
|
|
severity: "minor"
|
|
category: "isolation"
|
|
standard: "OWASP Secure Headers Project"
|
|
check_type: "header_check"
|
|
details:
|
|
header: "Cross-Origin-Embedder-Policy"
|
|
recommended_value: "require-corp"
|
|
valid_values:
|
|
- "unsafe-none"
|
|
- "require-corp"
|
|
- "credentialless"
|
|
|
|
- id: "sec-cross-origin-resource-policy"
|
|
name: "Cross-Origin-Resource-Policy (CORP)"
|
|
description: "Blocks resource loading from unauthorized origins"
|
|
severity: "minor"
|
|
category: "isolation"
|
|
standard: "OWASP Secure Headers Project"
|
|
check_type: "header_check"
|
|
details:
|
|
header: "Cross-Origin-Resource-Policy"
|
|
recommended_value: "same-site"
|
|
valid_values:
|
|
- "same-site"
|
|
- "same-origin"
|
|
- "cross-origin"
|
|
|
|
# --- Headers to Remove (Information Disclosure) ---
|
|
headers_to_remove:
|
|
- id: "sec-remove-server"
|
|
name: "Remove Server Header"
|
|
description: "Server header exposes web server technology"
|
|
severity: "minor"
|
|
category: "information_disclosure"
|
|
standard: "OWASP Secure Headers Project"
|
|
details:
|
|
header: "Server"
|
|
action: "Remove or set to non-informative value"
|
|
reason: "Prevents fingerprinting of web server software"
|
|
|
|
- id: "sec-remove-x-powered-by"
|
|
name: "Remove X-Powered-By Header"
|
|
description: "X-Powered-By exposes application framework"
|
|
severity: "minor"
|
|
category: "information_disclosure"
|
|
standard: "OWASP Secure Headers Project"
|
|
details:
|
|
header: "X-Powered-By"
|
|
action: "Remove entirely"
|
|
reason: "Prevents fingerprinting of application framework (Express, PHP, ASP.NET)"
|
|
|
|
- id: "sec-remove-x-aspnet-version"
|
|
name: "Remove X-AspNet-Version Header"
|
|
description: "Exposes .NET framework version"
|
|
severity: "minor"
|
|
category: "information_disclosure"
|
|
standard: "OWASP Secure Headers Project"
|
|
details:
|
|
header: "X-AspNet-Version"
|
|
action: "Remove entirely"
|
|
|
|
- id: "sec-remove-x-aspnetmvc-version"
|
|
name: "Remove X-AspNetMvc-Version Header"
|
|
description: "Exposes ASP.NET MVC version"
|
|
severity: "minor"
|
|
category: "information_disclosure"
|
|
standard: "OWASP Secure Headers Project"
|
|
details:
|
|
header: "X-AspNetMvc-Version"
|
|
action: "Remove entirely"
|
|
|
|
# --- Deprecated Headers ---
|
|
deprecated_headers:
|
|
- id: "sec-no-x-xss-protection"
|
|
name: "X-XSS-Protection (Deprecated)"
|
|
description: "Legacy XSS filter - should be disabled in favor of CSP"
|
|
severity: "info"
|
|
category: "legacy"
|
|
standard: "OWASP Secure Headers Project"
|
|
details:
|
|
header: "X-XSS-Protection"
|
|
recommended_value: "0"
|
|
reason: "Modern browsers have removed XSS auditor; use CSP instead"
|
|
note: "Setting to 1; mode=block can introduce vulnerabilities in older browsers"
|
|
|
|
- id: "sec-no-public-key-pins"
|
|
name: "Public-Key-Pins (HPKP) - Removed"
|
|
description: "HTTP Public Key Pinning is deprecated and should not be used"
|
|
severity: "info"
|
|
category: "legacy"
|
|
standard: "OWASP Secure Headers Project"
|
|
details:
|
|
header: "Public-Key-Pins"
|
|
action: "Do not use"
|
|
reason: "Risk of permanent site lockout; replaced by Certificate Transparency"
|
|
|
|
# --- Transport Security ---
|
|
transport:
|
|
- id: "sec-https"
|
|
name: "HTTPS Enforcement"
|
|
description: "Site must be served over HTTPS"
|
|
severity: "critical"
|
|
category: "transport"
|
|
standard: "OWASP / Google"
|
|
checks:
|
|
- id: "uses-https"
|
|
description: "Page is served over HTTPS"
|
|
severity: "critical"
|
|
- id: "no-mixed-content"
|
|
description: "No HTTP resources loaded on HTTPS page"
|
|
severity: "critical"
|
|
- id: "http-redirects-to-https"
|
|
description: "HTTP requests redirect to HTTPS"
|
|
severity: "major"
|
|
- id: "valid-certificate"
|
|
description: "SSL/TLS certificate is valid and not expired"
|
|
severity: "critical"
|
|
- id: "strong-tls-version"
|
|
description: "Uses TLS 1.2 or higher"
|
|
severity: "major"
|
|
details:
|
|
minimum_version: "TLS 1.2"
|
|
recommended_version: "TLS 1.3"
|
|
deprecated_versions:
|
|
- "SSL 2.0"
|
|
- "SSL 3.0"
|
|
- "TLS 1.0"
|
|
- "TLS 1.1"
|
|
|
|
# --- Cookie Security ---
|
|
cookies:
|
|
- id: "sec-cookie-secure"
|
|
name: "Secure Cookie Flag"
|
|
description: "Cookies should have Secure flag over HTTPS"
|
|
severity: "major"
|
|
category: "cookies"
|
|
standard: "OWASP Session Management"
|
|
details:
|
|
flag: "Secure"
|
|
description: "Cookie only sent over HTTPS connections"
|
|
|
|
- id: "sec-cookie-httponly"
|
|
name: "HttpOnly Cookie Flag"
|
|
description: "Session cookies should have HttpOnly flag"
|
|
severity: "major"
|
|
category: "cookies"
|
|
standard: "OWASP Session Management"
|
|
details:
|
|
flag: "HttpOnly"
|
|
description: "Cookie not accessible via JavaScript (prevents XSS theft)"
|
|
|
|
- id: "sec-cookie-samesite"
|
|
name: "SameSite Cookie Attribute"
|
|
description: "Cookies should have SameSite attribute"
|
|
severity: "major"
|
|
category: "cookies"
|
|
standard: "OWASP Session Management"
|
|
details:
|
|
attribute: "SameSite"
|
|
recommended_value: "Lax"
|
|
valid_values:
|
|
- value: "Strict"
|
|
description: "Cookie not sent in any cross-site request"
|
|
- value: "Lax"
|
|
description: "Cookie sent in top-level navigations (recommended default)"
|
|
- value: "None"
|
|
description: "Cookie sent in all contexts (requires Secure flag)"
|
|
|
|
# --- Content Security ---
|
|
content:
|
|
- id: "sec-subresource-integrity"
|
|
name: "Subresource Integrity (SRI)"
|
|
description: "External scripts/styles should use integrity attribute"
|
|
severity: "minor"
|
|
category: "supply_chain"
|
|
standard: "W3C Subresource Integrity"
|
|
check_type: "attribute_check"
|
|
details:
|
|
applies_to:
|
|
- "script[src] from CDN"
|
|
- "link[rel=stylesheet] from CDN"
|
|
attribute: "integrity"
|
|
description: "Hash-based verification of external resources"
|
|
|
|
- id: "sec-form-action-https"
|
|
name: "Form Action HTTPS"
|
|
description: "Form actions should use HTTPS"
|
|
severity: "major"
|
|
category: "transport"
|
|
standard: "OWASP"
|
|
check_type: "form_check"
|
|
details:
|
|
description: "Form submissions should always go to HTTPS endpoints"
|
|
|
|
- id: "sec-target-blank-rel"
|
|
name: "Target Blank Security"
|
|
description: "Links with target=_blank should have rel=noopener"
|
|
severity: "minor"
|
|
category: "injection"
|
|
standard: "Web Security Best Practice"
|
|
check_type: "link_check"
|
|
details:
|
|
description: "Prevents tab-napping attacks via window.opener"
|
|
recommended: 'rel="noopener noreferrer"'
|
|
note: "Modern browsers set noopener by default, but explicit is safer"
|
|
|
|
- id: "sec-no-inline-event-handlers"
|
|
name: "No Inline Event Handlers"
|
|
description: "Avoid inline event handlers (onclick, onload, etc.)"
|
|
severity: "minor"
|
|
category: "injection"
|
|
standard: "OWASP / CSP"
|
|
check_type: "attribute_check"
|
|
details:
|
|
description: "Inline event handlers are incompatible with strict CSP"
|
|
blocked_attributes:
|
|
- "onclick"
|
|
- "onload"
|
|
- "onerror"
|
|
- "onmouseover"
|
|
- "onsubmit"
|
|
- "onfocus"
|
|
- "onblur"
|
|
- "onchange"
|
|
- "onkeydown"
|
|
- "onkeyup"
|
|
- "onkeypress"
|