feat: add unified code quality dashboard with multiple validators
- Add validator_type field to scans and violations (architecture, security, performance) - Create security validator with SEC-xxx rules - Create performance validator with PERF-xxx rules - Add base validator class for shared functionality - Add validate_all.py script to run all validators - Update code quality service with validator type filtering - Add validator type tabs to dashboard UI - Add validator type filter to violations list - Update stats response with per-validator breakdown - Add security and performance rules documentation - Add chat-bubble icons to icon library 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
560
docs/development/security-rules.md
Normal file
560
docs/development/security-rules.md
Normal file
@@ -0,0 +1,560 @@
|
||||
# Security Rules Reference
|
||||
|
||||
This document provides a comprehensive reference for all security rules enforced by the `scripts/validate_security.py` validator.
|
||||
|
||||
## Overview
|
||||
|
||||
The security validator identifies potential security vulnerabilities and enforces security best practices across the codebase. Rules are organized by category and severity level.
|
||||
|
||||
**Version:** 1.0
|
||||
**Total Rules:** 60
|
||||
**Configuration Directory:** `.security-rules/`
|
||||
|
||||
## Running the Validator
|
||||
|
||||
### Using Python Directly
|
||||
|
||||
```bash
|
||||
# Check all files
|
||||
python scripts/validate_security.py
|
||||
|
||||
# Verbose output
|
||||
python scripts/validate_security.py -v
|
||||
|
||||
# Errors only
|
||||
python scripts/validate_security.py --errors-only
|
||||
|
||||
# JSON output (for CI/CD)
|
||||
python scripts/validate_security.py --json
|
||||
```
|
||||
|
||||
### Using the Unified Validator
|
||||
|
||||
```bash
|
||||
# Run security checks only
|
||||
python scripts/validate_all.py --security
|
||||
|
||||
# Run all validators
|
||||
python scripts/validate_all.py
|
||||
```
|
||||
|
||||
## Severity Levels
|
||||
|
||||
| Severity | Description | Exit Code | Action Required |
|
||||
|----------|-------------|-----------|-----------------|
|
||||
| **Error** | Critical security vulnerability | 1 | Must fix immediately |
|
||||
| **Warning** | Security concern | 0 | Should fix |
|
||||
| **Info** | Security suggestion | 0 | Consider implementing |
|
||||
|
||||
---
|
||||
|
||||
## Authentication Rules (SEC-001 to SEC-010)
|
||||
|
||||
### SEC-001: No Hardcoded Credentials
|
||||
**Severity:** Error
|
||||
|
||||
Credentials must never be hardcoded in source code. Use environment variables or secret management.
|
||||
|
||||
```python
|
||||
# Bad
|
||||
api_key = "sk-1234567890abcdef"
|
||||
password = "admin123"
|
||||
|
||||
# Good
|
||||
api_key = os.environ.get("API_KEY")
|
||||
password = settings.admin_password
|
||||
```
|
||||
|
||||
### SEC-002: JWT Expiry Enforcement
|
||||
**Severity:** Error
|
||||
|
||||
All JWT tokens must have expiration claims. Access tokens should expire in 15-60 minutes.
|
||||
|
||||
### SEC-003: Password Hashing Required
|
||||
**Severity:** Error
|
||||
|
||||
Passwords must be hashed using bcrypt, argon2, or scrypt. Never store or compare passwords in plain text.
|
||||
|
||||
```python
|
||||
# Bad
|
||||
if user.password == password:
|
||||
...
|
||||
|
||||
# Good
|
||||
if bcrypt.checkpw(password.encode(), user.hashed_password):
|
||||
...
|
||||
```
|
||||
|
||||
### SEC-004: Session Regeneration After Auth
|
||||
**Severity:** Warning
|
||||
|
||||
Session IDs should be regenerated after authentication to prevent session fixation attacks.
|
||||
|
||||
### SEC-005: Brute Force Protection
|
||||
**Severity:** Warning
|
||||
|
||||
Login endpoints should implement rate limiting or account lockout after failed attempts.
|
||||
|
||||
### SEC-006: Secure Password Reset
|
||||
**Severity:** Warning
|
||||
|
||||
Password reset tokens must be cryptographically random, expire within 1 hour, and be single-use.
|
||||
|
||||
### SEC-007: Authentication on Sensitive Endpoints
|
||||
**Severity:** Error
|
||||
|
||||
All endpoints except public ones must require authentication.
|
||||
|
||||
### SEC-008: Token in Authorization Header
|
||||
**Severity:** Warning
|
||||
|
||||
JWT tokens should be sent in Authorization header, not in URL parameters.
|
||||
|
||||
### SEC-009: Logout Invalidates Tokens
|
||||
**Severity:** Warning
|
||||
|
||||
Logout should invalidate or blacklist tokens.
|
||||
|
||||
### SEC-010: Multi-Factor Authentication Support
|
||||
**Severity:** Info
|
||||
|
||||
Consider implementing MFA for sensitive operations.
|
||||
|
||||
---
|
||||
|
||||
## Injection Prevention Rules (SEC-011 to SEC-020)
|
||||
|
||||
### SEC-011: No Raw SQL Queries
|
||||
**Severity:** Error
|
||||
|
||||
Use SQLAlchemy ORM or parameterized queries only. Never concatenate user input into SQL strings.
|
||||
|
||||
```python
|
||||
# Bad
|
||||
db.execute(f"SELECT * FROM users WHERE name = '{name}'")
|
||||
|
||||
# Good
|
||||
db.query(User).filter(User.name == name)
|
||||
```
|
||||
|
||||
### SEC-012: No Shell Command Injection
|
||||
**Severity:** Error
|
||||
|
||||
Never use `shell=True` with subprocess. Use subprocess with list arguments.
|
||||
|
||||
```python
|
||||
# Bad
|
||||
subprocess.run(f"convert {filename}", shell=True)
|
||||
os.system(f"rm {filename}")
|
||||
|
||||
# Good
|
||||
subprocess.run(["convert", filename])
|
||||
```
|
||||
|
||||
### SEC-013: No Code Execution
|
||||
**Severity:** Error
|
||||
|
||||
Never use `eval()` or `exec()` with user input.
|
||||
|
||||
### SEC-014: Path Traversal Prevention
|
||||
**Severity:** Error
|
||||
|
||||
Validate file paths to prevent directory traversal. Use `secure_filename()` for uploads.
|
||||
|
||||
```python
|
||||
# Bad
|
||||
path = f"/uploads/{filename}"
|
||||
|
||||
# Good
|
||||
from werkzeug.utils import secure_filename
|
||||
path = f"/uploads/{secure_filename(filename)}"
|
||||
```
|
||||
|
||||
### SEC-015: XSS Prevention in Templates
|
||||
**Severity:** Error
|
||||
|
||||
Use safe output methods in templates. Prefer `x-text` over `x-html` in Alpine.js.
|
||||
|
||||
```html
|
||||
<!-- Bad - vulnerable to XSS -->
|
||||
<div x-html="userInput"></div>
|
||||
|
||||
<!-- Good - safe from XSS -->
|
||||
<div x-text="userInput"></div>
|
||||
```
|
||||
|
||||
### SEC-016: LDAP Injection Prevention
|
||||
**Severity:** Error
|
||||
|
||||
Escape special characters in LDAP queries.
|
||||
|
||||
### SEC-017: XML External Entity Prevention
|
||||
**Severity:** Error
|
||||
|
||||
Disable external entities when parsing XML. Use `defusedxml`.
|
||||
|
||||
```python
|
||||
# Bad
|
||||
import xml.etree.ElementTree as ET
|
||||
tree = ET.parse(user_file)
|
||||
|
||||
# Good
|
||||
import defusedxml.ElementTree as ET
|
||||
tree = ET.parse(user_file)
|
||||
```
|
||||
|
||||
### SEC-018: Template Injection Prevention
|
||||
**Severity:** Error
|
||||
|
||||
Never render user input as template code.
|
||||
|
||||
### SEC-019: SSRF Prevention
|
||||
**Severity:** Warning
|
||||
|
||||
Validate URLs before making external requests. Whitelist allowed domains.
|
||||
|
||||
### SEC-020: Deserialization Safety
|
||||
**Severity:** Error
|
||||
|
||||
Never deserialize untrusted data with pickle. Use `yaml.safe_load()` instead of `yaml.load()`.
|
||||
|
||||
```python
|
||||
# Bad
|
||||
data = pickle.loads(user_data)
|
||||
config = yaml.load(user_config)
|
||||
|
||||
# Good
|
||||
config = yaml.safe_load(user_config)
|
||||
data = json.loads(user_data)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Data Protection Rules (SEC-021 to SEC-030)
|
||||
|
||||
### SEC-021: PII Logging Prevention
|
||||
**Severity:** Error
|
||||
|
||||
Never log passwords, tokens, credit cards, or sensitive PII.
|
||||
|
||||
```python
|
||||
# Bad
|
||||
logger.info(f"User login: {username}, password: {password}")
|
||||
|
||||
# Good
|
||||
logger.info(f"User login: {username}")
|
||||
```
|
||||
|
||||
### SEC-022: Sensitive Data in URLs
|
||||
**Severity:** Error
|
||||
|
||||
Sensitive data should not appear in URL query parameters. Use POST body or headers instead.
|
||||
|
||||
### SEC-023: Mass Assignment Prevention
|
||||
**Severity:** Warning
|
||||
|
||||
Use explicit field assignment, not `**kwargs` from user input.
|
||||
|
||||
```python
|
||||
# Bad
|
||||
user = User(**request.json)
|
||||
|
||||
# Good
|
||||
user = User(
|
||||
name=request.json.get("name"),
|
||||
email=request.json.get("email")
|
||||
)
|
||||
```
|
||||
|
||||
### SEC-024: Error Message Information Leakage
|
||||
**Severity:** Error
|
||||
|
||||
Error messages should not reveal internal details. No stack traces to users.
|
||||
|
||||
### SEC-025: Secure Cookie Settings
|
||||
**Severity:** Error
|
||||
|
||||
Cookies must have Secure, HttpOnly, SameSite attributes.
|
||||
|
||||
### SEC-026: Encryption for Sensitive Data at Rest
|
||||
**Severity:** Info
|
||||
|
||||
Consider encrypting sensitive data stored in the database.
|
||||
|
||||
### SEC-027: Data Retention Limits
|
||||
**Severity:** Info
|
||||
|
||||
Implement data retention policies.
|
||||
|
||||
### SEC-028: Response Data Filtering
|
||||
**Severity:** Warning
|
||||
|
||||
API responses should not include sensitive internal fields. Use Pydantic response models.
|
||||
|
||||
### SEC-029: File Upload Validation
|
||||
**Severity:** Error
|
||||
|
||||
Validate uploaded files by extension AND content type. Limit file size.
|
||||
|
||||
### SEC-030: Backup Encryption
|
||||
**Severity:** Info
|
||||
|
||||
Database backups should be encrypted.
|
||||
|
||||
---
|
||||
|
||||
## API Security Rules (SEC-031 to SEC-040)
|
||||
|
||||
### SEC-031: CORS Origin Validation
|
||||
**Severity:** Error
|
||||
|
||||
CORS must not allow all origins in production. Specify allowed origins explicitly.
|
||||
|
||||
```python
|
||||
# Bad
|
||||
allow_origins=["*"]
|
||||
|
||||
# Good
|
||||
allow_origins=["https://example.com", "https://api.example.com"]
|
||||
```
|
||||
|
||||
### SEC-032: Rate Limiting on Sensitive Endpoints
|
||||
**Severity:** Warning
|
||||
|
||||
Auth, password reset, and payment endpoints need rate limiting.
|
||||
|
||||
### SEC-033: Security Headers
|
||||
**Severity:** Warning
|
||||
|
||||
Configure security headers like X-Content-Type-Options, X-Frame-Options, Content-Security-Policy.
|
||||
|
||||
### SEC-034: HTTPS Enforcement
|
||||
**Severity:** Error
|
||||
|
||||
External URLs must use HTTPS. HTTP is only acceptable for localhost.
|
||||
|
||||
### SEC-035: Request Size Limits
|
||||
**Severity:** Warning
|
||||
|
||||
Limit request body size to prevent DoS attacks.
|
||||
|
||||
### SEC-036: Input Validation with Pydantic
|
||||
**Severity:** Warning
|
||||
|
||||
All API inputs should be validated using Pydantic models.
|
||||
|
||||
### SEC-037: API Versioning
|
||||
**Severity:** Info
|
||||
|
||||
APIs should be versioned for security update isolation.
|
||||
|
||||
### SEC-038: Method Restrictions
|
||||
**Severity:** Warning
|
||||
|
||||
Endpoints should only allow necessary HTTP methods.
|
||||
|
||||
### SEC-039: Authentication Bypass Prevention
|
||||
**Severity:** Error
|
||||
|
||||
Ensure authentication cannot be bypassed.
|
||||
|
||||
### SEC-040: Timeout Configuration
|
||||
**Severity:** Warning
|
||||
|
||||
All external calls must have timeouts configured.
|
||||
|
||||
---
|
||||
|
||||
## Cryptography Rules (SEC-041 to SEC-050)
|
||||
|
||||
### SEC-041: Strong Hashing Algorithms
|
||||
**Severity:** Error
|
||||
|
||||
Use bcrypt, argon2, scrypt for passwords. Use SHA-256 or stronger for general hashing. Never use MD5 or SHA1.
|
||||
|
||||
```python
|
||||
# Bad
|
||||
import hashlib
|
||||
password_hash = hashlib.md5(password.encode()).hexdigest()
|
||||
|
||||
# Good
|
||||
import bcrypt
|
||||
password_hash = bcrypt.hashpw(password.encode(), bcrypt.gensalt())
|
||||
```
|
||||
|
||||
### SEC-042: Secure Random Generation
|
||||
**Severity:** Error
|
||||
|
||||
Use the `secrets` module for security-sensitive randomness. Never use `random` module for tokens or keys.
|
||||
|
||||
```python
|
||||
# Bad
|
||||
import random
|
||||
token = ''.join(random.choices(string.ascii_letters, k=32))
|
||||
|
||||
# Good
|
||||
import secrets
|
||||
token = secrets.token_urlsafe(32)
|
||||
```
|
||||
|
||||
### SEC-043: No Hardcoded Encryption Keys
|
||||
**Severity:** Error
|
||||
|
||||
Encryption keys must come from environment variables or secret management services.
|
||||
|
||||
### SEC-044: Strong Encryption Algorithms
|
||||
**Severity:** Error
|
||||
|
||||
Use AES-256 or ChaCha20. Never use DES, 3DES, or RC4.
|
||||
|
||||
### SEC-045: Proper IV/Nonce Usage
|
||||
**Severity:** Error
|
||||
|
||||
Encryption IVs and nonces must be randomly generated and unique per encryption.
|
||||
|
||||
### SEC-046: TLS Version Requirements
|
||||
**Severity:** Warning
|
||||
|
||||
Enforce TLS 1.2 or higher. Disable SSLv2, SSLv3, TLS 1.0, TLS 1.1.
|
||||
|
||||
### SEC-047: Certificate Verification
|
||||
**Severity:** Error
|
||||
|
||||
Always verify SSL certificates. Never disable verification in production.
|
||||
|
||||
```python
|
||||
# Bad
|
||||
requests.get(url, verify=False)
|
||||
|
||||
# Good
|
||||
requests.get(url, verify=True)
|
||||
```
|
||||
|
||||
### SEC-048: Key Derivation for Passwords
|
||||
**Severity:** Warning
|
||||
|
||||
When deriving encryption keys from passwords, use PBKDF2 with 100K+ iterations, Argon2, or scrypt.
|
||||
|
||||
### SEC-049: Secure Key Storage
|
||||
**Severity:** Info
|
||||
|
||||
Encryption keys should be stored in environment variables, secret management, or HSMs.
|
||||
|
||||
### SEC-050: Key Rotation Support
|
||||
**Severity:** Info
|
||||
|
||||
Implement key rotation with multiple key versions.
|
||||
|
||||
---
|
||||
|
||||
## Audit & Logging Rules (SEC-051 to SEC-060)
|
||||
|
||||
### SEC-051: Authentication Event Logging
|
||||
**Severity:** Warning
|
||||
|
||||
Log authentication events including successful logins, failed attempts, logouts, and password changes.
|
||||
|
||||
### SEC-052: Admin Action Audit Trail
|
||||
**Severity:** Warning
|
||||
|
||||
All admin operations should be logged with admin user ID, action performed, target resource, timestamp, and IP address.
|
||||
|
||||
### SEC-053: Data Modification Logging
|
||||
**Severity:** Info
|
||||
|
||||
Log create/update/delete on sensitive data like user accounts, roles, financial transactions, and configuration changes.
|
||||
|
||||
### SEC-054: Security Event Logging
|
||||
**Severity:** Warning
|
||||
|
||||
Log security-relevant events like authorization failures, input validation failures, rate limit triggers, and suspicious activity.
|
||||
|
||||
### SEC-055: Log Injection Prevention
|
||||
**Severity:** Warning
|
||||
|
||||
Sanitize user input before logging. Newlines and control characters can corrupt logs.
|
||||
|
||||
```python
|
||||
# Bad
|
||||
logger.info(f"User search: {request.query}")
|
||||
|
||||
# Good
|
||||
logger.info(f"User search: {request.query!r}") # repr escapes
|
||||
```
|
||||
|
||||
### SEC-056: Centralized Logging
|
||||
**Severity:** Info
|
||||
|
||||
Use centralized logging for correlation across services, tamper-evident storage, and alerting.
|
||||
|
||||
### SEC-057: Log Level Appropriateness
|
||||
**Severity:** Info
|
||||
|
||||
Use appropriate log levels: ERROR for security failures, WARNING for suspicious activity, INFO for successful events.
|
||||
|
||||
### SEC-058: Structured Logging Format
|
||||
**Severity:** Info
|
||||
|
||||
Use structured logging (JSON) for easy parsing and searchability.
|
||||
|
||||
### SEC-059: Audit Log Integrity
|
||||
**Severity:** Info
|
||||
|
||||
Protect audit logs from tampering with append-only storage and cryptographic chaining.
|
||||
|
||||
### SEC-060: Privacy-Aware Logging
|
||||
**Severity:** Warning
|
||||
|
||||
Comply with data protection regulations. No PII in logs without consent.
|
||||
|
||||
---
|
||||
|
||||
## Configuration
|
||||
|
||||
All rules are defined in `.security-rules/` directory:
|
||||
|
||||
```
|
||||
.security-rules/
|
||||
├── _main.yaml # Main configuration
|
||||
├── authentication.yaml # SEC-001 to SEC-010
|
||||
├── injection.yaml # SEC-011 to SEC-020
|
||||
├── data_protection.yaml # SEC-021 to SEC-030
|
||||
├── api_security.yaml # SEC-031 to SEC-040
|
||||
├── cryptography.yaml # SEC-041 to SEC-050
|
||||
└── audit.yaml # SEC-051 to SEC-060
|
||||
```
|
||||
|
||||
## Suppressing Rules
|
||||
|
||||
Use noqa comments to suppress specific rules:
|
||||
|
||||
```python
|
||||
# noqa: SEC-001 - This is a test file with intentional test credentials
|
||||
test_password = "test123"
|
||||
```
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Architecture Rules](architecture-rules.md)
|
||||
- [Performance Rules](performance-rules.md)
|
||||
- [Code Quality Guide](code-quality.md)
|
||||
- [Contributing Guide](contributing.md)
|
||||
|
||||
---
|
||||
|
||||
## Summary Statistics
|
||||
|
||||
| Category | Rules | Errors | Warnings | Info |
|
||||
|----------|-------|--------|----------|------|
|
||||
| Authentication | 10 | 4 | 5 | 1 |
|
||||
| Injection Prevention | 10 | 9 | 1 | 0 |
|
||||
| Data Protection | 10 | 4 | 3 | 3 |
|
||||
| API Security | 10 | 4 | 5 | 1 |
|
||||
| Cryptography | 10 | 6 | 2 | 2 |
|
||||
| Audit & Logging | 10 | 0 | 5 | 5 |
|
||||
| **Total** | **60** | **27** | **21** | **12** |
|
||||
|
||||
---
|
||||
|
||||
**Last Updated:** 2025-12-21
|
||||
**Version:** 1.0
|
||||
Reference in New Issue
Block a user