Il Quartz Tribunal — Audit di Sicurezza AI-Driven di Zenzic v0.7.0
"Assediato. Riparato. Sigillato."
Prima che uno strumento che garantisce l'integrità della documentazione possa definirsi stabile, deve affrontare un avversario che sa esattamente dove cercare le crepe. Questo è il resoconto di quell'incontro.
L'Obiettivo
La Safe Harbor Guarantee non è un'affermazione di marketing. È un contratto ingegneristico: se Zenzic esce con 0 ed emette il Sentinel Seal, il sorgente della documentazione è strutturalmente integro, completo nei link e privo di segreti. Quel contratto può essere considerato affidabile solo se il motore stesso è stato testato da un avversario, non solo dai suoi autori.
La Direttiva CEO 189 — "Il Mandato dell'Inquisitore" — ha commissionato un audit di sicurezza strutturato di Zenzic v0.7.0 prima del rilascio stabile. Tre team AI indipendenti sono stati assemblati. Il mandato: trovare ogni crepa nel Safe Harbor, ripararla, e certificare il risultato.
:::note Baseline 1.301 test al momento dell'audit (D094). 1.307 dopo che D095 ha sigillato tutte le Known Limitations. Zero fallimenti prima, zero dopo. L'audit ha reso Zenzic più forte di quanto fosse all'ingresso. :::
La Metodologia — Il Modello del Magistrato
L'audit ha utilizzato una struttura a tre team progettata per eliminare il bias di conferma:
| Team | Ruolo | Bias |
|---|---|---|
| 🔴 Red Team | Avversariale — trova ciò che lo Shield manca | Massima aggressività |
| ⚪ Blue Team | Difensivo — verifica che gli invarianti RULE reggano | Massimo rigore |
| 🟣 Purple Team | Arbitro Etico — separa bug reali dal rumore | Massima obiettività |
Nessun team era autorizzato a dichiarare un finding senza la revisione del Purple Team. Un finding che non avrebbe superato il controllo di obiettività veniva scartato come rumore. Solo i finding che sopravvivevano al Modello del Magistrato entravano nel Registro dei Bug.
La Cronaca dell'Assedio
D1 — Path Traversal via @site/ (Docusaurus)
Vettore: [config](@site/../../zenzic/pyproject.toml) — un link che tenta di
sfuggire dalla root della documentazione tramite l'alias @site/ di Docusaurus.
Risultato: Z202 PATH_TRAVERSAL rilevato. L'InMemoryPathResolver ha risolto il
percorso al di fuori del perimetro autorizzato e ha risposto correttamente.
Tuttavia, è stato scoperto un bug di severità: Z202 era mappato alla severità
"error" → exit 1 (sopprimibile con --exit-zero). Per RULE R4,
i codici di uscita 2 e 3 non sono mai sopprimibili. PATH_TRAVERSAL (Z202) deve
uscire con 3.
Correzione applicata: _check.py _to_findings() — la condizione di severità è
stata estesa per includere PATH_TRAVERSAL insieme a PATH_TRAVERSAL_SUSPICIOUS.
🔴 Red Team bloccato · ⚪ Bug di severità Blue Team sigillato · Exit 3. Non sopprimibile. ✅
D3 — Bypass Shield tramite Prop JSX
Vettore: <MyComponent apiKey="ghp_<EXAMPLE_TOKEN>" /> —
un GitHub PAT incorporato in un attributo di componente JSX, non in prosa Markdown grezza.
Ipotesi: Lo Shield potrebbe saltare i valori delle prop JSX poiché non sono prosa.
Risultato: Lo Shield ha rilevato ghp_ immediatamente. Exit 2. VIOLAZIONE DI SICUREZZA RILEVATA.
Lo Shield Pass 1A usa enumerate(fh, start=1) sui byte grezzi del file. Non salta mai
righe in base al tipo di contenuto. Le prop JSX sono testo semplice per lo scanner di
file. RULE R9 regge incondizionatamente.
🔴 Red Team bloccato · RULE R9 confermata. ✅
S2 — Segreto Frontmatter Codificato in Base64 → Sigillato in v0.7.0
Vettore: Campo YAML frontmatter api_token: Z2hwXzEy[…base64…] —
— un GitHub PAT codificato in Base64 memorizzato come valore di configurazione nel frontmatter.
Risultato D094: Lo Shield usciva con 0. Questo era documentato come Limitazione Nota KL-001.
Risoluzione D095: Decodifica Base64 speculativa implementata in shield.py (CEO-194).
Il decoder estrae token candidati da ogni riga normalizzata, decodifica ciascuno come UTF-8,
e ri-scansiona il testo decodificato attraverso la tabella completa dei pattern _SECRETS.
Il vettore di test canonico (Z2hwXzEy[…base64…] → ghp_[TOKEN]) ora attiva Z201 ed esce con 2.
Guardia contro falsi positivi: Una lunghezza minima del token di 20 caratteri (prima della decodifica) impedisce a brevi stringhe Base64 casuali di generare finding spurii.
🔴 Vettore di attacco Red Team SIGILLATO. KL-001 chiusa. Exit 2 confermato. ✅
Le Crepe Sigillate
| ID | Area | Finding | Correzione | Stato |
|---|---|---|---|---|
| BUG-CEO189-01 | cli/_check.py | Z202 esce con 1 invece di 3 (sopprimibile) | Condizione severità estesa a PATH_TRAVERSAL | ✅ Sigillato |
| BUG-CEO189-02 | suppression-policy.mdx EN+IT | Z106 erroneamente etichettato ALT_TEXT_MISSING | Corretto a CIRCULAR_LINK | ✅ Sigillato |
| BUG-CEO189-03 | structural-integrity.mdx EN+IT | Z106 in Dimension 3 (dovrebbe essere Z403) | Codice + nome corretti | ✅ Sigillato |
| BUG-CEO189-04 | health-metrics.mdx EN+IT | Nome penalità Z106 errato | Sostituito con CIRCULAR_LINK / Z403 corretti | ✅ Sigillato |
| BUG-CEO189-05 | Structural Map RULE R23 | Z106 descritto erroneamente come Alt Text | RULE R23 corretta | ✅ Sigillato |
| BUG-CEO194-B64 | shield.py | Vettore Red Team S2 (bypass Base64) | Decoder Base64 speculativo aggiunto | ✅ Sigillato |
| KL-002 | resolver.py | Falso positivo PathTraversal su filesystem case-insensitive (APFS/NTFS) | os.path.normcase applicato al confronto del perimetro | ✅ Corretto (portabilità) |
7 finding sigillati su 2 sprint. 0 problemi di sicurezza aperti.
Il Verdetto
Metriche di Certificazione
| Metrica | Valore |
|---|---|
| Test superati | 1.307 (Python 3.11 / 3.12 / 3.13) |
| Copertura del codice | 80,28% (≥ 80% richiesto) |
Atti interattivi in zenzic lab | 20 (Atti 0–19) |
| Lunghezza Masterclass | 1.525 righe |
| Attacchi Red Team lanciati | 3 (D1, D3, S2) |
| Attacchi Red Team bloccati (D094) | 2/3 |
| Attacchi Red Team sigillati (D095) | 3/3 (S2 sigillato) |
| Correzioni critiche di sicurezza | 2 (codice uscita Z202, decoder Base64) |
| Bug di documentazione corretti | 5 (su 7 file) |
| Problemi di sicurezza aperti | 0 |
Verifica degli Invarianti
| Invariante | Test | Risultato |
|---|---|---|
| RULE R4 — Exit 2/3 mai sopprimibile | --exit-zero su Z202 | ✅ Exit 3, non soppresso |
| RULE R9 — Shield scansiona il contenuto grezzo | Prop JSX ghp_ | ✅ Rilevato, exit 2 |
| RULE R8 — Zero sottoprocessi | Audit completo del codice | ✅ Nessun subprocess, nessun os.system |
| RULE R3 — Codici finding obbligatori | Tutti i finding portano Zxxx | ✅ codes.normalize() confermato |
| ADR-013 — Z2xx inviolabile | Guard _INVIOLABLE_CODES | ✅ Presente in rules.py |
| RULE R20 — Silenzio macchina | Formato SARIF, nessun output Rich | ✅ Controllato in ogni call site |
La Certificazione Quartz
:::note Certificazione Quartz Tribunal — Zenzic v0.7.0 CERTIFICATO. Il Tribunale ha esaminato 3 vettori di attacco, sigillato tutte le crepe aperte, e verificato tutti gli invarianti. Exit 0. Sentinel Seal. ✨
"Il Safe Harbor non è una promessa. È una prova." :::