Cosa facciamo.

Una revisione interna strutturata contro una checklist consolidata, ogni trimestre, più immediatamente dopo qualsiasi aggiornamento di dipendenza non banale o cambiamento sulle superfici di autenticazione. La checklist segue il framework OWASP ASVS Level 2 + OWASP API Security Top 10 — non rivendichiamo certificazione, ma riprendiamo verbatim le domande del framework dove utile. Ogni passaggio produce un report datato committato nel repository, supportato da percorsi di file e file di test; i rilievi sono o risolti in un commit referenziato o accettati come rischio residuo con motivazione.

  • Checklist principale — otto aree: autenticazione e sessione, viewer pubblico + endpoint JSON-LD, percorsi di scrittura del dashboard, archiviazione, domini personalizzati, dipendenze, segreti, logging e monitoraggio.
  • Revisione trimestrale — ogni riga supportata nel file con percorsi e file di test; pass / parziale / fallimento per riga. Rilievi o risolti in un commit referenziato o accettati esplicitamente come rischio residuo con motivazione.
  • Igiene delle dipendenzepip-audit a ogni passaggio. requirements.txt bloccato senza intervalli di versione; gli aggiornamenti sono deliberati e testati.

I controlli portanti.

Affermazioni concrete e verificabili — ognuna è una proprietà di codice o configurazione che un revisore può controllare.

  • Cifrato in transito. TLS su ogni superficie pubblica (qrregistry.io, qrregistry.eu, viewer su domini personalizzati) tramite Caddy con emissione certificati on-demand. Il cookie di sessione è HttpOnly + Secure + SameSite=Lax.
  • Cifrato a riposo. PostgreSQL + MinIO su hardware UE con cifratura del disco.
  • Niente password. Solo magic-link. Il token grezzo è ~256 bit di entropia CSPRNG, scade in 15 minuti e viene consumato al primo uso; il database memorizza solo un hash SHA-256, quindi una lettura del database da sola non può autenticare nessuno.
  • Autenticazione differenziata per pubblico. Le credenziali di auditor / riciclatore / riparatore / organismo notificato sono JWT a breve durata revocabili da un'unica console admin; la revoca ha effetto alla richiesta successiva, non alla scadenza del JWT.
  • Percorsi di scrittura con verifica di proprietà. Ogni scrittura su passaporti, attestazioni, domini e asset è protetta lato server da row.user_id == user.id. Le righe di altri utenti restituiscono 404 invece di 403 — non riveliamo l'esistenza.
  • Filtro Restricted-tier. Una singola funzione (strip_to_visible) regola ogni superficie del passaporto — viewer HTML, endpoint JSON-LD, feed di audit, PDF. Nessun campo può trapelare attraverso un ramo che gli altri nascondono.
  • Catena di audit append-only. Ogni salvataggio scrive una riga passport_revisions con hash_before / hash_after / diff strutturato. DELETE /dashboard/passports/{id} restituisce incondizionatamente 403 — articolo 10(4) persistenza a vita.
  • Allowlist domini personalizzati. L'endpoint TLS on-demand «ask» di Caddy è bound al loopback e consulta la tabella dei domini verificati; solo gli hostname verificati e provisionati ottengono un certificato. Invariante single-claim — un hostname può appartenere a un solo proprietario.
  • Disciplina dei segreti. Nessun segreto nel sorgente. .env è l'unico inventario; le variabili per servizio (database, Stripe, Resend, MinIO) sono indipendenti.
  • Analytics rispettoso della privacy. Gli eventi di scansione registrano un codice paese ISO (derivato dall'header, mai l'IP grezzo) e una classe di dispositivo grossolana — mai un cookie di tracciamento, mai un'identità credenziale. Documentato e visibile sotto /privacy.

Cosa esplicitamente non facciamo.

Non paghiamo un test di penetrazione di terze parti finché il gate di acquisto di un cliente non lo rende un costo giustificato. L'articolo 11(h) ESPR non definisce un percorso di certificazione e non impone test di terze parti; commissionare un incarico da 15-30k € compra credibilità ma nessun <code>✅</code> regolatorio, e la revisione interna datata documenta gli stessi elementi probatori a costo inferiore mentre l'azienda è piccola.

Non rivendichiamo certificazioni SOC 2 o ISO 27001. La postura del nostro fornitore di infrastruttura è dietro la riga del footer <em>«ISO 27001 aligned»</em>; la certificazione appartiene a loro, non a Contenza K/S.

Non fingiamo che una revisione pulita sia l'assenza di rilievi. La revisione del 2026-04-30 evidenzia cinque righe 🟡 parziale — quattro sono CVE di dipendenze con versioni correttive disponibili tracciate come bump successivo, e una è un rate-limit a livello applicativo rinviato. Onesto è più utile di aspirazionale.

Cosa potete leggere.

  • La checklist principale risiede in docs/security-review-checklist.md nel repository sorgente — ogni riga è una domanda a cui la prossima revisione dovrà rispondere con prove.
  • Ogni revisione datata risiede in docs/security-review-{YYYY-MM-DD}.md — percorsi di file, file di test e rilievi, nel file. La cronologia git mostra cosa è cambiato tra i passaggi.
  • Ogni affermazione pubblica su questa pagina mappa una riga della revisione più recente.

Segnalare una vulnerabilità.

Inviate un'email al team con i dettagli. Trattiamo le segnalazioni di sicurezza come priorità e rispondiamo entro un giorno lavorativo. Non c'è ancora un programma formale di bug bounty — alla nostra scala, il riconoscimento è un grazie sentito e una menzione nel changelog.

Domande su questa politica? Usate il modulo di contatto — oppure scrivete al team tramite i recapiti della pagina contatti.