Malla exécute du contenu non fiable, des formules d'utilisateurs et des saisies de visiteurs à côté des secrets de ses clients. Voici les frontières qui les tiennent à l'écart les uns des autres.
Deux populations, jamais mélangées
Les utilisateurs de l'éditeur et les visiteurs des sites ont des tables séparées, des cookies de session séparés et des clés de signature séparées. Les sessions de l'éditeur sont des cookies HTTP-only, Secure et SameSite=Lax, avec vérification CSRF ; les mots de passe sont hachés avec scrypt. Les sessions des visiteurs sont limitées au domaine du client et vivent dans la base de données propre au site.
Autorisations
- Chaque route de l'api vérifie le rôle de l'appelant sur le site ; les sites inconnus et interdits répondent tous deux 404.
- Les publications en production, les changements de slug, les domaines et les écritures sur les intégrations exigent un administrateur.
- Les salles temps réel vérifient un jeton de courte durée et le site de la page ; les lecteurs sont en lecture seule et les éditeurs de contenu ne peuvent modifier que du texte.
- Le temps réel valide chaque mise à jour par rapport aux schémas avant de la stocker ou de la relayer.
Expressions
Pas d'eval ni de new Function. L'interpréteur refuse window, document, globalThis, constructor, __proto__ et prototype, n'a ni affectation ni boucles, et plafonne la longueur du source, la profondeur, le nombre de nœuds évalués ainsi que la taille des chaînes et des tableaux. Le même interpréteur évalue les règles de ligne et les règles d'accès des pages sur le serveur.
Le navigateur n'est pas fiable
Les workflows client et les liaisons peuvent être lus et modifiés par les visiteurs : ils ne détiennent donc jamais d'autorité. L'accès aux pages est contrôlé sur le serveur, les requêtes client des pages à accès restreint passent par le même contrôle, et les écritures passent par des workflows serveur et des règles de ligne. Dans les règles, un user anonyme a id: NaN, pour que les vérifications de propriété ne correspondent jamais aux lignes sans propriétaire.
Requêtes sortantes
Les intégrations n'atteignent que les hôtes qu'elles déclarent. Les fetch côté serveur exigent HTTPS, résolvent les noms d'hôte via DNS-over-HTTPS et bloquent les réponses privées, de loopback et link-local (redirections revérifiées), et plafonnent la durée et la taille des réponses. runJs tourne dans un isolat Worker Loader, sans liaisons ni secrets.
Styles et HTML
Les valeurs de style qui pourraient s'échapper d'une règle sont refusées ; les noms de propriétés sont validés. Le moteur de rendu échappe le texte et assainit les URL. Le texte enrichi est stocké en JSON structuré, jamais en HTML brut. Le code personnalisé d'un site ne s'exécute que sur les sites publiés, jamais dans l'éditeur.
Protection contre les abus
Les formulaires utilisent Turnstile, un pot de miel (honeypot) et des limites par IP et par formulaire, et stockent les IP sous forme hachée. Les points de terminaison publics, les requêtes client, la connexion et l'inscription utilisent la limitation de débit de Cloudflare.