Un navigateur distant naïf partage un seul processus de navigateur entre de nombreux utilisateurs. Les cookies définis dans une session apparaissent dans la suivante ; les données de localStorage franchissent les frontières de session ; l'état d'authentification d'un utilisateur peut être repris par un autre. Même si l'application protégée se comporte bien, le navigateur partagé devient un canal latéral qui contourne tout contrôle d'accès au niveau de l'application.
Il y a aussi la navigation. Un utilisateur disposant d'un droit de consultation uniquement sur un seul tableau de bord interne clique sur un lien de phishing à l'intérieur de ce tableau de bord, ouvre un nouvel onglet pour un compte personnel ou suit un lien externe qu'il n'avait pas l'intention de suivre. Sans une imposition au niveau du navigateur, la session s'échappe de l'application protégée — et désormais l'identifiant de session de l'application protégée, l'identité de l'utilisateur et l'état de navigation actif deviennent visibles partout où le navigateur se rend.
L'isolation du contexte de navigateur ferme les deux. Chaque session s'exécute dans son propre contexte de navigateur sans état partagé. Le navigateur lui-même impose une liste d'autorisation des domaines que la session peut atteindre et bloque chaque canal que l'utilisateur pourrait utiliser pour aller ailleurs — nouveaux onglets, popups, clics sur des liens vers des domaines non autorisés, navigation programmatique par la page elle-même.
Chaque session reçoit son propre contexte de navigateur au sein du moteur de rendu — entièrement séparé de l'état de toute autre session. Une liste d'autorisation de domaines stricte s'arrête à la couche de navigation — l'interception de requêtes, le polling de navigation des applications monopage et l'interception des clics sur les liens garantissent ensemble que la session n'atteint jamais un domaine non autorisé. En dessous, les pixels rendus eux-mêmes portent des modifications continues de bas niveau qui perturbent les outils d'automatisation tentant de lire la session ou d'interagir avec elle.
Chaque session utilisateur s'ouvre dans son propre contexte de navigateur isolé — un profil tout neuf avec son propre pot à cookies, son propre stockage local, son propre état de session. Deux utilisateurs sur la même application protégée disposent de navigateurs entièrement indépendants ; rien d'une session n'est visible dans une autre. La fin de session détruit entièrement le contexte ; aucun état ne survit.
Chaque tentative de navigation est interceptée avant d'être exécutée. La couche de requête bloque les domaines non autorisés au niveau réseau ; les clics sur les liens à l'intérieur de la page sont interceptés au niveau du rendu ; les navigations d'applications monopage (pushState, replaceState) sont interceptées par polling. La session ne peut pas atteindre un domaine hors liste d'autorisation, que l'utilisateur essaie délibérément ou que la page essaie d'elle-même.
Le navigateur de style kiosque ne permet pas à l'utilisateur d'ouvrir un nouvel onglet, de créer une popup ou d'utiliser le menu contextuel du clic droit. Chaque canal que l'utilisateur pourrait utiliser pour s'échapper de l'application protégée est fermé dans la configuration du navigateur. L'utilisateur travaille au sein de la session ouverte pour lui — rien de plus.
Sous le contenu visible, le flux de pixels rendu porte des modifications continues de bas niveau — bruit aléatoire, fins décalages de couleur, micro-déplacements d'éléments, vibration sous-pixel. Elles n'affectent pas ce que voit l'utilisateur, mais perturbent les outils d'automatisation (scripts Selenium, Puppeteer, racleurs d'écran) tentant de lire la session ou d'interagir avec elle en dehors du canal d'entrée officiel.
Chaque comportement ci-dessous se configure par service protégé et est imposé au niveau du navigateur, et non dans le code de l'application protégée. L'application protégée n'a pas besoin de connaître leur existence — la frontière est invisible depuis l'exécution de l'application.
Chaque session s'exécute dans son propre contexte de navigateur — une structure au niveau Chromium qui donne à la session son propre pot à cookies, son propre stockage local, son propre enregistrement de service worker, ses propres autorisations, son propre état de session. Deux sessions sur la même application protégée ne partagent rien au niveau du navigateur.
Chaque requête de navigation — document principal, sous-document, fetch, XHR — passe par un intercepteur qui vérifie le domaine cible par rapport à la liste d'autorisation de la session. Les domaines non autorisés sont bloqués avant l'établissement de la connexion. Il n'y a pas de condition de course entre le clic de l'utilisateur et la vérification de la navigation.
Les applications monopage modernes naviguent en appelant pushState ou replaceState sans effectuer de requête réseau. Un simple intercepteur de requêtes ne peut pas les capter. ZeroLeak interroge en outre l'URL courante à l'intérieur de la page à un court intervalle, de sorte que les navigations SPA vers des chemins non autorisés sont captées et annulées en quelques secondes.
Les éléments de lien à cible non autorisée, les appels window.open(), les changements de position programmatiques — tous sont interceptés dans la page rendue avant d'être exécutés. L'utilisateur qui clique sur un lien qu'il ne peut pas suivre est bloqué au moment du clic, et non après que la requête réseau a déjà commencé.
Le navigateur est configuré de sorte que toute tentative de création d'une nouvelle cible de navigation — par l'utilisateur, la page ou un script — soit instantanément interceptée et rejetée. La session possède toujours exactement un onglet visible, celui de l'application protégée.
Chaque session surveille l'interaction de l'utilisateur. Si l'utilisateur reste inactif plus longtemps que l'expiration configurée, la session est terminée proprement, le contexte de navigateur est détruit et (lorsque configuré) un webhook informe le coordinateur, afin que la politique cible puisse être mise à jour. Pas de navigateurs isolés abandonnés qui consomment de la mémoire.
Au-delà de l'isolation par session et de la frontière de navigation, le flux de pixels rendu lui-même porte des modifications continues de bas niveau. Leur objectif est de perturber les outils d'automatisation — les scripts qui, sinon, liraient l'écran de la session, identifieraient les éléments et interagiraient via des canaux non officiels — sans affecter la façon dont la page apparaît ou se comporte pour un utilisateur humain.
Un overlay canvas dessine en continu un bruit aléatoire de faible intensité sur l'ensemble de la page rendue. L'œil humain perçoit tout au plus une légère texture ; les scripts d'OCR et de template-matching qui tentent de lire l'écran perdent les frontières de pixels cohérentes sur lesquelles ils s'appuient. L'intensité du bruit et le taux de rafraîchissement sont configurables par service protégé.
Un overlay semi-transparent applique une teinte de couleur aléatoire qui change lentement sur l'ensemble de la page rendue. Les zones blanches et noires apparaissent encore effectivement blanches et noires à l'œil, mais les valeurs de pixels réelles se décalent. Les outils d'automatisation basés sur la vision qui font correspondre des signatures de couleur perdent leurs références.
Un flou continu très léger est appliqué comme filtre d'écran. Chaque image diffère légèrement dans son détail haute fréquence, ce qui rend plus difficile pour l'OCR et les correspondeurs de motifs de trouver des points caractéristiques fixes. L'utilisateur ne perçoit pas le flou à distance de lecture normale.
Les éléments de la page sont déplacés de manière aléatoire de 1 à 3 pixels par rapport à leur position normale. Le décalage est sous le seuil de perception humaine mais perturbe les scripts qui localisent les éléments par coordonnées d'écran absolues. Les outils d'automatisation ne peuvent pas se fier à une position d'élément fixe d'une image à l'autre.
À un court intervalle, l'ensemble de la surface rendue est décalé de quelques pixels — assez petit pour ne pas perturber la lecture, assez grand pour vaincre les outils d'automatisation qui dépendent de coordonnées de pixels absolues cohérentes pour la simulation d'entrée. Les attaques de replay de style Selenium perdent leurs points fixes.
Des interfaces d'infrastructure critique où une fuite d'état entre sessions ou une navigation indésirable pourrait affecter des systèmes physiques. L'isolation par session garantit que deux opérateurs sur la même console ne peuvent pas voir la session l'un de l'autre ; la liste d'autorisation stricte garantit qu'aucun ne passe de la console opérationnelle à un lien externe.
Tableaux de bord internes, interfaces d'audit, outils de reporting accédés par de nombreux utilisateurs — y compris sous-traitants et auditeurs externes. Chaque session est son propre navigateur, la politique d'accès est imposée à la couche de navigation, et les défenses de la couche de rendu résistent à l'automatisation de quiconque tente de racler l'écran.
Le contexte par session signifie qu'un sous-traitant consultant une data room ne peut pas voir les cookies, l'historique de recherche ou les identifiants de session d'un autre sous-traitant dans une data room différente. La liste d'autorisation garantit que la session de data room ne se rend jamais sur l'internet plus large.
Des portails d'étude où plusieurs chercheurs accèdent aux données patient sous des limites de divulgation strictes. L'isolation par session impose la frontière au niveau du navigateur ; la liste d'autorisation l'impose au niveau de la navigation ; les défenses de rendu résistent à l'automatisation de quiconque tente de racler les données via le canal d'affichage à l'écran.
Nous exécuterons côte à côte deux sessions sur la même application protégée, montrerons que rien ne fuit entre elles, tenterons de sortir de la liste d'autorisation et essaierons de piloter la session avec un outil d'automatisation externe — et vous montrerons ce qui se passe.