Una finestra di Chrome con più spazi di lavoro isolati: come funziona davvero
L’isolamento in una sola finestra è la sovrapposizione di tre strati: sessione e archiviazione, instradamento di rete, ciclo di vita. Non è virtualizzazione del kernel e non cambia l’impronta.
Perché aprire più finestre non equivale ad avere più account connessi insieme
Partiamo smontando un’intuizione: una finestra non è un’unità di isolamento. Dieci finestre nello stesso profilo condividono un archivio cookie, un localStorage e una cache HTTP, e il sito vede una sola sessione. La modalità incognito ha davvero un archivio separato, ma ce n’è uno solo e muore con la finestra, quindi non basta per dieci account. L’unità reale è il contenitore di sessione: un insieme di cookie proprio, uno spazio dei nomi di archiviazione proprio e una mappa di appartenenza stabile. Chrome non ha un’API per i contenitori — l’eccezione è contextualIdentities di Firefox — così l’estensione la costruisce al livello di sessione: annota quale scheda appartiene a quale contenitore, poi smista richieste e archiviazione secondo quella mappa. CrispLogin funziona così: il contenitore è un registro che l’estensione mantiene, non una primitiva di Chrome. L’unità dell’isolamento è la sessione, non il processo.
Primo strato: perché i cookie non si mescolano
Gli account restano separati grazie a un barattolo di cookie virtuale più la riscrittura dell’intestazione di richiesta per scheda. Ogni contenitore tiene dentro l’estensione i propri record di cookie. Prima che una richiesta parta, una session rule di declarativeNetRequest individua la scheda con condition.tabIds e imposta l’intestazione cookie al valore di quel contenitore; quando arriva la risposta, webRequest osserva Set-Cookie e lo riscrive nel barattolo corrispondente. Il barattolo deve serializzare i cookie ordinandoli per lunghezza del percorso e poi per data di creazione, altrimenti l’intestazione non coincide con quella che il browser avrebbe inviato.
Il punto che sfugge è la durata: tabIds vale solo nelle session rule, e le session rule vengono cancellate alla chiusura del browser e all’aggiornamento dell’estensione. Le regole vanno quindi reinstallate a ogni avvio; saltarlo produce il sintomo «dopo il riavvio tutti gli spazi di lavoro sono lo stesso account». L’archiviazione di pagina è un’altra faccia: document.cookie legge l’archivio reale e localStorage ha un solo spazio dei nomi, quindi uno script nel MAIN world deve intermediare letture e scritture per contenitore. Questo è isolamento a livello applicativo: separa due account dello stesso sito, ma non tocca l’impronta del kernel.
Secondo strato: come il proxy segue lo spazio di lavoro
Chrome non ha un’API per impostare il proxy per scheda. chrome.proxy.settings vale per l’intero profilo e FindProxyForURL(url, host) di uno script PAC non riceve mai un tabId; declarativeNetRequest può riscrivere intestazioni e reindirizzare, ma non ha l’azione «scegli il proxy a monte». Quello che un’estensione può fare è mantenere una mappa spazio di lavoro → uscita e riscrivere quella configurazione globale quando cambia la scheda in primo piano.
PAC può separare per dominio, ma il suo input è l’URL, non la scheda: lo stesso sito aperto in due spazi di lavoro riceve una sola risposta da PAC. Quindi «dieci spazi di lavoro, ognuno con il proprio tunnel» in un’estensione non esiste; ciò che è garantito è «lo spazio di lavoro che sta davanti è quello con la sua uscita». È anche il motivo per cui cambiando spazio si vede una riconnessione: cambiando la configurazione del proxy le connessioni già aperte vengono ricostruite. Confine: questo strato cambia l’IP di uscita e il percorso della richiesta, non l’impronta TCP/TLS (JA3/JA4); WebRTC si può limitare con chrome.privacy.network.webRTCIPHandlingPolicy per scartare l’UDP non proxato, ma è una politica dell’intero browser, non per spazio di lavoro.
Terzo strato: il legame sopravvive alla chiusura della scheda o a un riavvio?
Il background di MV3 è un service worker: 30 secondi senza eventi e viene terminato, portandosi via le variabili di modulo e ogni Map dentro una closure. Perciò «quale scheda appartiene a quale spazio di lavoro» non può stare in memoria: va in chrome.storage.session, che resta in memoria finché l’estensione è caricata e sopravvive al riciclo del worker, ma viene svuotato al riavvio del browser. Attenzione: non è esposto ai content script per impostazione predefinita; se il lato pagina deve leggere il legame, serve una chiamata esplicita a setAccessLevel.
Questo divide i dati in due: i legami di esecuzione in session, e tutto ciò che deve sopravvivere a un riavvio — elenco degli spazi, configurazione del proxy, indice delle istantanee — in storage.local. La catena causale è diretta: poiché il legame sta in session e non in una variabile, dopo il risveglio l’estensione sa ancora a chi appartiene ogni scheda e non riversa i cookie di uno spazio nella pagina di un altro. Se stesse solo in memoria, appena il worker si addormenta la richiesta successiva non avrebbe un proprietario da consultare, e si vedrebbero gruppi duplicati e istantanee ripristinate nel contenitore sbagliato.
Quarto strato: cosa salva un’istantanea del sito e cosa ripristina
L’istantanea risponde a un’altra domanda: la portabilità dello stato di accesso, non l’isolamento in esecuzione. È al quarto posto nell’elenco ma non fa parte dell’isolamento in sé. Serializza i cookie di un sito dentro un contenitore e l’archiviazione di quel sito, e al ripristino li riversa nello spazio dei nomi di quel contenitore. I due aspetti sono ortogonali: l’isolamento impedisce che due spazi si disturbino mentre coesistono, l’istantanea evita di dover accedere di nuovo. La granularità è il sito, non il browser: due siti in un contenitore sono due record indipendenti.
Per questo un’istantanea deve appartenere a un contenitore: versare lo stato di A in B fonde due account in uno. Altrettanto importante è dire cosa non fa: ripristina lo stato di sessione a livello applicativo, non un’impronta del kernel, e non promette di aggirare i controlli di rischio o la validazione del dispositivo di una piattaforma. Uso: Link interno: uso pratico delle istantanee del sito.
In cosa differisce dall’aprire più profili?
I profili multipli di Chrome sono un taglio fisico a livello della directory radice dell’archiviazione: ogni profilo ha archivio cookie, archiviazione, estensioni e cache propri, quindi l’isolamento è completo. Il prezzo si vede su quattro assi: memoria, perché ogni profilo ha il proprio contesto di rete e i propri processi di rendering, quindi tre profili sono all’incirca tre volte il costo residente; processi, perché gli alberi sono separati; finestre, perché un profilo è una finestra e cambiare significa cambiare finestra; impronta, perché i profili condividono kernel e macchina, e UA, Canvas e font sono identici per impostazione predefinita. C’è un costo più silenzioso: segnalibri, estensioni e cronologia non sono condivisi, e oltre il terzo profilo ognuno comincia a divergere.
La via dell’estensione ribalta tutto: un profilo, una finestra, processi e kernel condivisi, in cambio di parallelismo in una sola finestra con costo incrementale quasi nullo — e il prezzo è non raggiungere lo strato dell’impronta del kernel. Non sono due gradi della stessa cosa, ma due modi di tagliare la granularità dell’isolamento. Confronto: Link interno: profili di Chrome e isolamento per estensione.
Confini: quali strati copre un’estensione e quali no
I confini visti finora, compressi in una tabella. Si legge chiedendosi cosa controlla la piattaforma: per sessione e uscita la colonna centrale, per la coerenza dell’impronta quella di destra. Vale la pena ripeterlo: un’estensione fa isolamento a livello di sessione, che non è lo stesso grado di un browser antidetect; considerarla un antidetect più leggero significa leggere male il rischio.
| Strato | Ciò che l’estensione copre | Fuori portata, o il prezzo |
|---|---|---|
| Cookie e stato di accesso | Separati per contenitore, serializzabili in un’istantanea | Il kernel non conosce i contenitori; si riscrivono le intestazioni e, se le regole si perdono, si mescola |
| Archiviazione di pagina | localStorage e IndexedDB si possono prefissare o proxare per contenitore | Service worker, SharedWorker e altri contesti separati richiedono copertura dedicata |
| IP di uscita | Legato allo spazio di lavoro; cambiando il primo piano cambia l’uscita | Una sola uscita in primo piano alla volta; nessun tunnel concorrente |
| WebRTC | Si può scartare l’UDP non proxato (politica dell’intero browser) | Non per spazio di lavoro; i percorsi media possono ancora aggirare il proxy |
| Impronta TLS | Nulla | JA3/JA4 dipendono dal kernel e dallo stack di rete |
| Canvas / WebGL / Audio | Nulla | Il rendering avviene nel kernel; nessuna API per riscriverlo |
| Enumerazione dei font | Nulla | Solo patch JS nella pagina, e sono rilevabili |
| Cache HTTP | Nulla | La cache è per profilo e condivisa tra i contenitori |
La tabella mostra anche dov’è il tetto: ciò che un’estensione sostituisce è il motivo di comprare un client solo per accedere separatamente, non il client. Quale via scegliere è un’altra domanda, confrontata punto per punto in Link interno: estensione e browser antidetect.
Domande frequenti
L’isolamento dei cookie di un’estensione è la stessa cosa dei Partitioned Cookie di Chrome?
No. I Partitioned Cookie sono indicizzati per sito di primo livello, quindi un sito ha un solo barattolo per pagina di primo livello; partitionKey nell’API cookies è solo la chiave per leggere e scrivere quei cookie, e il suo unico componente è topLevelSite: non ci si inventano nuove partizioni. Il barattolo di uno spazio di lavoro è separato per contenitore, un sito può averne quanti vuole e l’estensione tiene i conti. Il primo è partizionamento per privacy del browser, il secondo un’astrazione di sessione dell’estensione.
Lo stato dello spazio di lavoro resta se chiudo la scheda?
Tre casi. La scheda sparisce e il legame se ne va con lei. Le definizioni dello spazio — nome, proxy, indice delle istantanee — sono dati che devono sopravvivere a un riavvio e di norma stanno in storage.local. Lo stato di accesso è recuperabile solo se hai salvato un’istantanea; altrimenti si accede di nuovo. Ciò che sta in storage.session viene svuotato alla chiusura del browser, quindi non trattarlo come archivio durevole.
L’approccio a finestra singola pesa sulle prestazioni del browser?
L’incremento viene dalle schede, non dall’isolamento. Non si avvia un secondo browser né si copia il kernel; il costo è l’abbinamento delle regole e la riscrittura delle intestazioni, una quantità costante per richiesta. Il costo vero è nel numero di schede e nelle pagine: con venti spazi ciò che si impunta è il rendering, non lo strato di isolamento.
Due spazi di lavoro possono usare IP di uscita diversi nello stesso momento?
No. La configurazione del proxy è per profilo e l’estensione può riscriverla solo al cambio di scheda, quindi in ogni istante solo lo spazio in primo piano usa la propria uscita; quelli in background vengono bloccati dalle regole o escono diretti. Per tunnel davvero concorrenti serve un client con uno stack di rete proprio.
Fonti e ultimo aggiornamento
Dove l’articolo tocca il comportamento delle API vale la documentazione ufficiale. I confini di un’estensione si spostano con le versioni di Chrome: ricontrolla prima di adottarla.
- Chrome for Developers, chrome.declarativeNetRequest — durata delle session rule, ambito di condition.tabIds e modifyHeaders sull’intestazione cookie: developer.chrome.com/docs/extensions/reference/api/declarativeNetRequest
- Chrome for Developers, chrome.storage — l’area session resta in memoria, si svuota al riavvio del browser e non è esposta ai content script per impostazione predefinita: developer.chrome.com/docs/extensions/reference/api/storage
- Chrome for Developers, chrome.cookies — partitionKey e la semantica di chiave dei Partitioned Cookie (CHIPS): developer.chrome.com/docs/extensions/reference/api/cookies
- Chrome for Developers, chrome.proxy — le impostazioni del proxy valgono per l’intero profilo del browser e PAC riceve solo URL e host: developer.chrome.com/docs/extensions/reference/api/proxy
- Chrome for Developers, The extension service worker lifecycle — terminazione dopo 30 secondi di inattività e perdita delle variabili globali con il worker: developer.chrome.com/…/service-workers/lifecycle
Ultimo aggiornamento: 11 novembre 2026. Qui è descritto il percorso di implementazione tipico di questa classe di estensioni; quali API e quali sedi di dati usi un singolo prodotto può variare, e per le sue interiora vale la sua documentazione.