Permissions et emplacements¶
Pour les auteurs de plugins : ce qu'un manifeste peut déclarer, ce que l'installateur vérifie, et les règles qui s'appliquent à un plugin pendant son exécution. Le catalogue ci-dessous est la liste dans laquelle choisir ; la façon dont le serveur confine un plugin, et ce que ce confinement ne peut pas empêcher, est décrite dans Sandbox des plugins et modèle de menace.
Ce qui est vérifié à l'installation¶
Un plugin est refusé à l'installation quand :
kindmanque, ou ne vaut nipluginnitheme;- un
kind: pluginn'a pas delanguageou d'entrypoint, ou unkind: themeles déclare, ou déclare despermissionsou descapabilities; - une permission ou une capacité est inconnue ;
- un module d'interface vise un emplacement hors de la liste des emplacements ;
- une entrée de
external_fetchenfreint les règles d'accès externe, ounetworkest déclaré sans aucune entrée ; - le ZIP enfreint les limites d'extraction ;
- l'analyse statique trouve un motif critique, ou un avertissement que
l'installateur traite comme tel (désérialisation non sûre, obfuscation).
Les binaires compilés, les archives embarquées et le code natif sont
refusés sauf si le manifeste déclare
native-binary.
Les commentaires sont retirés avant l'analyse : une ligne mise en commentaire n'est pas signalée. Les catégories sont listées dans Sandbox des plugins et modèle de menace.
Avant l'installation, l'administrateur voit les permissions et les capacités déclarées, et ce que l'analyse a trouvé ; les emplacements, les hôtes et la signature sont montrés à la mise à jour et dans le Tableau de bord sécurité. Rien de ce qu'un plugin déclare n'est accordé en silence.
Dans quelles conditions le plugin s'exécute¶
Quoi que déclare le manifeste :
- le plugin voit son propre dossier, pas les données du serveur ;
- il n'a aucun accès direct au réseau : un plugin qui a la permission
networkatteint les hôtes de sa listeexternal_fetchpar l'appelFetchde l'hôte, et rien d'autre ; - sans
subprocess, il ne peut pas lancer de processus enfants (les threads fonctionnent) ; - il tourne sous des limites de ressources que l'administrateur peut ajuster : 256 Mio de mémoire, 64 processus et threads, 100 Mio de disque pour son dossier, et une priorité processeur abaissée, par défaut.
La signature est facultative pendant le développement. Comment signer un plugin, et la politique de signature qu'un serveur peut imposer : Écrire un plugin.
Catalogue des permissions¶
Une permission se déclare sous permissions ; toute autre valeur fait refuser
l'installation. Recevoir des webhooks (webhook.receiver) et fournir des
métadonnées (metadata.provider) sont des capacités, déclarées sous
capabilities : voir
Référence de l'API des plugins.
| Permission | Ce qu'elle accorde |
|---|---|
network |
Le backend peut appeler Fetch. Doit être combinée avec une liste external_fetch non vide ; refusée à l'installation sans elle. Le processus lui-même n'a toujours aucun socket. |
subprocess |
Le backend peut créer des processus enfants. Sans elle, le filtre noyau du lanceur refuse fork, vfork et clone sans CLONE_THREAD, et la couche seccomp refuse execve pour les plugins interprétés. Les threads fonctionnent dans les deux cas. L'administrateur voit un avertissement dédié. |
native-binary |
Le paquet peut livrer des .so, .dll, .exe, .wasm, .jar, des archives embarquées ou du code natif que l'analyse ne sait pas lire. L'administrateur voit et doit accepter du code opaque. Obligatoire pour un plugin go. |
filesystem |
Intention déclarée de toucher au système de fichiers au-delà du dossier du plugin. Enregistrée et montrée à l'administrateur ; la sandbox n'accorde aucun accès hors du dossier du plugin, quoi qu'il soit déclaré. |
media.read |
GetMediaItem et ListMediaItems sur l'hôte : la fiche média complète. |
media.write |
Réservée aux appels d'écriture de métadonnées, non servis aujourd'hui. |
api.library |
Les mêmes appels de lecture des médias que media.read. |
api.user |
Réservée à GetUserPreferences, non servi aujourd'hui. |
api.metadata |
Réservée à UpdateMetadata, non servi aujourd'hui. |
notification.sender |
Réservée à SendNotification, non servi aujourd'hui. |
public |
L'interface peut lire une projection sûre des médias (identifiant, titre, type, année, résumé, affiche), jamais les chemins ni les flux. Voir evey.media.*. |
prefs |
L'interface peut lire et écrire les préférences de l'utilisateur courant dans l'espace propre du plugin. Voir evey.prefs.*. |
hardware.gpu |
Le processus reçoit le noeud de rendu DRM de l'hôte (le vrai renderD1xx, jamais un noeud carte). Une surface d'attaque sur le pilote noyau et une frontière de mémoire GPU partagée avec le transcodeur : un GPU bloqué peut figer le transcodage. Sans elle, les noeuds GPU sont entièrement exclus de la liste Landlock ; avec elle, le lanceur ajoute une règle IOCTL_DEV limitée à ce seul fichier (Landlock ABI 5 ou plus ; sur un noyau plus ancien, l'accès en lecture et écriture suffit déjà à soumettre des commandes). Le Tableau de bord sécurité affiche un avertissement critique une fois le plugin installé. Ne l'accordez qu'à un plugin que vous feriez tourner hors sandbox. |
Règles d'accès externe¶
Déclarées dans external_fetch: [...] et vérifiées à l'installation
(validateExternalFetch). Tout ou rien : une seule entrée invalide refuse
toute l'installation.
Une entrée est un nom d'hôte. Un préfixe de schéma et un chemin final sont
retirés à l'analyse ; seul le nom d'hôte est conservé. Les hôtes correspondent
exactement, un joker *.example.com est refusé à l'installation et un suffixe de port est ignoré.
| Entrée | Valide | Raison |
|---|---|---|
api.tmdb.org |
Oui | Nom d'hôte exact, la forme normale |
https://api.tmdb.org |
Oui | Schéma et chemin retirés à l'analyse, nom d'hôte conservé |
*.tmdb.org |
Non | Les jokers sont refusés à l'installation ; listez chaque hôte |
* |
Non | Un joker seul est refusé |
192.168.1.1, ::1 |
Non | Les adresses IP sont refusées, dans les deux familles |
À l'exécution, le courtier de l'hôte ajoute ses propres limites, que le
manifeste ne peut pas élargir : http et https seulement, GET et HEAD
seulement, l'hôte cible comparé à votre liste sans tenir compte de la casse
(un suffixe :port dans une entrée est ignoré), les adresses privées ou
réservées refusées après résolution DNS, un corps plafonné à 8 Mio et une
requête à 20 secondes. Les redirections sont revérifiées contre la liste et
contre la règle d'adresse.
La même liste d'hôtes est le connect-src du cadre du plugin, préfixée de
https:// : un widget peut appeler ces hôtes directement, en https
seulement.
Liste des emplacements¶
Les plugins ne peuvent injecter des éléments d'interface que dans des emplacements explicitement autorisés. Les chemins critiques en sont volontairement absents.
| Emplacement | Authentification requise | Notes |
|---|---|---|
home.section |
Oui | Zone de contenu de la page d'accueil |
home.hero |
Oui | Zone de bannière |
library.sidebar |
Oui | Barre latérale des vues de bibliothèque |
media.detail.sidebar |
Oui | Barre latérale d'une fiche média |
player.overlay |
Oui | Surcouche du lecteur |
settings.user.appearance |
Oui | Section apparence des paramètres utilisateur |
sidebar.bottom |
Oui | Bas de la barre de navigation |
admin.nav |
Oui | Une entrée de menu dans le panneau d'administration qui ouvre la page isolée du plugin ; n'injecte rien dans les écrans d'administration existants |
Jamais autorisés : admin.* (sauf admin.nav), login.*, setup.*,
profile.security.*. Ces chemins sont critiques pour l'authentification ou
les privilèges, et une injection à cet endroit est un vecteur d'élévation de
privilèges ou d'hameçonnage.
Le contenu de admin.nav est isolé comme tout autre emplacement : il
s'affiche dans un <iframe sandbox="allow-scripts"> sans
allow-same-origin, dans une page dont la politique est
default-src 'none'. C'est du contenu tiers affiché dans la zone
d'administration, pas une capacité d'administration accordée au plugin.
Le pont limite ce qu'un cadre peut demander à la page : evey.toast au plus
3 messages par seconde, 200 caractères, sans HTML ; evey.navigate seulement
/home, /library, /media, /player, /settings et /search ;
evey.resize borné à 50-800 px. Le cadre ne détient aucun jeton : l'hôte
émet un jeton de cinq minutes limité à (plugin, utilisateur) pour les appels
public et prefs, et le serveur refuse par défaut toute méthode que ce
jeton ne nomme pas.
Déroulement d'une mise à jour¶
- L'administrateur envoie un nouveau ZIP.
PreviewPluginUpdatelance l'analyse statique et la vérification de signature, et renvoie la différence de permissions, de capacités, d'emplacements et d'external_fetchpar rapport à la version installée. - Si la différence n'est pas vide, l'administrateur doit l'accepter
avant que la mise à jour ne soit appliquée (
requires_ack = true; par la route d'envoi,accept_permission_changes=true). - L'empreinte du paquet est relevée à l'aperçu et vérifiée à l'application : le ZIP analysé est le ZIP installé.
- La clé de signature est contrôlée pour la continuité : une mise à jour
signée par une autre clé que la version installée, ou qui n'est plus
signée, est refusée tant que l'administrateur n'a pas accepté le nouvel
éditeur. Sous
EVEY_PLUGINS_COSIGN_POLICY=enforce, une signature non fiable ou invalide à l'application bloque la mise à jour même si l'aperçu a réussi.