veza/veza-docs/ORIGIN/ORIGIN_SECURITY_FRAMEWORK.md
2026-03-05 19:22:31 +01:00

1760 lines
49 KiB
Markdown

# ORIGIN_SECURITY_FRAMEWORK.md
## 📋 RÉSUMÉ EXÉCUTIF
Ce document définit le framework de sécurité de la plateforme Veza. Il couvre la sécurité applicative, infrastructure, et conformité réglementaire (GDPR). Le framework suit les pratiques OWASP et CIS Benchmarks pour protéger les données utilisateurs et résister aux menaces courantes. Révisé le 2026-03-04 suite à un audit de sécurité ayant identifié deux vulnérabilités critiques JWT (voir section 0).
## 🎯 OBJECTIFS
### Objectif Principal
Construire une plateforme sécurisée par conception (Security by Design) qui protège les données utilisateurs, résiste aux menaces courantes (OWASP Top 10), et maintient la conformité GDPR/CCPA/SOC2 en permanence.
### Objectifs Secondaires
- Prévenir les vulnérabilités critiques (injection, XSS, CSRF)
- Chiffrer toutes les données sensibles (at rest, in transit)
- Implémenter une authentification robuste (MFA, JWT, OAuth)
- Auditer toutes les actions critiques (audit logs immuables)
- Détecter et répondre aux incidents rapidement (SIEM, alerting)
## 📖 TABLE DES MATIÈRES
0. [Corrections critiques — Audit 2026-03-04](#corrections-critiques--audit-2026-03-04)
1. [Security Philosophy](#1-security-philosophy)
2. [Threat Model](#2-threat-model)
3. [Authentication Systems](#3-authentication-systems)
4. [Authorization & RBAC](#4-authorization--rbac)
5. [Data Protection](#5-data-protection)
6. [Network Security](#6-network-security)
7. [Application Security](#7-application-security)
8. [Infrastructure Security](#8-infrastructure-security)
9. [Compliance (GDPR, CCPA, SOC2)](#9-compliance-gdpr-ccpa-soc2)
10. [Sécurité et éthique des données](#10-sécurité-et-éthique-des-données)
11. [Incident Response](#11-incident-response)
12. [Security Testing](#12-security-testing)
## 🔒 RÈGLES IMMUABLES
1. **Toutes les passwords DOIVENT être hashées** avec Argon2id ou bcrypt (cost ≥ 12)
2. **Toutes les communications DOIVENT être chiffrées** (TLS 1.3 minimum)
3. **Toutes les données sensibles au repos DOIVENT être chiffrées** (AES-256)
4. **JWT tokens DOIVENT expirer** (access: 15 min, refresh: 7 jours)
5. **MFA OBLIGATOIRE** pour admin et moderator
6. **Rate limiting OBLIGATOIRE** sur tous les endpoints publics
7. **Input validation OBLIGATOIRE** côté serveur (never trust client)
8. **Audit logs OBLIGATOIRES** pour actions sensibles (immuables)
9. **Security headers OBLIGATOIRES** (CSP, HSTS, X-Frame-Options, etc.)
10. **Secrets JAMAIS dans le code** (environment variables ou Vault)
## CORRECTIONS CRITIQUES — AUDIT 2026-03-04
Deux vulnérabilités critiques identifiées lors de l'audit du 2026-03-04. Priorité P0 — à corriger avant tout autre travail.
### VEZA-SEC-001 : Secret JWT par défaut en dur (P0)
**Fichier** : `veza-common/src/config_rust.rs:234`
Le secret JWT est défini avec une valeur par défaut en dur. Si la variable d'environnement `JWT_SECRET` est absente, le service démarre avec un secret prévisible, ce qui permet la forge de tokens arbitraires.
**Correction requise** :
- Supprimer la valeur par défaut du secret JWT dans `config_rust.rs:234`
- Le service DOIT refuser de démarrer si `JWT_SECRET` n'est pas défini
- Ajouter un test d'intégration qui vérifie le refus de démarrage sans secret
```rust
// AVANT (vulnérable) — config_rust.rs:234
let jwt_secret = env::var("JWT_SECRET").unwrap_or_else(|_| "default-secret".to_string());
// APRÈS (corrigé)
let jwt_secret = env::var("JWT_SECRET")
.expect("JWT_SECRET must be set — refusing to start with no secret");
```
### VEZA-SEC-002 : Désalignement issuer/audience JWT entre Go et Rust (P0)
Les services Go et Rust utilisent des valeurs différentes pour les champs `iss` (issuer) et `aud` (audience) des tokens JWT. Un token émis par le backend Go peut être rejeté par un service Rust (ou inversement), ou pire, accepté sans vérification de ces champs.
**Correction requise** :
- Définir une constante partagée pour `iss` et `aud` dans `veza-common`
- Les deux backends DOIVENT valider `iss` et `aud` à chaque vérification de token
- Valeurs à utiliser : `iss: "veza-api"`, `aud: "veza-platform"`
## 1. SECURITY PHILOSOPHY
### 1.1 Principes Fondamentaux
**Defense in Depth** (multiple layers):
```
Layer 1: Network (Firewall, WAF, DDoS protection)
Layer 2: Application (Input validation, output encoding)
Layer 3: Authentication (JWT, MFA, session management)
Layer 4: Authorization (RBAC, resource-level permissions)
Layer 5: Data (Encryption at rest, in transit)
Layer 6: Monitoring (SIEM, anomaly detection, alerting)
```
**Least Privilege Principle**:
- Users get minimum permissions needed
- Service accounts have scoped permissions
- Database users have role-specific privileges
**Fail Securely**:
- Default deny (whitelist, not blacklist)
- Errors don't leak sensitive info
- Graceful degradation
**Zero Trust Architecture**:
- Never trust, always verify
- Verify every request (even internal)
- Assume breach mentality
### 1.2 Security by Design
**Secure Defaults**:
```go
// Good: Secure by default
user := User{
Role: "user", // Not admin
IsActive: false, // Requires activation
EmailVerified: false, // Requires verification
MFAEnabled: false, // User opts in
}
// Bad: Insecure defaults
user := User{
Role: "admin", // DANGER
IsActive: true,
EmailVerified: true,
}
```
**Minimise Attack Surface**:
- Disable unused features
- Remove debug endpoints in production
- Restrict CORS origins
- Limit exposed ports
## 2. THREAT MODEL
### 2.1 OWASP Top 10 (2021)
| # | Threat | Mitigation | Status |
|---|--------|------------|--------|
| **A01** | Broken Access Control | RBAC, resource ownership checks | ✅ Implemented |
| **A02** | Cryptographic Failures | TLS 1.3, AES-256, proper key management | ✅ Implemented |
| **A03** | Injection | Parameterized queries, input validation | ✅ Implemented |
| **A04** | Insecure Design | Security requirements, threat modeling | ✅ Implemented |
| **A05** | Security Misconfiguration | Hardened configs, automated scanning | ✅ Implemented |
| **A06** | Vulnerable Components | Dependency scanning, automated updates | ✅ Implemented |
| **A07** | Authentication Failures | JWT + MFA, rate limiting, session management | ✅ Implemented |
| **A08** | Software & Data Integrity | Signed packages, CI/CD security | ✅ Implemented |
| **A09** | Security Logging Failures | Comprehensive audit logs, SIEM | ✅ Implemented |
| **A10** | Server-Side Request Forgery | URL validation, allowlist | ✅ Implemented |
### 2.2 Threat Actors
| Actor | Motivation | Capability | Targets |
|-------|------------|------------|---------|
| **Script Kiddies** | Fun, recognition | Low | Public endpoints, known vulnerabilities |
| **Competitors** | Business advantage | Medium | API, data scraping |
| **Cybercriminals** | Financial gain | High | User data, payment info, accounts |
| **Nation States** | Espionage, disruption | Very High | Infrastructure, sensitive data |
| **Malicious Insiders** | Revenge, financial | High | Database, internal systems |
### 2.3 Attack Scenarios
**Scenario 1: Credential Stuffing Attack**
- **Attack**: Automated login attempts with leaked credentials
- **Mitigation**: Rate limiting (10 attempts/min), CAPTCHA after 3 failures, account lockout, MFA
- **Detection**: Anomalous login patterns, multiple failed attempts
**Scenario 2: SQL Injection**
- **Attack**: Malicious SQL in user input
- **Mitigation**: Parameterized queries (GORM, SQLx), input validation, WAF rules
- **Detection**: SQLMap signatures, unusual query patterns
**Scenario 3: XSS Attack**
- **Attack**: Inject malicious JavaScript
- **Mitigation**: Output encoding, CSP headers, sanitize HTML
- **Detection**: WAF rules, CSP violation reports
**Scenario 4: Data Breach**
- **Attack**: Unauthorized access to database
- **Mitigation**: Encryption at rest, minimal privileges, audit logs, network segmentation
- **Detection**: Unusual query volumes, access from unknown IPs
**Scenario 5: DDoS Attack**
- **Attack**: Overwhelm servers with traffic
- **Mitigation**: Cloudflare DDoS protection, rate limiting, auto-scaling
- **Detection**: Traffic spikes, latency increases
## 3. AUTHENTICATION SYSTEMS
### 3.1 Password Authentication
**Password Requirements**:
```
- Minimum length: 12 characters
- Maximum length: 128 characters
- Must contain:
- At least 1 uppercase letter
- At least 1 lowercase letter
- At least 1 digit
- At least 1 special character
- Cannot contain:
- Email or username
- Common passwords (check against Have I Been Pwned)
- Sequential characters (abc, 123)
```
**Password Hashing** (Go backend):
```go
import "golang.org/x/crypto/bcrypt"
// Hash password with bcrypt (cost 12)
func HashPassword(password string) (string, error) {
hash, err := bcrypt.GenerateFromPassword([]byte(password), 12)
if err != nil {
return "", err
}
return string(hash), nil
}
// Verify password
func VerifyPassword(hash, password string) bool {
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
return err == nil
}
```
**Password Hashing** (Rust services):
```rust
use argon2::{Argon2, PasswordHasher, PasswordVerifier};
use argon2::password_hash::{SaltString, rand_core::OsRng};
// Hash password with Argon2id
pub fn hash_password(password: &str) -> Result<String> {
let salt = SaltString::generate(&mut OsRng);
let argon2 = Argon2::default();
let hash = argon2.hash_password(password.as_bytes(), &salt)
.map_err(|e| anyhow!("Hash error: {}", e))?;
Ok(hash.to_string())
}
// Verify password
pub fn verify_password(hash: &str, password: &str) -> bool {
let parsed_hash = PasswordHash::new(hash).ok()?;
Argon2::default()
.verify_password(password.as_bytes(), &parsed_hash)
.is_ok()
}
```
**Password History**:
```sql
-- Prevent password reuse (last 5 passwords)
SELECT COUNT(*) FROM password_history
WHERE user_id = $1
AND password_hash = $2
AND created_at > NOW() - INTERVAL '90 days'
```
### 3.2 JWT Tokens
**Token Structure**:
```json
{
"header": {
"alg": "HS256",
"typ": "JWT"
},
"payload": {
"sub": "550e8400-e29b-41d4-a716-446655440000",
"email": "user@example.com",
"role": "user",
"token_version": 0,
"iat": 1730556000,
"exp": 1730556900
},
"signature": "..."
}
```
**Migration HS256 → RS256 (Phase 3.5 — planifiée)** :
L'algorithme actuel (HS256, secret symétrique) est fonctionnel mais présente des limites :
- Un même secret est partagé entre tous les services qui vérifient les tokens
- La rotation du secret nécessite un redéploiement synchronisé
- Pas de distinction entre capacité d'émission et capacité de vérification
La migration vers RS256 (clé asymétrique) est planifiée pour la Phase 3.5 :
- Seul le service d'authentification détient la clé privée (émission)
- Les autres services ne reçoivent que la clé publique (vérification)
- Rotation facilitée via JWKS endpoint
- Période de transition : les deux algorithmes acceptés pendant 30 jours
**Token Lifecycle**:
- **Access Token**: 15 minutes (short-lived)
- **Refresh Token**: 7 days (long-lived, stored in DB)
**Token Generation** (Go):
```go
import "github.com/golang-jwt/jwt/v5"
type Claims struct {
UserID uuid.UUID `json:"sub"`
Email string `json:"email"`
Role string `json:"role"`
TokenVersion int `json:"token_version"`
jwt.RegisteredClaims
}
func GenerateAccessToken(user *models.User) (string, error) {
claims := Claims{
UserID: user.ID,
Email: user.Email,
Role: user.Role,
TokenVersion: user.TokenVersion,
RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(time.Now().Add(15 * time.Minute)),
IssuedAt: jwt.NewNumericDate(time.Now()),
},
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
return token.SignedString([]byte(os.Getenv("JWT_SECRET")))
}
```
**Token Invalidation**:
```go
// Invalidate all tokens for user (logout all devices)
func InvalidateAllTokens(userID uuid.UUID) error {
return db.Model(&models.User{}).
Where("id = ?", userID).
Update("token_version", gorm.Expr("token_version + 1")).
Error
}
```
**Token Verification Middleware**:
```go
func AuthMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
authHeader := c.GetHeader("Authorization")
if !strings.HasPrefix(authHeader, "Bearer ") {
c.JSON(401, ErrorResponse{Code: 1002, Message: "Invalid token"})
c.Abort()
return
}
tokenString := strings.TrimPrefix(authHeader, "Bearer ")
claims, err := VerifyToken(tokenString)
if err != nil {
c.JSON(401, ErrorResponse{Code: 1001, Message: "Token expired"})
c.Abort()
return
}
// Check token version (for revocation)
user := GetUser(claims.UserID)
if user.TokenVersion != claims.TokenVersion {
c.JSON(401, ErrorResponse{Code: 1002, Message: "Token revoked"})
c.Abort()
return
}
c.Set("user", user)
c.Next()
}
}
```
### 3.3 Multi-Factor Authentication (MFA)
**TOTP (Time-Based One-Time Password)**:
```go
import "github.com/pquerna/otp/totp"
// Generate TOTP secret
func GenerateTOTPSecret(email string) (*otp.Key, error) {
return totp.Generate(totp.GenerateOpts{
Issuer: "Veza",
AccountName: email,
})
}
// Verify TOTP code
func VerifyTOTPCode(secret, code string) bool {
return totp.Validate(code, secret)
}
```
**Backup Codes**:
```go
// Generate 10 backup codes (8 characters each)
func GenerateBackupCodes() []string {
codes := make([]string, 10)
for i := range codes {
codes[i] = generateRandomString(8)
}
return codes
}
// Store hashed backup codes
func StoreBackupCodes(userID uuid.UUID, codes []string) error {
hashed := make([]string, len(codes))
for i, code := range codes {
hash, _ := bcrypt.GenerateFromPassword([]byte(code), 12)
hashed[i] = string(hash)
}
return db.Model(&models.TwoFactorConfig{}).
Where("user_id = ?", userID).
Update("backup_codes", hashed).
Error
}
```
**MFA Login Flow**:
```
1. User enters email/password
2. Backend verifies credentials
3. IF MFA enabled:
a. Return "mfa_required" response
b. User enters TOTP code
c. Backend verifies TOTP
d. Return JWT tokens
4. ELSE:
Return JWT tokens directly
```
### 3.4 OAuth 2.0 (Social Login)
**Supported Providers**:
- Google OAuth 2.0
- GitHub OAuth
- Discord OAuth
- Spotify OAuth
**OAuth Flow** (Authorization Code):
```go
// Step 1: Redirect to provider
func InitiateOAuth(c *gin.Context) {
provider := c.Param("provider") // google, github, discord, spotify
config := getOAuthConfig(provider)
state := generateRandomString(32)
// Store state in Redis (expires in 10 min)
redis.Set("oauth_state:"+state, c.ClientIP(), 10*time.Minute)
url := config.AuthCodeURL(state, oauth2.AccessTypeOffline)
c.Redirect(302, url)
}
// Step 2: Handle callback
func OAuthCallback(c *gin.Context) {
code := c.Query("code")
state := c.Query("state")
// Verify state
if !redis.Exists("oauth_state:" + state) {
c.JSON(400, ErrorResponse{Code: 1009, Message: "Invalid state"})
return
}
// Exchange code for token
token, err := config.Exchange(ctx, code)
if err != nil {
c.JSON(400, ErrorResponse{Code: 1009, Message: "OAuth error"})
return
}
// Get user info from provider
userInfo := fetchUserInfo(token)
// Find or create user
user := findOrCreateUserByOAuth(userInfo)
// Generate JWT
accessToken := GenerateAccessToken(user)
refreshToken := GenerateRefreshToken(user)
c.JSON(200, LoginResponse{
AccessToken: accessToken,
RefreshToken: refreshToken,
User: user,
})
}
```
### 3.5 Session Management
**Refresh Token Storage**:
```sql
CREATE TABLE refresh_tokens (
id UUID PRIMARY KEY,
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
token_hash VARCHAR(255) NOT NULL UNIQUE, -- SHA-256 hash
device_name VARCHAR(255),
user_agent TEXT,
ip_address INET,
expires_at TIMESTAMPTZ NOT NULL,
last_used_at TIMESTAMPTZ,
is_revoked BOOLEAN NOT NULL DEFAULT false,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
```
**Session Security**:
- Store only hashed refresh tokens (SHA-256)
- Track device, IP, user agent
- Invalidate on password change
- Revoke on logout
- Auto-expire after 7 days of inactivity
## 4. AUTHORIZATION & RBAC
### 4.1 Role Hierarchy
```
admin (highest privileges)
└── moderator (content moderation)
└── premium (paid features)
└── creator (content creation)
└── user (base role)
```
### 4.2 Permission Matrix
| Resource | Action | user | creator | premium | moderator | admin |
|----------|--------|------|---------|---------|-----------|-------|
| **Track** | View | ✅ | ✅ | ✅ | ✅ | ✅ |
| **Track** | Upload | ❌ | ✅ | ✅ | ✅ | ✅ |
| **Track** | Edit Own | ❌ | ✅ | ✅ | ✅ | ✅ |
| **Track** | Delete Own | ❌ | ✅ | ✅ | ✅ | ✅ |
| **Track** | Delete Any | ❌ | ❌ | ❌ | ✅ | ✅ |
| **User** | View Profile | ✅ | ✅ | ✅ | ✅ | ✅ |
| **User** | Edit Own | ✅ | ✅ | ✅ | ✅ | ✅ |
| **User** | Ban | ❌ | ❌ | ❌ | ✅ | ✅ |
| **User** | Change Role | ❌ | ❌ | ❌ | ❌ | ✅ |
| **Product** | Buy | ✅ | ✅ | ✅ | ✅ | ✅ |
| **Product** | Sell | ❌ | ✅ | ✅ | ✅ | ✅ |
| **Config** | View | ❌ | ❌ | ❌ | ❌ | ✅ |
| **Config** | Edit | ❌ | ❌ | ❌ | ❌ | ✅ |
### 4.3 Resource-Level Authorization
**Check Ownership**:
```go
func RequireOwnership() gin.HandlerFunc {
return func(c *gin.Context) {
user := GetCurrentUser(c)
resourceID := c.Param("id")
resource := GetResource(resourceID)
if resource.UserID != user.ID && user.Role != "admin" {
c.JSON(403, ErrorResponse{Code: 1003, Message: "Forbidden"})
c.Abort()
return
}
c.Next()
}
}
// Usage
r.PATCH("/tracks/:id", AuthMiddleware(), RequireOwnership(), handlers.UpdateTrack)
```
**Permission Policies** (Casbin):
```ini
# policy.csv
p, admin, *, *
p, moderator, track, delete
p, moderator, user, ban
p, creator, track, create
p, creator, track, update_own
p, user, track, view
```
### 4.4 API Key Authentication (for external integrations)
**API Key Structure**:
```
Format: vz_live_1234567890abcdef1234567890abcdef
Prefix: vz_live_ (production) or vz_test_ (sandbox)
```
**API Key Storage**:
```sql
CREATE TABLE api_keys (
id UUID PRIMARY KEY,
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
key_prefix VARCHAR(20) NOT NULL, -- vz_live_1234
key_hash VARCHAR(255) NOT NULL UNIQUE, -- SHA-256 of full key
name VARCHAR(255),
scopes VARCHAR(50)[], -- ['read:tracks', 'write:playlists']
last_used_at TIMESTAMPTZ,
expires_at TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
```
## 5. DATA PROTECTION
### 5.1 Encryption at Rest
**Database Encryption** (PostgreSQL):
```sql
-- Enable pgcrypto extension
CREATE EXTENSION IF NOT EXISTS pgcrypto;
-- Encrypt sensitive columns
CREATE TABLE users (
id UUID PRIMARY KEY,
email VARCHAR(255) NOT NULL,
ssn BYTEA, -- Encrypted with pgcrypto
phone_encrypted BYTEA
);
-- Insert encrypted data
INSERT INTO users (id, email, ssn)
VALUES (
gen_random_uuid(),
'user@example.com',
pgp_sym_encrypt('123-45-6789', 'encryption_key')
);
-- Decrypt data
SELECT
id,
email,
pgp_sym_decrypt(ssn, 'encryption_key') AS ssn_decrypted
FROM users;
```
**File Encryption** (S3/MinIO):
```go
// Client-side encryption before upload
func EncryptFile(data []byte, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}
nonce := make([]byte, gcm.NonceSize())
if _, err := rand.Read(nonce); err != nil {
return nil, err
}
ciphertext := gcm.Seal(nonce, nonce, data, nil)
return ciphertext, nil
}
// Or server-side encryption (S3)
s3Client.PutObject(&s3.PutObjectInput{
Bucket: aws.String("veza-files"),
Key: aws.String("file.txt"),
Body: bytes.NewReader(data),
ServerSideEncryption: aws.String("AES256"),
})
```
**Encryption Key Management**:
```
Production: HashiCorp Vault
Development: Environment variables
Rotation: Every 90 days
Algorithm: AES-256-GCM
Key derivation: PBKDF2 or Argon2
```
### 5.2 Encryption in Transit
**TLS Configuration** (Nginx):
```nginx
server {
listen 443 ssl http2;
server_name api.veza.io;
# TLS 1.3 only
ssl_protocols TLSv1.3;
# Modern cipher suite
ssl_ciphers 'TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256';
ssl_prefer_server_ciphers off;
# Certificates (Let's Encrypt)
ssl_certificate /etc/letsencrypt/live/api.veza.io/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.veza.io/privkey.pem;
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
# HSTS header
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
}
```
**Database TLS** (PostgreSQL):
```go
// Require SSL for database connections
db, err := gorm.Open(postgres.Open(
"host=db.veza.io user=veza password=xxx dbname=veza_db sslmode=require",
), &gorm.Config{})
```
**Redis TLS**:
```go
redisClient := redis.NewClient(&redis.Options{
Addr: "redis.veza.io:6380",
Password: os.Getenv("REDIS_PASSWORD"),
TLSConfig: &tls.Config{
MinVersion: tls.VersionTLS13,
},
})
```
### 5.3 Data Masking & Anonymization
**PII Masking** (logs):
```go
func MaskEmail(email string) string {
parts := strings.Split(email, "@")
if len(parts) != 2 {
return "***"
}
username := parts[0]
if len(username) > 3 {
username = username[:3] + "***"
} else {
username = "***"
}
return username + "@" + parts[1]
}
// Log: user@example.com → use***@example.com
logger.Info("User logged in", zap.String("email", MaskEmail(user.Email)))
```
**Data Anonymization** (for analytics):
```sql
-- Anonymize user data for analytics
CREATE MATERIALIZED VIEW analytics_users AS
SELECT
MD5(id::text)::uuid AS anonymous_id, -- One-way hash
DATE_TRUNC('month', created_at) AS signup_month,
role,
country -- Aggregated, not precise location
FROM users;
```
### 5.4 Data Retention & Deletion
**Soft Delete** (default):
```sql
-- Soft delete (set deleted_at timestamp)
UPDATE users SET deleted_at = NOW() WHERE id = $1;
-- Queries exclude soft-deleted
SELECT * FROM users WHERE deleted_at IS NULL;
```
**Hard Delete** (GDPR right to be forgotten):
```go
func DeleteUserData(userID uuid.UUID) error {
// 1. Delete user data
db.Unscoped().Where("id = ?", userID).Delete(&models.User{})
// 2. Anonymize related data (preserve analytics)
db.Model(&models.Track{}).
Where("creator_id = ?", userID).
Update("creator_id", uuid.Nil) // Null user reference
// 3. Delete personal files (S3)
deleteUserFiles(userID)
// 4. Log deletion (audit)
auditLog("user_deleted", userID)
return nil
}
```
**Retention Policy**:
```
Données de compte : jusqu'à demande de suppression par l'utilisateur
Logs applicatifs : 90 jours (anonymisés après expiration)
Sessions : 30 jours
Analytics : 12 mois (agrégées, anonymisées)
Backups : 30 jours
Audit logs : 24 mois
```
## 6. NETWORK SECURITY
### 6.1 Firewall Rules
**VPC Security Groups** (AWS):
```hcl
# Allow HTTPS from anywhere
resource "aws_security_group_rule" "allow_https" {
type = "ingress"
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
security_group_id = aws_security_group.web.id
}
# Allow PostgreSQL only from backend
resource "aws_security_group_rule" "allow_postgres" {
type = "ingress"
from_port = 5432
to_port = 5432
protocol = "tcp"
source_security_group_id = aws_security_group.backend.id
security_group_id = aws_security_group.database.id
}
# Deny all other inbound traffic (implicit)
```
### 6.2 WAF (Web Application Firewall)
**Cloudflare WAF Rules**:
```
Rule 1: Block known bad IPs (threat intelligence)
Rule 2: Rate limit login attempts (10/min per IP)
Rule 3: Block SQL injection patterns (UNION SELECT, etc.)
Rule 4: Block XSS patterns (<script>, onerror=, etc.)
Rule 5: Block common attack tools (Nikto, SQLMap)
Rule 6: Challenge suspicious traffic (high request rate, unusual headers)
Rule 7: Block traffic from high-risk countries (optional)
```
**ModSecurity Rules** (if self-hosted):
```apache
# Enable OWASP Core Rule Set
Include /etc/modsecurity/crs-setup.conf
Include /etc/modsecurity/rules/*.conf
# Custom rules
SecRule REQUEST_URI "@rx (\bunion\b.{1,100}\bselect\b)" \
"id:1001,phase:2,deny,status:403,msg:'SQL Injection Attempt'"
SecRule ARGS "@rx (<script|onerror=|onload=)" \
"id:1002,phase:2,deny,status:403,msg:'XSS Attempt'"
```
### 6.3 DDoS Protection
**Cloudflare DDoS Protection** (Layer 3/4/7):
- Automatic mitigation (up to 100 Tbps capacity)
- Rate limiting (configurable thresholds)
- Challenge page for suspicious traffic
**Application-Level Rate Limiting**:
```go
// Redis-based rate limiter
func RateLimitMiddleware(limit int, window time.Duration) gin.HandlerFunc {
return func(c *gin.Context) {
key := "ratelimit:" + c.ClientIP() + ":" + c.Request.URL.Path
count, _ := redis.Incr(key)
if count == 1 {
redis.Expire(key, window)
}
if count > int64(limit) {
c.Header("X-RateLimit-Limit", strconv.Itoa(limit))
c.Header("X-RateLimit-Remaining", "0")
c.JSON(429, ErrorResponse{
Code: 5000,
Message: "Rate limit exceeded",
})
c.Abort()
return
}
c.Header("X-RateLimit-Limit", strconv.Itoa(limit))
c.Header("X-RateLimit-Remaining", strconv.Itoa(limit-int(count)))
c.Next()
}
}
```
### 6.4 Network Segmentation
**VPC Architecture**:
```
Public Subnet (DMZ):
- Load Balancers (ALB)
- Bastion hosts
Private Subnet (Application):
- Backend API servers
- Rust services (chat, stream)
- Worker nodes
Private Subnet (Data):
- PostgreSQL (RDS)
- Redis (ElastiCache)
- Elasticsearch
Isolated Subnet (Management):
- Monitoring (Prometheus, Grafana)
- CI/CD runners
```
## 7. APPLICATION SECURITY
### 7.1 Input Validation
**Validate ALL Inputs**:
```go
type CreateTrackRequest struct {
Title string `json:"title" binding:"required,min=1,max=255"`
Artist string `json:"artist" binding:"max=255"`
Genre string `json:"genre" binding:"oneof=electronic house techno"`
BPM int `json:"bpm" binding:"min=60,max=200"`
Duration int `json:"duration" binding:"required,min=1"`
Visibility string `json:"visibility" binding:"required,oneof=public unlisted private"`
}
func CreateTrack(c *gin.Context) {
var req CreateTrackRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(400, ErrorResponse{
Code: 2000,
Message: "Validation failed",
Details: parseValidationErrors(err),
})
return
}
// Additional business logic validation
if req.BPM > 0 && (req.BPM < 60 || req.BPM > 200) {
c.JSON(400, ErrorResponse{Code: 2003, Message: "BPM out of range"})
return
}
// Process request...
}
```
**Sanitize HTML** (frontend):
```typescript
import DOMPurify from 'dompurify';
function sanitizeHTML(dirty: string): string {
return DOMPurify.sanitize(dirty, {
ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a'],
ALLOWED_ATTR: ['href'],
});
}
// Usage
const userBio = sanitizeHTML(inputBio);
```
### 7.2 SQL Injection Prevention
**Use Parameterized Queries** (GORM):
```go
// ✅ Safe: Parameterized query
db.Where("email = ?", userInput).First(&user)
// ❌ DANGER: String concatenation
db.Where("email = '" + userInput + "'").First(&user) // NEVER DO THIS
```
**Use Parameterized Queries** (SQLx Rust):
```rust
// ✅ Safe: Parameterized query
let user = sqlx::query_as!(
User,
"SELECT * FROM users WHERE email = $1",
email
)
.fetch_one(&pool)
.await?;
// ❌ DANGER: Format string
let query = format!("SELECT * FROM users WHERE email = '{}'", email); // NEVER
```
### 7.3 XSS Prevention
**Output Encoding** (React automatically escapes):
```tsx
// ✅ Safe: React escapes by default
<div>{userInput}</div>
// ⚠️ Danger: dangerouslySetInnerHTML
<div dangerouslySetInnerHTML={{ __html: userInput }} /> // Only if sanitized
// ✅ Safe with sanitization
<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(userInput) }} />
```
**CSP Header**:
```go
c.Header("Content-Security-Policy",
"default-src 'self'; " +
"script-src 'self' 'unsafe-inline' https://cdn.veza.io; " +
"style-src 'self' 'unsafe-inline'; " +
"img-src 'self' data: https:; " +
"font-src 'self' data:; " +
"connect-src 'self' wss://api.veza.io; " +
"frame-ancestors 'none';")
```
### 7.4 CSRF Protection
**CSRF Token** (for forms):
```go
// Generate CSRF token
func GenerateCSRFToken() string {
b := make([]byte, 32)
rand.Read(b)
return base64.URLEncoding.EncodeToString(b)
}
// Store in session
session.Set("csrf_token", GenerateCSRFToken())
// Validate on POST
func ValidateCSRFToken(c *gin.Context) {
sessionToken := session.Get("csrf_token")
requestToken := c.PostForm("csrf_token")
if sessionToken != requestToken {
c.JSON(403, ErrorResponse{Code: 1003, Message: "CSRF token invalid"})
c.Abort()
return
}
}
```
**SameSite Cookie** (for API):
```go
c.SetSameSite(http.SameSiteStrictMode)
c.SetCookie(
"refresh_token",
token,
3600*24*7, // 7 days
"/",
"veza.io",
true, // Secure (HTTPS only)
true, // HttpOnly (no JavaScript access)
)
```
### 7.5 File Upload Security
**Validation**:
```go
func ValidateFileUpload(file *multipart.FileHeader) error {
// 1. Check file size (max 100 MB)
if file.Size > 100*1024*1024 {
return errors.New("file too large")
}
// 2. Check file extension (whitelist)
allowedExtensions := []string{".mp3", ".wav", ".flac", ".m4a"}
ext := filepath.Ext(file.Filename)
if !contains(allowedExtensions, ext) {
return errors.New("invalid file type")
}
// 3. Check MIME type (from content, not just extension)
f, _ := file.Open()
defer f.Close()
buffer := make([]byte, 512)
f.Read(buffer)
mimeType := http.DetectContentType(buffer)
if !strings.HasPrefix(mimeType, "audio/") {
return errors.New("invalid file content")
}
// 4. Virus scan (ClamAV)
if !virusScan(file) {
return errors.New("virus detected")
}
return nil
}
```
**Safe Storage**:
```go
// Generate random filename (prevent path traversal)
func GenerateFilename(originalName string) string {
ext := filepath.Ext(originalName)
randomName := uuid.New().String()
return randomName + ext
}
// Store outside webroot with restricted permissions
func SaveFile(file *multipart.FileHeader) error {
filename := GenerateFilename(file.Filename)
path := filepath.Join("/var/uploads", filename) // Outside webroot
if err := c.SaveUploadedFile(file, path); err != nil {
return err
}
// Set permissions (owner read/write only)
os.Chmod(path, 0600)
return nil
}
```
### 7.6 Security Headers
**All Responses Include**:
```go
func SecurityHeadersMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
// Prevent clickjacking
c.Header("X-Frame-Options", "DENY")
// Prevent MIME sniffing
c.Header("X-Content-Type-Options", "nosniff")
// Enable XSS filter
c.Header("X-XSS-Protection", "1; mode=block")
// HSTS (force HTTPS)
c.Header("Strict-Transport-Security", "max-age=31536000; includeSubDomains; preload")
// Referrer policy
c.Header("Referrer-Policy", "strict-origin-when-cross-origin")
// Permissions policy
c.Header("Permissions-Policy", "geolocation=(), microphone=(), camera=()")
// CSP (see above)
c.Header("Content-Security-Policy", "default-src 'self'; ...")
c.Next()
}
}
```
## 8. INFRASTRUCTURE SECURITY
### 8.1 Container Security
**Dockerfile Best Practices**:
```dockerfile
# Use specific version (not latest)
FROM golang:1.22-alpine AS builder
# Run as non-root user
RUN adduser -D -u 10001 appuser
# Copy only necessary files
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN go build -o main .
# Multi-stage build (smaller image)
FROM alpine:3.19
RUN adduser -D -u 10001 appuser
COPY --from=builder /app/main /app/main
# Run as non-root
USER appuser
EXPOSE 8080
CMD ["/app/main"]
```
**Image Scanning**:
```bash
# Trivy scan
trivy image veza-backend:latest
# Fail CI if critical vulnerabilities
trivy image --severity CRITICAL,HIGH --exit-code 1 veza-backend:latest
```
### 8.2 Secrets Management
**HashiCorp Vault**:
```go
import "github.com/hashicorp/vault/api"
func GetSecret(key string) (string, error) {
client, _ := api.NewClient(api.DefaultConfig())
client.SetAddress("https://vault.veza.io")
client.SetToken(os.Getenv("VAULT_TOKEN"))
secret, err := client.Logical().Read("secret/data/veza/" + key)
if err != nil {
return "", err
}
return secret.Data["value"].(string), nil
}
// Usage
jwtSecret := GetSecret("jwt_secret")
dbPassword := GetSecret("db_password")
```
**Environment Variables** (development):
```bash
# .env (NEVER commit to Git)
JWT_SECRET=your-super-secret-jwt-key-min-32-chars
DATABASE_URL=postgresql://veza:password@localhost:5432/veza_db
REDIS_URL=redis://localhost:6379
AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
```
### 8.3 Logging & Monitoring
**Audit Logs** (all sensitive actions):
```go
func AuditLog(action string, userID uuid.UUID, resourceType string, resourceID uuid.UUID, metadata map[string]interface{}) {
log := models.AuditLog{
ID: uuid.New(),
UserID: userID,
Action: action,
ResourceType: resourceType,
ResourceID: resourceID,
Metadata: metadata,
IPAddress: c.ClientIP(),
UserAgent: c.Request.UserAgent(),
CreatedAt: time.Now(),
}
db.Create(&log)
}
// Usage
AuditLog("user.login", user.ID, "user", user.ID, map[string]interface{}{
"mfa_used": true,
})
AuditLog("track.deleted", user.ID, "track", track.ID, map[string]interface{}{
"track_title": track.Title,
})
```
**Security Monitoring** (Prometheus metrics):
```go
var (
loginAttempts = prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "veza_login_attempts_total",
Help: "Total login attempts",
},
[]string{"status", "method"},
)
unauthorizedRequests = prometheus.NewCounter(
prometheus.CounterOpts{
Name: "veza_unauthorized_requests_total",
Help: "Total unauthorized requests (401/403)",
},
)
)
// Track failed logins
loginAttempts.WithLabelValues("failed", "password").Inc()
// Alert if > 100 failed logins/min from same IP
```
**Protection des routes Prometheus `/metrics`** :
Les endpoints `/metrics` Prometheus sont actuellement exposés publiquement. Cela permet à un attaquant d'observer les patterns de trafic, les taux d'erreur, et la topologie interne des services. Correction requise :
- Les routes `/metrics` DOIVENT être accessibles uniquement depuis le réseau interne (subnet monitoring)
- En environnement Kubernetes : utiliser un `ServiceMonitor` sur un port dédié non exposé par l'Ingress
- En environnement Docker Compose : ne pas mapper le port metrics sur l'hôte, utiliser le réseau interne Docker
- Alternative : protéger avec authentification Basic Auth sur un reverse proxy dédié
```go
// Exposer /metrics sur un port séparé, non public
go func() {
mux := http.NewServeMux()
mux.Handle("/metrics", promhttp.Handler())
// Port 9090 : accessible uniquement depuis le réseau interne
http.ListenAndServe(":9090", mux)
}()
```
## 9. COMPLIANCE (GDPR, CCPA, SOC2)
### 9.1 GDPR Compliance
**Lawful Basis**: Consent (for marketing), Contract (for service), Legitimate Interest (for security)
**Data Subject Rights**:
**Right to Access** (Article 15):
```go
func ExportUserData(userID uuid.UUID) (map[string]interface{}, error) {
data := make(map[string]interface{})
// Personal data
var user models.User
db.First(&user, userID)
data["user"] = user
// Tracks
var tracks []models.Track
db.Where("creator_id = ?", userID).Find(&tracks)
data["tracks"] = tracks
// Orders
var orders []models.Order
db.Where("user_id = ?", userID).Find(&orders)
data["orders"] = orders
// Messages (recent 90 days)
var messages []models.Message
db.Where("sender_id = ? AND created_at > ?", userID, time.Now().AddDate(0, -3, 0)).Find(&messages)
data["messages"] = messages
return data, nil
}
```
**Right to Erasure** (Article 17):
```go
func DeleteUserDataGDPR(userID uuid.UUID) error {
// 1. Hard delete user
db.Unscoped().Delete(&models.User{}, userID)
// 2. Anonymize tracks (keep for platform, anonymize creator)
db.Model(&models.Track{}).
Where("creator_id = ?", userID).
Update("creator_id", nil)
// 3. Delete messages
db.Delete(&models.Message{}, "sender_id = ?", userID)
// 4. Delete files (S3)
deleteUserFiles(userID)
// 5. Blacklist email (prevent re-registration)
db.Create(&models.DeletedUser{
Email: user.Email,
DeletedAt: time.Now(),
})
return nil
}
```
**Right to Data Portability** (Article 20):
```go
// Export as JSON
func ExportUserDataJSON(userID uuid.UUID) ([]byte, error) {
data, err := ExportUserData(userID)
if err != nil {
return nil, err
}
return json.MarshalIndent(data, "", " ")
}
```
**Consent Management**:
```sql
CREATE TABLE user_consents (
id UUID PRIMARY KEY,
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
consent_type VARCHAR(50) NOT NULL, -- marketing, analytics, cookies
granted BOOLEAN NOT NULL,
ip_address INET,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
```
### 9.2 CCPA Compliance
**Do Not Sell My Personal Information**:
```go
func OptOutOfDataSale(userID uuid.UUID) error {
return db.Model(&models.UserSettings{}).
Where("user_id = ?", userID).
Update("ccpa_opt_out", true).
Error
}
```
**Disclosure**: Privacy policy lists all data collected and shared
### 9.3 SOC 2 Type II
**Security Controls**:
- [ ] Access control (RBAC)
- [ ] Encryption (TLS, AES-256)
- [ ] Logging & monitoring
- [ ] Incident response plan
- [ ] Disaster recovery plan
- [ ] Vendor risk management
- [ ] Security awareness training
**Audit Trail**: All access to production systems logged
## 10. SÉCURITÉ ET ÉTHIQUE DES DONNÉES
Veza collecte le minimum de données nécessaire au fonctionnement de la plateforme. Ce principe s'applique à tous les services.
### 10.1 Minimisation des données collectées
Seules les données strictement nécessaires au service sont collectées :
- Compte : email, nom d'affichage, mot de passe hashé, rôle
- Contenu : métadonnées des tracks (titre, artiste, genre, BPM), fichiers audio
- Transactions : historique d'achats (montant, date, identifiant produit)
Ne sont PAS collectées :
- Localisation précise (pas de géolocalisation)
- Contacts ou carnet d'adresses
- Données biométriques
- Historique de navigation hors plateforme
### 10.2 Durées de rétention explicites
| Type de donnée | Durée de rétention | Action à expiration |
|---|---|---|
| Logs applicatifs | 90 jours | Anonymisation automatique |
| Sessions utilisateur | 30 jours | Suppression |
| Analytics | 12 mois | Agrégation puis suppression des données brutes |
| Données de compte | Jusqu'à demande de suppression | Suppression complète sous 30 jours |
| Audit trail | 24 mois | Archivage anonymisé |
### 10.3 Droits GDPR implémentés
- **Export** : endpoint `GET /api/v1/users/me/export` — retourne toutes les données personnelles en JSON
- **Suppression** : endpoint `DELETE /api/v1/users/me` — suppression complète (hard delete) avec anonymisation des contenus associés, exécutée sous 30 jours
- **Rectification** : endpoint `PATCH /api/v1/users/me` — modification des données personnelles
- **Portabilité** : l'export JSON est dans un format standard réutilisable
### 10.4 Pas de tracking comportemental tiers
Aucun service de tracking tiers n'est intégré :
- Pas de Google Analytics, Facebook Pixel, ou équivalent
- Pas de fingerprinting navigateur
- Pas de revente ou partage de données avec des tiers
- Les analytics internes sont agrégées et anonymisées (voir section 5.3)
### 10.5 Anonymisation des logs
Les logs applicatifs sont anonymisés automatiquement après 90 jours :
- Adresses IP remplacées par des hashes non réversibles
- Identifiants utilisateur supprimés
- Seuls les patterns agrégés sont conservés (compteurs, métriques de performance)
### 10.6 Audit trail pour les actions sensibles
Toutes les actions suivantes génèrent une entrée d'audit immuable :
- Connexion / déconnexion (succès et échecs)
- Modification de mot de passe ou d'email
- Activation / désactivation MFA
- Suppression de compte
- Modification de rôle
- Suppression de contenu (tracks, commentaires)
- Accès aux données d'export utilisateur
- Actions de modération
L'audit trail est conservé 24 mois et accessible aux administrateurs via le panneau d'administration.
## 11. INCIDENT RESPONSE
### 11.1 Incident Response Plan
**Phase 1: Detection** (< 15 minutes)
- SIEM alerts (unusual patterns)
- User reports (security@veza.io)
- Bug bounty reports
**Phase 2: Containment** (< 1 hour)
- Isolate affected systems
- Block malicious IPs
- Disable compromised accounts
- Preserve evidence
**Phase 3: Eradication** (< 4 hours)
- Identify root cause
- Remove malware/backdoors
- Patch vulnerabilities
- Reset credentials
**Phase 4: Recovery** (< 8 hours)
- Restore from clean backups
- Re-enable services
- Monitor for re-infection
**Phase 5: Post-Incident** (< 1 week)
- Post-mortem report
- Update security controls
- User notification (if required)
- Regulatory notification (GDPR 72h)
### 11.2 Security Incident Categories
| Severity | Examples | Response Time | Escalation |
|----------|----------|---------------|------------|
| **Critical** | Data breach, RCE, complete outage | < 15 min | CTO, CEO |
| **High** | SQL injection, XSS, privilege escalation | < 1 hour | Security Lead |
| **Medium** | DDoS, brute-force, CSRF | < 4 hours | DevOps Team |
| **Low** | Informational leaks, outdated software | < 24 hours | Developer |
### 11.3 Communication Plan
**Internal**:
- Slack #security-incidents channel
- On-call rotation (PagerDuty)
**External**:
- Status page (status.veza.io)
- Email notifications (affected users)
- Press release (if public breach)
## 12. SECURITY TESTING
### 12.1 Static Application Security Testing (SAST)
**Go** (Gosec):
```bash
# Install
go install github.com/securego/gosec/v2/cmd/gosec@latest
# Run
gosec ./...
# CI/CD integration
gosec -fmt=json -out=report.json ./...
```
**Rust** (Cargo Audit):
```bash
# Install
cargo install cargo-audit
# Run
cargo audit
# CI/CD integration
cargo audit --deny warnings
```
**TypeScript** (ESLint security plugin):
```bash
npm install --save-dev eslint-plugin-security
# .eslintrc.js
plugins: ['security'],
extends: ['plugin:security/recommended'],
```
### 12.2 Dynamic Application Security Testing (DAST)
**OWASP ZAP**:
```bash
# Docker scan
docker run -t owasp/zap2docker-stable zap-baseline.py \
-t https://staging.veza.io \
-r zap_report.html
```
**Burp Suite** (manual testing):
- Proxy all requests
- Identify injection points
- Test authentication flows
- Test session management
### 12.3 Dependency Scanning
**Go** (Dependabot + govulncheck):
```bash
# Install
go install golang.org/x/vuln/cmd/govulncheck@latest
# Run
govulncheck ./...
```
**Rust** (Cargo Audit):
```bash
cargo audit --deny warnings
```
**JavaScript** (npm audit):
```bash
npm audit --audit-level=high
```
### 12.4 Penetration Testing
**Schedule**: Avant chaque release majeure + audit externe annuel
**Pentest externe obligatoire avant Phase 4R** :
Un audit de sécurité externe (pentest) par un prestataire indépendant est requis avant le passage en Phase 4R (release publique). Conditions :
- Prestataire certifié (OSCP, CREST, ou équivalent)
- Périmètre : authentification, API, upload, WebSocket, RBAC
- Rapport avec scores CVSS pour chaque vulnérabilité
- Toutes les vulnérabilités critiques et hautes doivent être corrigées avant la release
- Le rapport de pentest est archivé et accessible à l'équipe sécurité
**Scope**:
- Web application (frontend + backend)
- API endpoints
- WebSocket connections
- File upload functionality
- Authentication flows
**Methodology**: OWASP Testing Guide
**Deliverables**:
- Executive summary
- Vulnerability list (CVSS scores)
- Proof of concept exploits
- Remediation recommendations
### 12.5 Bug Bounty Program
**Platform**: HackerOne or Bugcrowd
**Scope**:
- *.veza.io domains
- API (api.veza.io)
- Mobile apps (iOS, Android)
**Out of Scope**:
- Social engineering
- Physical attacks
- DDoS
- Third-party services
**Rewards**:
| Severity | Reward |
|----------|--------|
| Critical | $1,000 - $5,000 |
| High | $500 - $1,000 |
| Medium | $250 - $500 |
| Low | $50 - $250 |
## ✅ CHECKLIST DE VALIDATION
### Authentication
- [ ] Password hashing (bcrypt/Argon2, cost 12)
- [ ] JWT tokens (HS256, expiration: 15 min)
- [ ] Refresh tokens (secure storage, revocation)
- [ ] MFA (TOTP + backup codes)
- [ ] OAuth 2.0 (Google, GitHub, Discord, Spotify)
- [ ] Session management (device tracking, revocation)
### Authorization
- [ ] RBAC (roles: user, creator, premium, moderator, admin)
- [ ] Resource-level permissions
- [ ] API key authentication (for integrations)
### Data Protection
- [ ] Encryption at rest (AES-256)
- [ ] Encryption in transit (TLS 1.3)
- [ ] Key management (Vault)
- [ ] Data masking (logs)
- [ ] Data retention policies
- [ ] GDPR right to be forgotten
### Application Security
- [ ] Input validation (all endpoints)
- [ ] Parameterized queries (SQL injection prevention)
- [ ] Output encoding (XSS prevention)
- [ ] CSRF protection
- [ ] File upload validation
- [ ] Security headers (CSP, HSTS, X-Frame-Options)
### Infrastructure
- [ ] Firewall rules (VPC security groups)
- [ ] WAF (Cloudflare or ModSecurity)
- [ ] DDoS protection
- [ ] Network segmentation
- [ ] Container security (non-root, image scanning)
- [ ] Secrets management (Vault or env vars)
### Compliance
- [ ] GDPR (consent, data export, right to erasure)
- [ ] CCPA (opt-out of data sale)
- [ ] SOC 2 (controls, audit trail)
### Incident Response
- [ ] Incident response plan
- [ ] On-call rotation
- [ ] Communication plan
### Security Testing
- [ ] SAST (Gosec, cargo audit, ESLint)
- [ ] DAST (OWASP ZAP, Burp Suite)
- [ ] Dependency scanning (Dependabot)
- [ ] Penetration testing (quarterly)
- [ ] Bug bounty program
## 📊 MÉTRIQUES DE SUCCÈS
### Security KPIs
- **Vulnerability Response Time**: < 24 hours (critical), < 7 days (high)
- **Incident Detection Time**: < 15 minutes
- **Incident Response Time**: < 1 hour (containment)
- **Password Strength**: 100% compliant (min 12 chars, complexity)
- **MFA Adoption**: > 90% (admin/moderator), > 50% (all users)
- **Failed Login Rate**: < 1%
- **Unauthorized Access Attempts**: 0 successful
- **Security Scan Coverage**: 100% codebase
- **Critical Vulnerabilities**: 0 in production
## 🔄 HISTORIQUE DES VERSIONS
| Version | Date | Changements |
|---------|------|-------------|
| 2.0.0 | 2026-03-04 | Révision éthique Corrections P0 JWT (VEZA-SEC-001, VEZA-SEC-002), migration RS256 planifiée (Phase 3.5), section éthique des données, protection routes Prometheus, pentest externe avant Phase 4R, durées de rétention révisées |
| 1.0.0 | 2025-11-02 | Version initiale - Framework sécurité complet |
---
## ⚠️ AVERTISSEMENT
**CE FRAMEWORK EST IMMUABLE**
Les contrôles de sécurité définis ici sont **OBLIGATOIRES**. Toute modification nécessite:
1. **RFC Security Change** avec threat analysis
2. **Approbation CISO** (ou CTO si pas de CISO)
3. **Penetration testing** après modification
4. **Update documentation**
**Contournement des contrôles de sécurité est STRICTEMENT INTERDIT.**
---
**Document créé par**: Security Team + Architecture
**Date de création**: 2025-11-02
**Dernière révision**: 2026-03-04 (révision éthique post-audit)
**Prochaine révision**: Trimestrielle
**Propriétaire**: CISO / Lead Security Engineer
**Statut**: **APPROUVÉ ET VERROUILLÉ**