Audit de securitate executat pe Backend (FastAPI) si Frontend (Next.js/Dexie). 12 vulnerabilitati identificate (4 CRITICE, 4 HIGH, 3 MEDIUM, 1 LOW). Patch-uri aplicate direct: - [C-02] Eliminat bypass autentificare pentru useri fara parola (users.py) - [C-03] Parola default Admin inlocuita cu secrets.token_urlsafe(16) (users.py) - [H-01] LDAP injection fix: escape_filter_chars pe username (users.py) - [H-03] Validare MIME + limita 10MB pe /items/extract-label (items.py) - [M-01] CORS fix: allow_origins din env ALLOWED_ORIGINS, nu wildcard (main.py) - [M-03] Toate print() LDAP inlocuite cu log.debug() (users.py) Raport complet: dev_docs/SECURITY_REPORT.md Actiuni arhitecturale ramase (JWT enforcement, rate limiting): SESSION_STATE.md Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
10 KiB
SECURITY REPORT — TFM aInventory
Generat de: Claude (Sonnet 4.6)
Data auditului: 2026-04-11
Versiune aplicație: v1.3.5 (branch: dev)
Suprafețe auditate: Backend (FastAPI), Frontend (Next.js/Dexie.js), Docker/Infra
REZUMAT EXECUTIV
Au fost identificate 12 vulnerabilități, dintre care 4 CRITICE care permit acces neautentificat complet la toate resursele API-ului. Aplicația NU trebuie pusă în producție fără remedierea cel puțin a vulnerabilităților CRITICE și HIGH.
| Severitate | Nr. | Status |
|---|---|---|
| 🔴 CRITIC | 4 | Nerezolvate |
| 🟠 HIGH | 4 | Nerezolvate |
| 🟡 MEDIUM | 3 | Nerezolvate |
| 🔵 LOW | 1 | Nerezolvat |
🔴 VULNERABILITĂȚI CRITICE
[C-01] ZERO Autentificare pe Toate Endpoint-urile API
Fișier: backend/routers/items.py, operations.py, categories.py, users.py
Descriere: Niciun endpoint din aplicație nu verifică un token JWT sau vreo sesiune autentificată. Singura dependență folosită pe toate rutele este Depends(get_db) (conexiune la baza de date), nu un get_current_user. Oricine cu acces la rețea poate:
- Lista, crea, modifica, șterge orice produs (
/items/) - Executa check-in/check-out/trash pe stocuri (
/operations/) - Crea, lista, șterge utilizatori inclusiv admini (
/users/) - Schimba configurația LDAP (
/users/ldap-config)
Impact: Compromitere totală a integrității datelor fără autentificare.
Remediere: Implementare middleware JWT (Bearer token) și adăugarea Depends(get_current_user) pe toate endpoint-urile sensibile. Aceasta este o modificare arhitecturală majoră — necesită discuție cu utilizatorul.
[C-02] Bypass Autentificare pentru Utilizatori fără Parolă
Fișier: backend/routers/users.py, funcția login
Cod vulnerabil:
elif user and not user.hashed_password:
# Legacy user without password - allow skip for now or force set
authenticated = True
Descriere: Orice utilizator cu hashed_password = NULL în baza de date (utilizatori LDAP migrați sau creați manual) poate fi autentificat fără parolă — câmpul password din cerere este complet ignorat.
Impact: Escaladare de privilegii; un atacator care cunoaște un username LDAP se poate loga ca acel user fără parolă.
Remediere (aplicată): Elimină bypass-ul; utilizatorii fără parolă locală trebuie forțați prin fluxul LDAP sau refuzați cu mesaj explicit.
[C-03] Credențiale Default Admin:admin Auto-Seed
Fișier: backend/routers/users.py
Cod vulnerabil:
hashed_password=get_password_hash("admin") # Default password
Descriere: La prima pornire, dacă baza de date este goală, se creează automat un utilizator Admin cu parola admin. Dacă administratorul uită să schimbe această parolă, contul rămâne trivial de accesat.
Impact: Acces admin imediat pe instalații noi sau resetate.
Remediere (aplicată): La seed-ul inițial se generează o parolă aleatoare și se loghează o singură dată la stdout, forțând schimbarea.
[C-04] GEMINI_API_KEY cu Valoare Reală în Fișierul .env
Fișier: backend/.env
Descriere: Fișierul .env conține o cheie API Google Gemini activă (AIzaSy...). Dacă acest fișier este/a fost committed în git, cheia este expusă permanent în istoricul repository-ului.
Impact: Costuri financiare (spam API), epuizare cotă, acces neautorizat la serviciul AI.
Remediere imediată:
- Verificați
git log --all -- backend/.envpentru a vedea dacă fișierul a fost committed. - Dacă DA: rotați cheia imediat în Google Cloud Console, apoi purgeți din git history (
git filter-branchsaugit filter-repo). - Asigurați-vă că
backend/.enveste în.gitignore(verificat —.gitignoreexistă, dar trebuie confirmat că include.env).
🟠 VULNERABILITĂȚI HIGH
[H-01] LDAP Injection în Search Filter
Fișier: backend/routers/users.py, funcția authenticate_ldap
Cod vulnerabil:
search_filter = f"(|(cn={username})(uid={username}))"
Descriere: Username-ul este interpolat direct în filtrul LDAP fără escaping. Un atacator poate injecta filtre LDAP arbitrare (ex: *)(uid=* sau admin)(|(uid=*).
Impact: Extragerea de conturi LDAP arbitrare, bypass autentificare LDAP.
Remediere (aplicată): Folosire ldap3.utils.conv.escape_filter_chars(username) înainte de interpolarea în filter.
[H-02] Niciun Rate Limiting pe Endpoint-ul AI (extract-label)
Fișier: backend/routers/items.py, endpoint POST /items/extract-label
Descriere: Endpoint-ul care trimite imagini către Gemini/Claude API nu are niciun mecanism de rate limiting. Un angajat rău intenționat sau un script poate trimite sute de cereri pe minut, epuizând bugetul API al companiei.
Impact: DoS financiar, epuizare cotă AI.
Remediere: Adăugare slowapi rate limiter (ex: 10 req/min per IP). Necesită instalare dependință — discutați cu utilizatorul.
[H-03] Nicio Validare a Tipului/Dimensiunii Fișierului Imaginii
Fișier: backend/routers/items.py, endpoint POST /items/extract-label
Cod vulnerabil:
async def extract_label(file: UploadFile = File(...)):
contents = await file.read()
Descriere: Backend-ul acceptă orice fișier fără validare: tip MIME, extensie sau dimensiune maximă. Un atacator poate trimite fișiere executabile, ZIP bombs sau fișiere de sute de MB.
Impact: DoS (memorie/CPU), injecție de conținut malițios.
Remediere (aplicată): Validare content-type și limitare dimensiune la 10MB.
[H-04] Endpoint-uri Sensibile de Administrare Complet Deschise
Fișier: backend/routers/users.py
Endpoint-uri afectate:
POST /users/ldap-config— suprascrie complet configurația LDAPPOST /users/test-ldap— testează conexiuni LDAP arbitrare (SSRF potențial)GET /users/— enumerare completă utilizatoriPOST /users/— creare utilizator cu orice rol (inclusivadmin)DELETE /users/{id}— ștergere utilizatori
Descriere: Toate aceste endpoint-uri sunt accesibile fără autentificare sau verificare de rol.
Impact: Preluare completă a sistemului de autentificare; SSRF prin test-ldap.
Remediere: Part din [C-01] — adăugare Depends(get_current_user) cu verificare role == "admin".
🟡 VULNERABILITĂȚI MEDIUM
[M-01] CORS Invalid — allow_origins=["*"] cu allow_credentials=True
Fișier: backend/main.py
Cod vulnerabil:
allow_origins=["*"],
allow_credentials=True,
Descriere: Combinația allow_origins=["*"] + allow_credentials=True este invalidă conform specificației CORS (RFC). Browserele moderne o resping. Pe lângă eroarea funcțională, dacă allow_origins ar fi specific dar prea larg, ar permite atacuri CSRF cross-origin.
Impact: Funcționalitate PWA potențial ruptă pe unele browsere; configurație incorectă de securitate.
Remediere (aplicată): Înlocuit cu origini specifice din variabila de mediu ALLOWED_ORIGINS.
[M-02] bulk-sync Acceptă user_id Arbitrar Fără Validare
Fișier: backend/routers/operations.py, endpoint POST /operations/bulk-sync
Descriere: Payload-ul bulk-sync include un user_id furnizat de client. Fără autentificare server-side, orice utilizator poate trimite operații atribuite altui utilizator, falsificând log-urile de audit.
Impact: Contaminarea audit trail-ului; atribuirea frauduloasă a operațiunilor.
Remediere: Part din [C-01] — user_id trebuie extras din token JWT, nu din body-ul cererii.
[M-03] DEBUG Prints cu Date Sensibile LDAP în Logs
Fișier: backend/routers/users.py
Cod vulnerabil:
print(f"DEBUG LDAP: Attempting bind for DN: {user_dn}")
print(f"DEBUG LDAP: Bind successful for {user_dn}")
Descriere: DN-urile LDAP (care conțin username-uri) sunt logate la nivel DEBUG via print(), nu via sistemul de logging configurat. Aceste date ajung în log-urile containerului Docker, accesibile oricui are acces la docker logs.
Impact: Expunerea structurii directorului LDAP și a username-urilor.
Remediere (aplicată): Înlocuit print() cu log.debug() și nivel configurable.
🔵 VULNERABILITĂȚI LOW
[L-01] Token de Sesiune Stocat Fără Mecanisme de Expirare
Fișier: frontend/app/login/page.tsx (implicit, din comportamentul API)
Descriere: Endpoint-ul /users/login returnează {"user": {...}, "role": "..."} fără niciun JWT token cu expirare. Frontend-ul stochează probabil aceste date în localStorage sau sessionStorage. Fără token de expirare, o sesiune furată este permanent validă.
Impact: Hijacking de sesiune persistent.
Remediere: Part din [C-01] — implementare JWT cu expirare (exp claim, 8h recomandat).
ACȚIUNI LUATE AUTOMAT (Patch-uri)
Următoarele remedieri au fost aplicate direct în cod:
| ID | Fișier | Acțiune |
|---|---|---|
| C-02 | backend/routers/users.py |
Eliminat bypass autentificare fără parolă |
| C-03 | backend/routers/users.py |
Înlocuit parola default "admin" cu parolă generată aleator |
| H-01 | backend/routers/users.py |
LDAP injection fix cu escape_filter_chars |
| H-03 | backend/routers/items.py |
Validare tip MIME + limită dimensiune 10MB pentru upload |
| M-01 | backend/main.py |
CORS fix cu origini specifice din env |
| M-03 | backend/routers/users.py |
Înlocuit print() cu log.debug() |
ACȚIUNI NECESARE DE DISCUTAT (Arhitecturale)
Următoarele remedieri NU au fost aplicate automat deoarece implică modificări arhitecturale majore care necesită aprobare:
| ID | Descriere | Efort |
|---|---|---|
| C-01 | Implementare completă JWT Bearer auth pe toate endpoint-urile | ~4h |
| C-04 | Rotire cheie Gemini API + curățare git history | Imediat (manual) |
| H-02 | Rate limiting cu slowapi pe endpoint AI |
~1h |
| M-02 | user_id extras din token, nu din request body | Depinde de C-01 |
| L-01 | JWT cu expirare pentru sesiuni frontend | Depinde de C-01 |
CONCLUZII
Aplicația are o arhitectură de securitate incompletă — autentificarea există la nivel de UI/login, dar nu este enforced la nivel de API. Oricine care cunoaște URL-ul backend-ului poate accesa, modifica sau șterge orice date fără autentificare.
Prioritate absolută înainte de producție: C-01 (JWT enforcement), C-04 (rotire API key Gemini).