Inganno Unicode

Caratteri invisibili nel codice e nei prompt IA: rischi e difese



Indirizzo copiato

Caratteri invisibili, omoglifi e normalizzazione Unicode possono alterare ciò che leggiamo e ciò che i sistemi eseguono. Dal Trojan Source alla prompt injection nei modelli generativi, il rischio cresce quando revisione umana, parsing e tokenizzazione producono interpretazioni diverse dello stesso testo

Pubblicato il 25 mar 2026

Massimo Dionisi

Terrorism and Counterterrorism



programmare codice con IA (1) Informatica e AI
AI Questions Icon
Chiedi allʼAI Nextwork360
Riassumi questo articolo
Approfondisci con altre fonti

Ogni riga di codice può nascondere un’illusione: spesso quella che vediamo non è la stessa che il computer esegue (Cambridge, 2021). È il cuore degli attacchi “Trojan Source”, scoperti da ricercatori di Cambridge: inserendo caratteri Unicode speciali invisibili o bidirezionali in punti strategici, un revisore umano vede un testo innocuo mentre il compilatore esegue altro. Queste tecniche non si fermano al software tradizionale: nelle applicazioni di intelligenza artificiale generativa, caratteri invisibili (bidirezionali, a larghezza zero, omoglifi) e differenze di normalizzazione possono camuffare comandi o forzare parsing diversi, aprendo la strada a prompt injection (OWASP, 2024).

Negli ultimi anni l’ecosistema ha reagito: GitHub segnala i file con testo bidi sospetto, Microsoft/VS Code evidenziano i caratteri direzionali (CVE-2021-42574), e Red Hat/Ubuntu hanno documentato l’impatto nei bollettini di sicurezza. Resta però fondamentale andare oltre il “leggi e firma”: servono strumenti, pipeline CI e formazione che facciano emergere ciò che a occhio resta invisibile. In questa nota analizzeremo cause, esempi, rischi per il codice e per l’IA, e misure pratiche: proteggere una riga di codice significa anche difendere la supply chain del software e la sicurezza dell’IA.

Il trucco della doppia lettura

Immaginiamo una riga di codice come un nastro: alla vista appare dritto e lineare, ma basta un piccolo “pezzo piegato” perché ciò che l’occhio vede (la scena sul palco) sia diverso da ciò che la macchina legge (dietro le quinte). Unicode include caratteri di controllo bidirezionali (UAX #9) per testi in arabo o ebraico; normalmente li usiamo per formattare, ma negli attacchi Trojan Source vengono infilati in commenti o stringhe nel punto sbagliato. Il risultato è che un token come // commento può sembrare commentato al revisore, mentre per il compilatore è ancora dentro una stringa (o viceversa). In pratica si crea una doppia realtà: due testi diversi, uno visibile e uno logico.

Unicode Consortium e NVD ricordano che la “bidirezionalità” è una proprietà necessaria del testo internazionale; il problema nasce quando strumenti e revisori non la gestiscono correttamente. Red Hat e Ubuntu considerano questi attacchi un rischio per repository e pipeline di build (supply chain software). In alcuni resoconti “popolari” compare il nome “Mirab Security” come fonte, ma non abbiamo trovato conferme in documenti ufficiali: la citiamo per completezza ma come non verificata.

I caratteri che alterano il significato

Per chi non è tecnico è utile dividerli in blocchi:

Caratteri bidi e ordine di visualizzazione

Codici invisibili che influenzano l’ordine di visualizzazione (UAX #9). Possono far sembrare “spostati” pezzi di testo rispetto all’ordine logico effettivo. Ad esempio CVE-2021-42574 sfrutta esattamente questo (Microsoft, 2021). Se un revisore vede // fine blocco, il compilatore potrebbe leggerlo in ordine logico opposto.

Caratteri invisibili di controllo e zero-width

Come ZERO WIDTH SPACE, ZERO WIDTH JOINER, escape, tab invisibile ecc. Non appaiono a occhio, ma contano nel confronto di stringhe o nel parsing. Possono nascondere token o spezzare parole chiave, bypassando controlli statici. Ad esempio, inserire un ZERO WIDTH SPACE dentro “password” può rendere inutili filtri che cercano la parola proibita.

Omoglifi e confusione tra alfabeti

Lettere provenienti da alfabeti diversi che sembrano identiche. Es. la “a” latina vs “a” cirillica. Nel codice possono rendere due variabili o funzioni indistinguibili a occhio, ma diverse per il compilatore. Trojan Source ha generato anche CVE su omoglifi (CVE-2021-42694), evidenziando che la confusione tra script è un vettore reale.

Normalizzazione Unicode e divergenze tra sistemi

Una stessa stringa di caratteri può essere codificata in modi multipli (NFC/NFD). Se un componente normalizza e un altro no, “quegli” caratteri diventano diversi: ciò che sembra identico per l’occhio può non esserlo per un check. Microsoft avverte di progettare validazioni tenendo conto di normalizzazione. Nelle app LLM (e in genere) è cruciale decidere se e come normalizzare prima della tokenizzazione, per evitare bypass invisibili.

Tokenizzazione e significato operativo

Compiler e modelli AI spezzano il testo in “token” a livello di code point. Piccole differenze di carattere causano token diversi, che possono cambiare significato e priorità. Nelle LLM, comandi mascherati da caratteri invisibili possono creare token inattesi e portare il modello a eseguire istruzioni nascoste (prompt injection).

Come leggere gli esempi e riconoscere la divergenza visiva

Nel seguito useremo segnaposto come {U+202E} nei commenti e nelle stringhe: non sono caratteri reali, servono solo a mostrare visivamente dove normalmente sarebbe invisibile. Nei veri attacchi questi code point vengono inseriti direttamente tra simboli di commento o virgolette, creando divergenze tra il rendering grafico e l’ordine logico vero del testo. Ad esempio, editor moderni come VS Code visualizzano i caratteri di direzionalità per rendere percepibile il rischio (Microsoft, 2021).

Il codice qui sotto non è un attacco reale (usa segnaposto). Mostra però l’intuizione: ciò che sembra commento può essere parte di una stringa, oppure i delimitatori possono apparire “spostati” nella resa visiva.

Questa mini-dimostrazione (sempre non eseguibile) illustra: un // check admin che a occhio sembra commentato può in realtà essere “dentro” la stringa o il codice, cambiando il comportamento. GitHub spiega il concetto: un file con testo bidi può “apparire” diverso da come viene compilato.

Dai repository ai modelli linguistici

Nei sistemi LLM il testo spesso diventa comando. OWASP mette la Prompt Injection tra i rischi critici per i modelli generativi (Prompt Injection Top 10, 2024). Parole chiave (ad es. “esegui”, “riavvia”, o delimitatori di contesto) possono essere rese invisibili o camuffate con omoglifi, permettendo all’utente malintenzionato di spezzare o mimare le istruzioni predeterminate. Inoltre, i modelli tokenizzano: piccoli cambiamenti di code point alterano i token e quindi l’interpretazione. Un prompt copiato-incollato da fonti non controllate può trasportare caratteri bidi o zero-width senza che l’operatore se ne accorga, inducendo il modello a leggere istruzioni nascoste.

Un modello riceve il prompt normalizzato e “pulito”, lo spezza in token e poi lo esegue (compila o genera testo). Se le fasi precedenti sono compromesse, il risultato finale può tradire l’intento originale dell’utente.

Difese pratiche: strumenti e processi

Le contromisure sono semplici, ma vanno implementate su più livelli:

Editor e repository

Abilitare la visualizzazione o il warning sui caratteri invisibili. Ad esempio VS Code mostra i bidi e GitHub segnala i file sospetti. Questi avvisi vanno presi sul serio, non ignorati come falsi positivi di UI.

Policy Unicode e normalizzazione coerente

Definire cosa è consentito nei sorgenti, commenti, stringhe e template di prompt. Adottare una normalizzazione coerente (ad es. NFC) lungo tutta la catena: ciò che viene confrontato o whitelistato deve essere normalizzato in anticipo. I controlli di sicurezza (scan statici, whitelist) vanno pensati in funzione di questa forma canonica.

CI/CD, review e formazione

Integrare nello sviluppo strumenti di analisi Unicode: scanner in pre-commit o pipeline che blocchino sequenze bidi sospette, caratteri zero-width, e mixed-script confondibili (profilo TR39). CERT/CC raccomanda addirittura di vietare i caratteri di direzionalità nei compilatori, ma almeno implementare warning/blocco in pipeline è un buon inizio (forte priorità). In review, se emergono avvisi o simboli strani, la regola dovrebbe essere: bloccare e indagare finché non si chiarisce il testo reale. Formare il team (anche 30 min di training) su questi pericoli aiuta a riconoscere l’inganno.

Applicazioni LLM e igiene degli input

Separare dati e istruzioni (usare delimitatori, prompt con contesto stretto), minimizzare i permessi “automatizzati” del modello, sanitizzare sempre input esterni (web, email, documenti OCR). Loggare input e output aiuta a ricostruire un eventuale incidente di prompt injection. È igiene applicativa, ma cruciale: in pratica, trattare i prompt come potenziali vettori di attacco aggiuntivi.

Priorità operative e controlli da implementare subito

Tabella comparativa (priorità operative)

VettoreComponenti colpitiDifficoltà rilevamentoPriorità mitigazione
Bidi/Trojan SourceEditor, review, compilatoreAltaMolto alta (supply chain)
Zero-width / ControlParser, tokenizer, modelloMedia-altaAlta
Omoglifi (mixed-script)Review, build, dipendenzeAltaAlta
Normalizzazione incoerenteBackend, CI, modelliMediaAlta
Prompt injection + UnicodeApp LLM, automazioniAltaMolto alta



Checklist operativa per codice, pipeline e prompt

Un modo di procedere, utile per gli sviluppatori, potrebbe essere quello di:

Abilitare rendering/avvisi per bidi e caratteri di controllo (editor e repository).
Integrare scanner Unicode in pre-commit/CI (bidi non terminati, zero-width, mixed-script).
Applicare una normalizzazione coerente (es. NFC) su confronto, whitelist e deduplica.
• Nel codice di app LLM: separa nettamente dati e istruzioni, limita i permessi delle azioni automatiche, logga input/output.

Unicode invisibile tra supply chain, GDPR e AI Act

Il testo “mascherato” può diventare problema reale: basta un attacco riuscito in un repository per compromettere tutta la supply chain del software (Red Hat, 2021). Se il codice nascosto porta alla compromissione di dati (fuga o alterazione), entrano in gioco GDPR e obblighi di sicurezza dei dati. In ambito IA, l’AI Act (2024) richiede la gestione del rischio e la tracciabilità nel ciclo di vita; nemmeno qui si possono trascurare vulnerabilità testuali. Per tradurre “rischi Unicode” in controlli concreti, NIST ha introdotto l’AI Risk Management Framework e un profilo dedicato alla generativa (AI RMF 1.0, 2023): sono utili punti di partenza per trasformare linee guida in checklist operative.

La sicurezza passa anche da ciò che non si vede

La sicurezza del 2026 passa anche da ciò che non si vede. Rendere visibili i caratteri speciali, automatizzare i controlli e trattare i prompt come input ostile è un piccolo prezzo da pagare rispetto al costo di una backdoor nella supply chain o di un agente LLM che esegue istruzioni mascherate.

guest

0 Commenti
Più recenti
Più votati
Inline Feedback
Vedi tutti i commenti

Articoli correlati

0
Lascia un commento, la tua opinione conta.x