Files
tfm_ainventory/dev_docs/SECURITY_REPORT.md
Daniel Bedeleanu 247ea45408 security: audit complet + patch vulnerabilitati critice v1.3.5
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>
2026-04-11 13:20:05 +03:00

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ă:

  1. Verificați git log --all -- backend/.env pentru a vedea dacă fișierul a fost committed.
  2. Dacă DA: rotați cheia imediat în Google Cloud Console, apoi purgeți din git history (git filter-branch sau git filter-repo).
  3. Asigurați-vă că backend/.env este în .gitignore (verificat — .gitignore există, 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 LDAP
  • POST /users/test-ldap — testează conexiuni LDAP arbitrare (SSRF potențial)
  • GET /users/ — enumerare completă utilizatori
  • POST /users/ — creare utilizator cu orice rol (inclusiv admin)
  • 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).