1. Introduzione
Hermes Console (di seguito "Hermes") è uno strumento di audit e remediation statici per repository software. Produce un documento strutturato (PDF + Markdown) con: descrizione funzionale del codice del cliente, vulnerabilità reali nelle dipendenze, rischi dedotti dal codice, proposte concrete di rimedio.
Questo whitepaper descrive:
- il modello di minaccia per la piattaforma Hermes;
- il ciclo di vita del codice del cliente dentro Hermes (ingresso, elaborazione, persistenza, output, cancellazione);
- i controlli tecnici e organizzativi implementati;
- la posizione rispetto a ISO/IEC 27001:2022 e alla Direttiva NIS2.
Pubblico target: procurement, DPO, security officer, compliance officer che valutano l'adozione di Hermes da parte di un soggetto regolato (NIS2-scope, GDPR personal data, settore finanziario o sanitario, PA).
2. Scope & architettura
Hermes è un'applicazione web (Next.js) servita su HTTPS pubblico, con un
database PostgreSQL dedicato e un engine TypeScript puro
(@oasi/hermes-core). Il deployment standard è in modalità SaaS su
infrastruttura controllata da OASI S.r.l.
Sono disponibili due ulteriori modalità per clienti con requisiti di sovranità più stringenti:
- Upload mono-shot (.zip/.tar.gz, sandbox temporanea, cancellazione entro 1 ora dall'analisi);
- On-prem (Docker Compose installato dentro la DMZ del cliente, swap del provider LLM verso Bedrock/Vertex/Ollama on-prem).
Le modalità on-prem e Hermes Agent (binary desktop) sono in roadmap commerciale; questo whitepaper riguarda la modalità SaaS.
3. Threat model
3.1 Asset protetti
| Asset | Sensibilità | Classificazione |
|---|---|---|
| Codice sorgente del cliente (clone temporaneo) | Critica | confidential / restricted |
| Risultato analisi (JSON con scopo, rischi, vuln) | media | confidential |
| Discovery Report (PDF/MD) | media — consegnabile al cliente | confidential |
| Credenziali servizio: deploy key SSH, PAT GitHub | Critica | secret |
| Sessioni operatore: JWT, refresh, WebAuthn credentials | alta | secret |
| Audit log | alta — integrità | restricted |
3.2 Attori e capacità
| Attore | Capacità | Trust |
|---|---|---|
| Operatore OASI (ADMIN, superAdmin) | tutto, cross-tenant | massima |
| Operatore cliente (ADMIN tenant-scoped) | solo dati del proprio tenant | alta |
| Operatore cliente (OPERATOR/VIEWER) | sola lettura su proprio tenant | media |
| Visitatore non autenticato | landing + /legal/* | nulla |
| Subprocessor: Anthropic | corpus di codice limitato al solo CodeComprehender/RemediationPlanner | contrattuale (DPA) |
| Subprocessor: Stripe (se attivo) | metadata di billing, mai dati cliente | contrattuale (DPA) |
| Provider hosting | accesso fisico al disco | contrattuale + cifratura at-rest |
3.3 Vettori di minaccia considerati
- Esposizione codice cliente verso terzi → cifratura at-rest + minimizzazione (LLM riceve solo i file selezionati); cancellazione clone in
finally. - Compromissione credenziali servizio → cifratura AES-256-GCM con scrypt-derived key, mai in clear, mai loggate.
- Privilege escalation tra tenant → guard
canAccessTenantsu ogni route ID-based, filtrotenantWheresu ogni query list, 404 (non 403) per evitare leak di esistenza. - Compromissione sessione operatore → WebAuthn passkey only (no password riusabili), JWT a 15 min, step-up per azioni sensibili, audit log indelebile.
- Iniezione via input malformato → input validation Zod su ogni POST body; SQL via Prisma ORM o
$queryRawparametrizzato; HTML output via React (auto-escape). - Compromissione webhook billing → HMAC-SHA256 con timing-safe compare e tolleranza 5 min.
- Cross-Site Request Forgery → cookie
SameSite=strict,Secure,HttpOnly; refresh in cookie separato.
3.4 Out of scope (esplicito)
- DDoS layer-7 (mitigazione presso reverse proxy / CDN, non a layer applicativo).
- Attacchi fisici al data center (responsabilità provider hosting; vedi Subprocessor list).
- Vulnerabilità nei dispositivi degli operatori (responsabilità del cliente e delle policy MFA dei suoi laptop).
- Vulnerabilità nei nodi Anthropic (responsabilità contrattuale di Anthropic, DPA di riferimento).
4. Controlli tecnici implementati
4.1 Crittografia
| Risorsa | Schema | Riferimento codice |
|---|---|---|
| Deploy key SSH (per repo) | AES-256-GCM, key=scrypt(REPO_DEPLOY_KEY_SECRET, salt-per-blob, 32), IV 12B, AuthTag | src/lib/hermes/repo-key.ts |
| PAT GitHub (per repo) | stesso schema della deploy key | src/lib/hermes/repo-key.ts |
| Access JWT | HS256 (HMAC-SHA256), JWT_ACCESS_SECRET, exp 15 min | @oasi/admin-shell/session.ts |
| Refresh token | crypto.randomBytes(48), sha256 hex hash in DB, exp 30 giorni | @oasi/admin-shell/session.ts |
| Recovery code (10×) | bcryptjs SALT_ROUNDS=11 | @oasi/admin-shell/recovery.ts |
| Invite token | crypto.randomBytes(32).toString("hex"), exp 15 min | @oasi/admin-shell/invite.ts |
| Stripe webhook | HMAC-SHA256 (STRIPE_WEBHOOK_SECRET), tolleranza 5 min, timing-safe | src/app/api/billing/webhook/route.ts |
| In transito (UI + API) | TLS 1.2+ (Let's Encrypt sul reverse proxy nginx) | deploy/nginx/* |
| At-rest (DB) | demandato a Postgres + volume cifrato lato hosting | provider hosting |
4.2 Autenticazione e gestione sessione
- Solo passkey (WebAuthn). Nessuna password riutilizzabile in alcun flusso.
- Step-up richiesto per azioni elevate (Apply→PR, .patch, gestione PAT).
- Recovery codes consegnati una sola volta al primo login; conservati come hash bcrypt.
- Bruteforce protection: tabella
HermesLoginAttempttraccia gli attempts; dopo soglia configurabile rate-limit per IP. - Logout: revoca refresh in DB (
HermesSession.revokedAt), invalida cookie.
4.3 Multi-tenancy e segregazione dati
- Schema relazionale: ogni risorsa client-derived (HermesRepo, HermesDiscovery, HermesAuditLog) ha FK
tenantIdNOT NULL →HermesTenant. - Filtro a livello applicativo: helper
tenantWhere(ctx)su ogni queryfindMany;canAccessTenant(ctx, id)su ogni route ID-based. - Cross-tenant solo a operatori OASI con
superAdmin: true. Toggle solo via UI/tenantscon doppio guardrail (no self-demote, no rimozione ultimo superAdmin attivo). - Audit cross-tenant: ogni evento di modifica plan tenant è loggato con
action: tenant.update+ difffrom→to.
4.4 Audit logging
- Indelebile a livello applicativo:
HermesAuditLogè append-only (nessuna route fornisce DELETE). - Coverage: ogni mutating action passa per
logAudit(...)conuserId,tenantId,action,target,ip,userAgent,success,metadata. Vedi tassonomia in §6. - Retention DB: nessuna policy automatica di purga → conservato per tutta la vita del database (configurabile su richiesta cliente per esigenze legacy).
- Esposizione: lettura via UI
/audit(filtri action/success/target, scope per tenant).
4.5 Gestione segreti
deploy/.envcon permessi 600, gitignored.- Iniezione via STDIN → file 600 → SSH-pipe al box, mai in chat / mai in echo log. Pattern documentato in
deploy/STRIPE.md§5 e nel playbook interno. - Mai persistenza in repo: nessun
*.env.localcommittato;.gitignoreesplicita. - Rotazione:
REPO_DEPLOY_KEY_SECRETruotabile (la cifratura per-blob include il salt; ri-cifratura batch dei blob esistenti supportata, on-demand).JWT_ACCESS_SECRETruotabile (invalida tutte le sessioni → richiesto re-login). - Logs: scrubbing dei pattern
oauth2:[^@]+@nei messaggi d'errore Git per non leak-are PAT.
4.6 Input validation
zodsu ogni request body (POST/PATCH/DELETE).- Path traversal: rifiuto esplicito di
..nei path locali di Discovery (if (repo.includes("..")) throw ...). - Path UUID-ish:
/^[0-9a-fA-F-]{36}$/prima di cast Prisma (no SQL injection via raw cast). - HTML output: React auto-escape; nessun
dangerouslySetInnerHTMLsu input utente. - Markdown legal: rendering server-side con
react-markdown(no eval).
4.7 Subprocess sandboxing
- Hermes esegue tool esterni (
git,osv-scanner,ssh-keygen) viaChildProcessRunnercon:- timeout esplicito (default 60-180s per operazione);
maxBuffer: 16 MBper output;- working directory
mkdtemptemporanea; - cleanup in
finally(rm -rf).
- L'
InstrumentationApplierhaforbidden_targetsconfigurabile (default vuoto in modalità SaaS; in onboarding template =["master","main"]per evitare PR direttamente in produzione).
5. Ciclo di vita del codice del cliente
5.1 Ingresso (clone)
Il codice entra in Hermes via uno di questi canali:
- HTTPS clone con PAT (per Apply→PR su GitHub) — URL
oauth2:<PAT>@host/owner/name.git, durata transitiva (clone in temp dir, deletion immediata dopo l'apply). - SSH clone con deploy key (per Discovery, .patch) — chiave materializzata su temp file 0600, scoped via
GIT_SSH_COMMAND, eliminata dopo il clone. - Path locale assoluto (per Discovery su filesystem del box) — nessuna copia, lettura diretta.
In tutti i casi: temp dir creata con mkdtemp(join(tmpdir(), "hermes-...")), cancellata in finally indipendentemente dall'esito.
5.2 Elaborazione
| Stadio | Cosa fa | Cosa esce dal box |
|---|---|---|
StackDetector | lettura manifest, regex sui file source | nulla |
LocCounter | conta newline su file source | nulla |
VulnScanner (osv-scanner) | invio dei nomi+versioni delle dipendenze al servizio osv.dev (HTTPS) | nomi pacchetto + versioni (no codice cliente) |
CodeComprehender | invio dei top-N file source selezionati ad Anthropic | estratti di codice sorgente del cliente |
RemediationPlanner | invio degli stessi file + lista rischi ad Anthropic | estratti di codice sorgente del cliente |
InstrumentationPlanner | logica deterministica sul StackReport | nulla |
InstrumentationApplier (mode "pr") | scrittura file + commit + push + apertura PR | nuovi file scritti su un branch del repo cliente (su GitHub) |
InstrumentationApplier (mode "patch") | scrittura file + git diff | nulla — solo restituzione locale del .patch |
5.3 Persistenza
HermesDiscovery.report/vulnReport/comprehension/remediationsono artifact dell'analisi, NON il codice sorgente. Tuttavia possono contenere estratti di codice (es. snippet incriminato nelle proposte di rimedio).- Retention default: vita del database. Cancellazione singola Discovery via API (in roadmap); cancellazione massiva su richiesta cliente o termine contratto.
5.4 Output e consegna
- PDF (carta intestata OASI) e Markdown restituiti via TLS all'operatore. Nessuna memoria temporanea persistente lato server (rendering on-demand).
- PR su GitHub: contenuti già accessibili al cliente (è il suo repo).
- .patch: download diretto, scaricato e poi gestito dal cliente in locale.
5.5 Cancellazione
- Clone temporaneo:
rm -rfinfinallydi ogni endpoint (/api/hermes/discovery,apply,patch). - Dati persisitti: cancellazione contestuale alla cancellazione del tenant (
onDelete: Restrictpreviene cancellazioni accidentali; il superAdmin deve disabilitare prima). - Backup DB: vedi Subprocessor list (provider hosting) e DPA.
6. Tassonomia degli eventi audit
Eventi tracciati con action standardizzata:
| action | Cosa traccia |
|---|---|
login.success / login.fail | login passkey |
register.success | registrazione passkey |
recovery.* | uso recovery code |
discovery.run | esecuzione Discovery (success+failure, con primaryStack/durationMs) |
discovery.blocked_loc | rifiuto FREE > 3000 LOC |
discovery.apply | Apply→PR (success+failure, con pr_url) |
discovery.patch | scarico .patch (success+failure, con patch_bytes) |
repo.register / repo.verify / repo.set_token | gestione repo registrati |
tenant.create / tenant.update | gestione tenant (superAdmin) |
user.update | modifiche per-utente (con diff from→to) |
invite.create | invito utente in tenant |
billing.webhook | eventi Stripe webhook (success+failure, eventType+eventId) |
Ogni evento è correlato a userId + tenantId (NULL solo per azioni di sistema pre-login).
7. Disaster Recovery & Business Continuity
- Backup DB: snapshot giornaliero gestito dal provider hosting (frequenza e RPO/RTO definiti nel DPA con il cliente; RPO target ≤24h, RTO target ≤4h per modalità SaaS standard).
- Recovery test: procedura documentata internamente, eseguita ad ogni release maggiore.
- Monitoring esterno: status page pubblica a
status.oasi.systems(Upptime, GitHub Actions cron 5 minuti). Uptime + response time + incident history pubblici. Indipendente dall'infrastruttura monitorata (se il box muore, il monitor se ne accorge). Notifiche automatiche asecurity@oasi.systemssu downtime >5 min. - Multi-region: non incluso nel piano base SaaS; disponibile su modalità Enterprise (DR-aware).
- Code & build: tutto il source code è in repository Git versionato; ogni release è ricostruibile dal commit Git corrispondente (vedi footer commit hash su /legal).
8. Incident response
- Detection: monitoraggio applicativo (logs, status codes, audit anomalies) + alerting infrastrutturale (provider hosting).
- Triage: classificazione interna (P0 = data exposure / P1 = service down / P2 = degraded).
- Comunicazione:
security@oasi.systemsper il cliente; obbligo di notifica entro 24-72h ai sensi del GDPR Art. 33 (se applicabile) e NIS2 Art. 23 (early warning). - Post-mortem: documento pubblicato (anonimizzato) in caso di incidenti P0/P1.
9. Vulnerability disclosure
OASI accetta segnalazioni responsabili di vulnerabilità via
security@oasi.systems, idealmente PGP-encrypted. Tempistica di
gestione:
- ack entro 48h;
- assessment entro 5 giorni lavorativi;
- fix per vulnerabilità critiche entro 14 giorni;
- public disclosure coordinata con il segnalante.
10. Posizione rispetto a ISO/IEC 27001:2022
Hermes è aligned allo standard ISO/IEC 27001:2022. Il Statement of
Applicability (vedi pagina dedicata /legal/iso27001-soa) mappa i 93
controlli dell'Annex A allo stato attuale (implementato / parzialmente
/ N/A con motivazione).
Hermes non è ancora certificato da ente accreditato. La certificazione formale è programmata in funzione del raggiungimento delle soglie commerciali (€100k+ ARR). Fino ad allora, la posizione è ISO27001-aligned, autocertificata: la documentazione (questo whitepaper + SoA + DFD + DPA + Subprocessor list) è prodotta secondo i requisiti dello standard ed è disponibile per audit indipendente su richiesta sotto NDA.
11. Posizione rispetto a NIS2 (Direttiva UE 2022/2555)
OASI non è un soggetto NIS2-scope per sé (le soglie dimensionali e settoriali della direttiva non si applicano a Hermes come prodotto).
Hermes facilita la conformità del cliente in-scope rispetto a vari
punti dell'Art. 21(2) — vedi pagina dedicata
/legal/nis2-mapping per il mapping puntuale (in particolare lettere
d, e, f, h sulla supply-chain e gestione vulnerabilità).
12. Contatti
- Sicurezza:
security@oasi.systems - Privacy / DPO:
privacy@oasi.systems - Procurement / Sales:
hermes@oasi.systems - Vulnerability disclosure:
security@oasi.systems(PGP su richiesta)
Versione 1.0 — pubblicata insieme al commit Git riportato nel footer.
La cronologia delle modifiche è ricostruibile via git log apps/hermes-console/src/app/legal/whitepaper/. Aggiornamenti maggiori
sono comunicati ai clienti attivi via email.