isolated-vm, falla critica può trasformare un sandbox JavaScript in RCE sull’host
Vulnerabilità

Immagine illustrativa generata con AI

isolated-vm, falla critica può trasformare un sandbox JavaScript in RCE sull’host

Scopri come una falla critica in isolated-vm può trasformare un sandbox JavaScript in RCE sull'host, con dettagli tecnici e impatto sulla sicurezza.

Testo generato da intelligenza artificiale, pubblicato senza revisione umana. Trasparenza IA

Una corruzione della memoria rompe il confine tra guest e host

Una vulnerabilità critica nella libreria Node.js isolated-vm consente a codice JavaScript non affidabile di provocare crash del processo host e, in condizioni favorevoli, di assumere il controllo del suo flusso di esecuzione.

Il problema riguarda il codice nativo C++ che collega gli oggetti JavaScript di V8 alle strutture di memoria usate da isolated-vm. La falla combina type confusion, corruzione della memoria e una condizione time-of-check/time-of-use (TOCTOU).

L’impatto è particolarmente serio perché isolated-vm viene adottata proprio per eseguire codice potenzialmente ostile all’interno di isolate V8. Questi ambienti separano heap, stato di esecuzione e garbage collector, offrendo un confine di sicurezza senza ricorrere necessariamente a container o macchine virtuali.

Il difetto compromette quel confine. Il codice guest può arrivare a influenzare il processo host, con potenziale esecuzione remota di codice sull’host. Non è stata indicata evidenza di sfruttamento della vulnerabilità in campagne reali.

La vulnerabilità è stata rilevata il 21 agosto 2026. Non è noto alcun identificativo CVE associato al problema.

Il difetto nasce da una doppia lettura di transferList

Il punto d’ingresso è il meccanismo:

ivm.ExternalCopy(value, { transferList })

ExternalCopy permette di serializzare dati in un isolate e ricostruirli in un altro. Per trasferire in modo efficiente grandi ArrayBuffer, il buffer sorgente può essere “staccato” e il relativo spazio di memoria passato alla destinazione.

Durante la costruzione di ExternalCopySerialized, isolated-vm analizza però transferList due volte. Nella prima scansione verifica che ciascun elemento sia un ArrayBuffer. Nella seconda recupera nuovamente gli elementi e li converte, senza ripetere il controllo del tipo.

Questa differenza è decisiva. La lettura degli elementi avviene tramite Get(), che non si limita a recuperare un valore già presente: può eseguire accessor JavaScript, compresi gli index getter.

Un getter controllato dal guest può quindi restituire un vero ArrayBuffer durante la validazione e un valore completamente diverso nella seconda lettura. Il nuovo valore viene poi passato a As<ArrayBuffer>(), che in questo percorso agisce come un cast non verificato, non come una conversione sicura.

Il controllo riguarda dunque un valore, mentre l’uso successivo può coinvolgerne un altro.

Come il valore controllato arriva al codice C++

La catena vulnerabile attraversa diversi componenti interni:

  • src/external_copy/serializer.cc, dove transferList viene iterato due volte;
  • src/isolate/generic/array.h:42, il cui iteratore legge gli elementi tramite array->Get(context, index);
  • src/external_copy/external_copy.cc:397, dove ExternalCopyArrayBuffer::Transfer utilizza l’handle considerato, erroneamente, un ArrayBuffer.

Nella seconda scansione, l’handle può quindi contenere un valore che non rappresenta alcun buffer. Il codice tenta comunque operazioni riservate a un oggetto valido, tra cui:

  • verificare se il buffer è separabile;
  • ottenere il relativo backing store;
  • staccare il buffer;
  • gestire il shared_ptr<BackingStore> associato alla memoria.

Un intero piccolo come 0x41414141 può essere interpretato da V8 come SMI, cioè un intero rappresentato direttamente nel valore tagged. Il codice nativo lo tratta invece come se fosse un oggetto e prova a dereferenziarlo.

Il risultato è un indirizzo calcolato a partire da dati controllati dall’attaccante. Inoltre, durante la distruzione dello shared_ptr, il percorso può effettuare una chiamata indiretta attraverso un puntatore vtable ricavato da quella memoria. Questa condizione offre una possibile primitiva per il control-flow hijacking, cioè la deviazione del flusso di esecuzione del processo.

La classificazione tecnica comprende CWE-843, accesso a una risorsa attraverso un tipo incompatibile, e CWE-704, interpretazione o conversione errata del tipo.

Il guest può raggiungere l’API anche indirettamente

Il costruttore ExternalCopy è esposto sul lato host, ma l’attacco non richiede necessariamente che l’host invochi direttamente l’API con dati già manipolati.

La classe può essere trasferita nel guest tramite l’opzione externalCopy del meccanismo transferable. È sufficiente che il codice non attendibile disponga anche di una sola ivm.Reference. Da quel riferimento può recuperare il costruttore in questo modo:

const ExternalCopy =
  ref.getSync('anyKey', { externalCopy: true }).constructor;

A quel punto il guest può preparare un transferList contenente un getter con comportamento variabile. Alla prima lettura il getter restituisce un ArrayBuffer valido, superando il controllo iniziale. Alla seconda può restituire, per esempio, 0x41414141.

Sono quindi esposti gli embedder che eseguono JavaScript non affidabile in un isolate e condividono con quel codice almeno un oggetto ivm.Reference.

Esiste anche uno scenario più diretto: il codice host può essere vulnerabile se passa a ExternalCopy un array transferList controllabile dall’utente. In questo caso non è necessario che il guest possieda una reference trasferita.

Il PoC dimostra un crash controllabile

Il proof of concept è stato verificato con:

  • isolated-vm 7.0.0 installata da npm;
  • Node.js 26.5.0;
  • macOS su architettura arm64.

Il problema è riproducibile su qualsiasi piattaforma, anche se indirizzi e dettagli del fault possono variare.

L’esecuzione del PoC con:

node poc.js

porta alla terminazione del processo host con:

  • segnale SIGSEGV;
  • codice di uscita 139;
  • errore in v8::ArrayBuffer::IsDetachable;
  • indirizzo di fault 0x4141414100000047.

Quest’ultimo valore è significativo perché deriva dall’intero controllato dal guest, interpretato come SMI. Non si tratta quindi soltanto di una dereferenziazione nulla o di un crash casuale.

Il crash rappresenta l’impatto minimo dimostrato. La stessa corruzione può, in scenari più complessi, consentire letture o scritture verso indirizzi scelti dall’attaccante e il controllo del flusso del processo host. Da qui deriva il rischio di evasione del sandbox e di esecuzione di codice sull’host.

Versioni corrette e azioni per gli amministratori

Le correzioni sono disponibili in:

  • isolated-vm 6.2.0;
  • isolated-vm 7.0.1.

Chi utilizza il ramo 6 deve aggiornare almeno alla 6.2.0; chi utilizza il ramo 7 deve portarsi almeno alla 7.0.1. È opportuno verificare anche le dipendenze transitive che includono isolated-vm, soprattutto nei servizi che eseguono script forniti da utenti, plugin o contenuti remoti.

La correzione impedisce l’esecuzione di JavaScript durante l’operazione di copia. In questo modo il contenuto di transferList non può cambiare tra la fase di validazione e quella del cast.

Gli interventi prioritari sono:

  1. aggiornare isolated-vm alla versione corretta del ramo utilizzato;
  2. censire gli embedder che eseguono JavaScript non attendibile;
  3. individuare i casi in cui il guest riceve oggetti ivm.Reference;
  4. controllare gli utilizzi di ExternalCopy con transferList influenzabili dall’input;
  5. ridurre, ove possibile, la condivisione di ivm.Reference con codice non fidato.

Sul piano del monitoraggio, crash con SIGSEGV, codice 139 e indirizzi di fault anomali o riconducibili a valori controllati meritano un’analisi immediata. Sono indicatori tecnici compatibili con il PoC, ma da soli non dimostrano una compromissione.

Non sono noti indicatori di compromissione basati su rete, file o processi. Non è inoltre noto se la vulnerabilità sia stata inserita nel catalogo KEV della CISA, né risultano informazioni su una scadenza di remediation associata.

Leggi anche

Fonti

Questo articolo è una rielaborazione originale basata sulle fonti seguenti.

Argomenti correlatiisolated-vmvulnerabilitàsandbox JavaScriptRCENode.jsfalla criticamemoriasicurezza
Torna alla home