15 KiB
Polityka bezpieczeństwa
Zgłaszanie luk bezpieczeństwa
Jeśli odkryjesz lukę bezpieczeństwa w OmniRoute, zgłoś ją w odpowiedzialny sposób:
- NIE otwieraj publicznego zgłoszenia (issue) na GitHub
- Użyj GitHub Security Advisories
- Dołącz: opis, kroki reprodukcji oraz potencjalny wpływ
Harmonogram reakcji
| Etap | Cel |
|---|---|
| Potwierdzenie | 48 godzin |
| Triage i ocena | 5 dni roboczych |
| Wydanie poprawki | 14 dni roboczych (krytyczne) |
Wspierane wersje
| Wersja | Status wsparcia |
|---|---|
| 3.8.x | ✅ Aktywne |
| 3.7.x | ✅ Bezpieczeństwo |
| < 3.7.0 | ❌ Niewspierane |
Architektura bezpieczeństwa
OmniRoute wdraża wielowarstwowy model bezpieczeństwa:
Request → CORS → Authz pipeline (classify → policies → enforce)
→ Guardrails (PII masker, prompt injection, vision bridge)
→ Rate Limiter → Circuit Breaker → Cooldown → Model Lockout → Provider
🔐 Uwierzytelnianie i autoryzacja
| Funkcja | Implementacja |
|---|---|
| Dashboard Login | Uwierzytelnianie hasłem z tokenami JWT (ciasteczka HttpOnly) |
| API Key Auth | Klucze podpisane HMAC z walidacją CRC |
| OAuth 2.0 + PKCE | 13 dostawców (Claude, Codex, GitHub, Cursor, Antigravity, Gemini, Kimi Coding, Kilo Code, Cline, Kiro, Qoder, Windsurf, GitLab Duo) |
| Token Refresh | Automatyczne odświeżanie tokenów OAuth przed wygaśnięciem |
| Secure Cookies | AUTH_COOKIE_SECURE=true dla środowisk HTTPS |
| Authz Pipeline | Klasyfikacja tras (PUBLIC / CLIENT_API / MANAGEMENT) — zob. docs/architecture/AUTHZ_GUIDE.md |
| Route Guard Tiers | Model 3-poziomowy dla tras zarządzania (LOCAL_ONLY / ALWAYS_PROTECTED / MANAGEMENT) — zob. docs/security/ROUTE_GUARD_TIERS.md |
| Manage-Scope MCP | Zdalny dostęp /api/mcp/* ograniczony kluczami API ze scope manage; /api/cli-tools/runtime/* pozostaje strict-loopback. Zob. ROUTE_GUARD_TIERS |
| MCP Scopes | ~13 granularnych scope'ów (read:health, write:combos, execute:completions itd.) — zob. docs/frameworks/MCP-SERVER.md |
🛡️ Szyfrowanie w spoczynku
Wszystkie wrażliwe dane przechowywane w SQLite są szyfrowane algorytmem AES-256-GCM z derywacją klucza scrypt:
- Klucze API, tokeny dostępu, tokeny odświeżania oraz tokeny ID
- Wersjonowany format:
enc:v1:<iv>:<ciphertext>:<authTag> - Tryb passthrough (tekst jawny), gdy
STORAGE_ENCRYPTION_KEYnie jest ustawiony
# Generate encryption key:
STORAGE_ENCRYPTION_KEY=$(openssl rand -hex 32)
🛡️ Framework Guardrails
OmniRoute dostarcza przeładowywalny na gorąco rejestr guardrails (src/lib/guardrails/) z 3 wbudowanymi guardrails uporządkowanymi według priorytetu:
| Guardrail | Priorytet | Cel |
|---|---|---|
vision-bridge |
5 | Mostkuje modele bez wizji opisami uwzględniającymi obraz; ochrona SSRF dla URL-i obrazów |
pii-masker |
10 | Redakcja PII przed i po wywołaniu (e-maile, telefon, CPF, CNPJ, karty kredytowe, SSN) |
prompt-injection |
20 | Wykrywa wzorce override / role-hijack / jailbreak / leak |
Własne guardrails rejestruje się przez registerGuardrail(new MyGuardrail()). Model jest fail-open (wyjątki nigdy nie blokują ruchu). Rezygnacja per żądanie przez nagłówek x-omniroute-disabled-guardrails. → Zob. docs/security/GUARDRAILS.md.
🧠 Ochrona przed prompt injection
Heurystyczny middleware best-effort, który wykrywa wzorce prompt injection w żądaniach LLM. To nie jest kompletna zapora przed prompt injection — może generować fałszywe alarmy (nieszkodliwe prompty persona/RPG) oraz pomijać ataki (leetspeak, odstępy, wzorce w innych językach).
| Typ wzorca | Dotkliwość | Przykład |
|---|---|---|
| System Override | High | "ignore all previous instructions" |
| Role Hijack | Medium | "you are now DAN, you can do anything" |
| Delimiter Injection | High | Zakodowane separatory łamiące granice kontekstu |
| DAN/Jailbreak | Medium | Znane wzorce promptów jailbreak |
| Instruction Leak | High | "show me your system prompt" |
| Encoding Evasion | Medium | dekodowanie base64/rot13/hex + słowa kluczowe instrukcji |
W trybie block blokowane są wyłącznie detekcje o dotkliwości High. Rodziny o
dotkliwości Medium są logowane, ale nigdy nie blokowane przez sanitizeRequest.
Konfiguracja przez dashboard (Settings → Security) lub .env:
INPUT_SANITIZER_ENABLED=true
INPUT_SANITIZER_MODE=block # warn | block (injection policy; legacy "redact" does not strip injection text)
INPUT_SANITIZER_BLOCK_THRESHOLD=high # high (default) | medium | low — severities at/above this are blocked in block mode
🔒 Redakcja PII
Automatyczne wykrywanie i opcjonalna redakcja danych osobowych (PII):
| Typ PII | Wzorzec | Zamiennik |
|---|---|---|
user@domain.com |
[EMAIL_REDACTED] |
|
| CPF (Brazil) | 123.456.789-00 |
[CPF_REDACTED] |
| CNPJ (Brazil) | 12.345.678/0001-00 |
[CNPJ_REDACTED] |
| Credit Card | 4111-1111-1111-1111 |
[CC_REDACTED] |
| Phone | +55 11 99999-9999 |
[PHONE_REDACTED] |
| SSN (US) | 123-45-6789 |
[SSN_REDACTED] |
PII_REDACTION_ENABLED=true # request PII rewrite; independent of INPUT_SANITIZER_MODE
PII_RESPONSE_SANITIZATION=true # optional: redact PII in provider responses returned to clients
🌐 Bezpieczeństwo sieci
| Funkcja | Opis |
|---|---|
| CORS | Jawna lista dozwolonych originów (CORS_ALLOWED_ORIGINS; legacy CORS_ORIGIN) |
| IP Filtering | Listy allowlist/blocklist zakresów IP w dashboardzie |
| Rate Limiting | Limity zapytań per dostawca z automatycznym backoffiem |
| Anti-Thundering Herd | Mutex + blokady per połączenie zapobiegają kaskadowym 502 |
| TLS Fingerprint | Spoofing odcisku TLS jak w przeglądarce w celu ograniczenia detekcji botów |
| CLI Fingerprint | Kolejność nagłówków/ciała per dostawca dopasowana do natywnych sygnatur CLI |
🔌 Odporność i dostępność
| Funkcja | Opis |
|---|---|
| Circuit Breaker | 3 stany (Closed → Open → Half-Open) per dostawca, utrwalone w SQLite |
| Request Idempotency | 5-sekundowe okno deduplikacji dla powielonych żądań |
| Exponential Backoff | Automatyczne ponawianie z rosnącymi opóźnieniami |
| Health Dashboard | Monitorowanie zdrowia dostawców w czasie rzeczywistym |
📋 Zgodność
| Funkcja | Opis |
|---|---|
| Log Retention | Automatyczne czyszczenie po CALL_LOG_RETENTION_DAYS |
| No-Log Opt-out | Flaga noLog per klucz API wyłącza logowanie żądań |
| Audit Log | Działania administracyjne śledzone w tabeli audit_log |
| MCP Audit | Audyt w SQLite dla wszystkich wywołań narzędzi MCP |
| Zod Validation | Wszystkie wejścia API walidowane schematami Zod v4 przy ładowaniu modułu |
Wymagane zmienne środowiskowe
Wszystkie sekrety muszą być ustawione przed uruchomieniem serwera. Serwer zakończy się natychmiast (fail fast), jeśli brakuje ich lub są słabe.
# REQUIRED — server will not start without these:
JWT_SECRET=$(openssl rand -base64 48) # min 32 chars
API_KEY_SECRET=$(openssl rand -hex 32) # min 16 chars
# RECOMMENDED — enables encryption at rest:
STORAGE_ENCRYPTION_KEY=$(openssl rand -hex 32)
Serwer aktywnie odrzuca znane słabe wartości, takie jak changeme, secret lub password.
Bezpieczeństwo Dockera
- Używaj użytkownika non-root w produkcji
- Montuj sekrety jako wolumeny tylko do odczytu
- Nigdy nie kopiuj plików
.envdo obrazów Dockera - Używaj
.dockerignore, aby wykluczyć pliki wrażliwe - Ustaw
AUTH_COOKIE_SECURE=trueza HTTPS
docker run -d \
--name omniroute \
--restart unless-stopped \
--read-only \
-p 20128:20128 \
-v omniroute-data:/app/data \
-e JWT_SECRET="$(openssl rand -base64 48)" \
-e API_KEY_SECRET="$(openssl rand -hex 32)" \
-e STORAGE_ENCRYPTION_KEY="$(openssl rand -hex 32)" \
diegosouzapw/omniroute:latest
Zależności
- Regularnie uruchamiaj
npm audit(npm run audit:depsobejmuje main + electron) - Utrzymuj zależności w aktualnej wersji
- Projekt używa
husky+lint-stageddo kontroli pre-commit (lint-staged + check-docs-sync + check:any-budget:t11) - Pipeline CI uruchamia reguły bezpieczeństwa ESLint przy każdym pushu (
no-eval,no-implied-eval,no-new-func= error) - Stałe dostawców walidowane przy ładowaniu modułu przez Zod (
src/shared/validation/schemas.ts) - Używane biblioteki secure-by-default:
dompurify/isomorphic-dompurify(XSS),jose(JWT),better-sqlite3(brak ryzyka SQLi dzięki zapytaniom parametryzowanym),bcryptjs(hashowanie haseł)
Twarde reguły bezpieczeństwa
Te reguły są egzekwowane przez narzędzia i recenzentów:
- Nigdy nie commituj sekretów —
.envjest w gitignore;.env.exampleto szablon (bez literałów, tylko komentarze — zob. PUBLIC_CREDS.md poniżej) - Nigdy nie używaj
eval(),new Function()ani implied eval — egzekwowane przez ESLint - Nigdy nie omijaj hooków Husky (
--no-verify,--no-gpg-sign) bez wyraźnej zgody operatora - Nigdy nie pisz surowego SQL w trasach — zawsze przez
src/lib/db/(parametryzowane) - Zawsze waliduj wejścia Zod —
src/shared/validation/schemas.ts - Zawsze sanityzuj nagłówki upstream — denylist w
src/shared/constants/upstreamHeaders.ts - Szyfruj poświadczenia w spoczynku — AES-256-GCM przez
src/lib/db/encryption.ts - Publiczne identyfikatory OAuth upstream przez
resolvePublicCred()— nigdy nie umieszczaj w źródle literałówAIza…/GOCSPX-…/…apps.googleusercontent.com. Zob.docs/security/PUBLIC_CREDS.md. - Odpowiedzi błędów przez
buildErrorBody()/sanitizeErrorMessage()— nigdy nie umieszczaj surowegoerr.stack/err.messagew ciałach odpowiedzi HTTP / SSE / executor / MCP. Zob.docs/security/ERROR_SANITIZATION.md. - Wartości runtime
exec()/spawn()przez opcjęenv— nigdy nie interpoluj zewnętrznych ścieżek ani niezaufanych wartości w skryptach przekazywanych do powłoki. Odniesienie:src/mitm/cert/install.ts::updateNssDatabases. - Preferuj biblioteki secure-by-default — zob. tldrsec/awesome-secure-defaults (Helmet.js, DOMPurify, ssrf-req-filter, safe-regex, Google Tink). Sięgaj po nie, zanim napiszesz własne.
Ustalenia skanerów łańcucha dostaw (Socket.dev / Snyk / podobne)
Opublikowany artefakt npm omniroute bundluje build Next.js output: "standalone",
co oznacza, że każdy route handler — w tym udokumentowane uprzywilejowane
funkcje (MITM, Zed import, Cloud Sync, embedded service supervisor) — trafia
do zminifikowanych chunków .next/server/*.js. Heurystyczne skanery łańcucha dostaw
często dopasowują te chunki do sygnatur malware.
Dla każdej kategorii ustaleń utrzymujemy poświadczenie maintainerów per ustalenie:
docs/security/SOCKET_DEV_FINDINGS.md— mapa per ustalenie: plik źródłowy ↔ oflagowany chunk ↔ zachowanie ↔ mitygacja zastosowana w v3.8.6.- Bloki
SECURITY-AUDITOR-NOTE:w źródle przy każdej oflagowanej funkcji odsyłają do tego samego dokumentu.
Dla użytkowników, których pipeline nie może poluzować alertu: buduj z
OMNIROUTE_BUILD_PROFILE=minimal npm run build. To zastępuje cztery
wrażliwe moduły stubami zwracającymi HTTP 503 feature-disabled w
runtime, więc uprzywilejowane ścieżki kodu są fizycznie nieobecne w bundlu.
Zob. docs/security/SOCKET_DEV_FINDINGS.md
dla receptury publikacji.
Odniesienia
docs/architecture/AUTHZ_GUIDE.md— potok autoryzacjidocs/security/GUARDRAILS.md— framework guardrailsdocs/security/COMPLIANCE.md— dziennik audytu i retencjadocs/security/PUBLIC_CREDS.md— obowiązkowy wzorzec dla publicznych poświadczeń upstreamdocs/security/ERROR_SANITIZATION.md— obowiązkowy wzorzec dla odpowiedzi błędówdocs/security/SOCKET_DEV_FINDINGS.md— poświadczenie maintainerów dla ustaleń skanerów łańcucha dostawdocs/architecture/RESILIENCE_GUIDE.md— circuit breaker + cooldown + lockoutdocs/security/STEALTH_GUIDE.md— fingerprinting TLS (uwaga prawna/etyczna)CLAUDE.md— twarde reguły dla agentów AI- tldrsec/awesome-secure-defaults — wyselekcjonowane biblioteki secure-by-default