Ctrl K
ComunidadGuías…

SECURITY.md

Rama master · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# Security Policy

## Reporting a Vulnerability

If you discover a security vulnerability in Sublarr, please report it privately via
[GitHub Security Advisories](https://github.com/Abrechen2/Sublarr/security/advisories/new).

**Do not** open a public issue for security vulnerabilities.

Please include:
1. Description of the vulnerability
2. Steps to reproduce
3. Affected version(s)
4. Potential impact

We aim to acknowledge reports within 48 hours and provide a fix within 7 days for critical issues.

## Supported Versions

| Version | Supported |
|---------|-----------|
| 1.0.x | Yes — current stable |
| 0.9x-beta | Best-effort — please upgrade to 1.0 |
| < 0.31.x | No — missing critical security fixes |

## Security Architecture

### Authentication

Sublarr supports two authentication mechanisms:

1. **API Key Authentication** — Set via `SUBLARR_API_KEY` environment variable. All `/api/v1/` endpoints require the key in the `X-Api-Key` header. Enforced by a global `before_request` hook in `auth.py`.

2. **UI Session Authentication** — Browser-based login with bcrypt-hashed passwords. Session cookies use `HttpOnly`, `SameSite=Lax` flags. Minimum password length: 8 characters.

**Important:** At least one authentication mechanism must be enabled. If both `SUBLARR_API_KEY` is empty and UI auth is disabled, a startup warning is logged and all endpoints are publicly accessible.

### Rate Limiting

- Login endpoint: 5 requests/minute per IP
- API key auth failures: 20 failures/60s per IP
- Powered by `flask-limiter` with in-memory or Redis backend

### Input Validation

- **Path traversal prevention:** `is_safe_path()` applied on all file/path endpoints. Validates paths resolve within allowed directories using `os.path.realpath()`.
- **SSRF protection:** `validate_service_url()` blocks `file://`, `ftp://`, cloud metadata IPs (169.254.x.x), link-local addresses, and custom blocked hosts. Applied to all config URL fields and webhook URLs.
- **Git URL validation:** `validate_git_url()` enforces HTTPS-only and domain allowlist (`github.com`, `gitlab.com`, `codeberg.org`) for plugin installations.
- **Config validation:** Enum fields validate against allowed values, string fields enforce max length (4096 chars).

### Injection Prevention

- **SQL Injection:** All database queries use SQLAlchemy ORM with parameterized queries. No raw SQL with user input.
- **XSS Prevention:** Subtitle files are sanitized before display — ASS/SSA files have Lua scripts and drawing commands stripped, SRT/VTT files have HTML tags sanitized.
- **Command Injection:** No user-supplied data reaches shell calls. External tools (mkvmerge, ffmpeg) receive arguments as list parameters, not shell strings.
- **Prompt Injection:** LLM translation inputs have subtitle lines escaped to prevent embedded newlines from manipulating the prompt structure.

### File Handling

- **ZIP bomb protection:** 50 MB max uncompressed size, 100:1 compression ratio limit via `safe_zip_extract()`.
- **ZIP Slip prevention:** All archive members validated against the target directory before extraction.
- **Subtitle sanitization:** ASS/SSA Lua script stripping, drawing-mode removal, SRT/VTT HTML tag sanitization.

### Cryptography

- **Password hashing:** bcrypt via `werkzeug.security.generate_password_hash()` / `check_password_hash()`
- **Timing-safe comparison:** `hmac.compare_digest()` for API key and webhook signature verification
- **Webhook signatures:** HMAC-SHA256 with per-instance secret keys

### HTTP Security Headers

Applied to all responses via `@app.after_request`:
- `X-Frame-Options: DENY`
- `X-Content-Type-Options: nosniff`
- `Referrer-Policy: same-origin`
- `Content-Security-Policy` (script-src self, style-src self unsafe-inline)
- `Permissions-Policy` (camera=(), microphone=(), geolocation=())

### Network Security

- **Webhook URL validation:** Blocks RFC1918 ranges and localhost to prevent SSRF
- **Provider download URLs:** Domain allowlist per provider to prevent SSRF via compromised provider APIs
- **Docker container:** Runs as non-root user (`sublarr`), single exposed port (5765)

### Circuit Breaker

Per-provider and per-backend failure isolation using a CLOSED → OPEN → HALF_OPEN state machine with configurable threshold and cooldown. Prevents cascading failures from affecting the entire system.

## Penetration Testing History

Sublarr has undergone three rounds of authorized penetration testing:

| Round | Date | Version | Tester | Findings |
|-------|------|---------|--------|----------|
| 1 | 2026-03-16 | 0.30.0-beta | Kali Linux | 11 findings (F-01 to F-11) |
| 2 | 2026-03-16 | 0.30.0-beta | Kali Linux | 5 findings (F-12 to F-16) |
| 3 | 2026-03-22 | 0.34.0-beta | BlackArch | 9 findings (F-17 to F-25) |

### Resolution Status

| Severity | Total | Fixed | Accepted | Open |
|----------|-------|-------|----------|------|
| CRITICAL | 4 | 4 | 0 | 0 |
| HIGH | 5 | 5 | 0 | 0 |
| MEDIUM-HIGH | 4 | 4 | 0 | 0 |
| MEDIUM | 5 | 4 | 1 (F-05) | 0 |
| LOW | 4 | 2 | 2 (F-08, F-15) | 0 |
| INFO | 3 | 0 | 3 | 0 |

All CRITICAL, HIGH, and MEDIUM-HIGH findings have been fixed as of v0.35.0-beta.

## Accepted Risks

| ID | Description | Rationale |
|----|-------------|-----------|
| F-05 | Webhook middleware exemption | By design — webhook paths use per-handler HMAC verification instead of global API key auth. Documented in `auth.py`. |
| F-08 | Socket.IO handshake unauthenticated | EIO4 open frame leaks only transport parameters (pingTimeout, pingInterval). Namespace connect is correctly rejected without auth. |
| F-15 | Internal network topology in config | Sublarr is an internal self-hosted tool. Config endpoint is auth-gated. Internal IPs in config values are expected and necessary for operation. |

## Confirmed Safe

The following attack vectors have been tested and confirmed mitigated:

- SQL Injection (parameterized queries)
- Path Traversal (`is_safe_path()` on all file endpoints)
- Command Injection (no user data in shell calls)
- ZIP Slip (`safe_zip_extract()` validates all members)
- CORS Misconfiguration (no wildcard origin, no credentials)
- CSRF (JSON-only POST endpoints, CORS blocks cross-origin)
- Timing Attacks (`hmac.compare_digest()`)
- HTTP TRACE (disabled, returns 405)

## Security Configuration Checklist

For production deployments:

- [ ] Set `SUBLARR_API_KEY` to a strong random value (32+ chars)
- [ ] Enable UI auth with a strong password (8+ chars)
- [ ] Use a reverse proxy with HTTPS termination
- [ ] Restrict network access to trusted networks
- [ ] Set `SUBLARR_LOG_LEVEL=WARNING` to reduce log verbosity
- [ ] Regularly update to the latest version
- [ ] Review Docker container permissions (PUID/PGID)