Entrée et confidentialité d’une PWA Web Share Target
Concevez une PWA Web Share Target qui valide les entrées GET et POST, limite la conservation et garde un repli sûr.
BotBrowser Team
Vous voulez la documentation structurée pour Plateforme ?
Cet article fait partie de la bibliothèque éditoriale. Pour les étapes de configuration, la référence et les mises à jour continues, passez directement à la section docs.
Une PWA Web Share Target peut recevoir une demande de partage médiée par le navigateur, sans savoir pourquoi une personne a choisi la source ni si chaque champ devait la quitter. BotBrowser peut rejouer un fixture contrôlé et inspecter la route, la validation et le repli; il ne peut pas choisir la source du système d’exploitation ni certifier la décision de divulgation.
TL;DR
- Traitez
share_targetcomme un contrat d’entrée non fiable, jamais comme une identité. - Validez les valeurs de requête
GETet le formulairePOSTavant affichage ou stockage. - Gardez
scope, la route et les champs acceptés du manifeste étroits. - Rendez les livraisons répétées idempotentes et ne conservez que le minimum utile.
- Gardez une navigation normale ou une copie lorsque le navigateur ne peut pas installer ou invoquer la PWA.
Sommaire
- Manifeste et analyse de la requête
- Validation, confidentialité et repli
- Implémentation et acceptation
- Conclusion pratique
Manifeste et analyse de la requête
La proposition Web Share Target de WICG définit le membre share_target du manifeste pour associer un partage entrant à une URL, une méthode et des paramètres. La référence MDN Web Share Target API décrit une remise vers une PWA installée. Cette déclaration n’est ni un jeton d’authentification, ni une identité de source, ni une preuve que les données partagées peuvent être conservées. Pour le statut local séparé de cette entrée, consultez limites de Badging API pour les notifications PWA.
BotBrowser peut rejouer un fixture autorisé de même origine et inspecter la route visible, la validation et le repli. Il ne peut pas choisir la source du système d’exploitation ni certifier ce qu’une personne a décidé de divulguer; ces limites appartiennent au contrat produit.
Gardez une déclaration courte et explicite. Une cible publique limitée à une URL peut être écrite ainsi :
{
"share_target": {
"action": "/inbox/share",
"method": "GET",
"params": { "title": "title", "text": "text", "url": "url" }
},
"acceptanceMetadata": { "fixtureRevision": 3 }
}
action doit rester dans le périmètre de l’application. Une route de boîte dédiée vaut mieux qu’un attrape-tout. Pour distinguer les états détenus par l’origine, consultez le modèle de stockage du navigateur.
GET place les valeurs mappées dans l’URL d’action. Une URL peut finir dans l’historique, les journaux, les referrers ou l’analytique : n’y mettez donc jamais de jeton, de texte privé ou d’identifiant de compte. Normalisez la longueur et le codage avant le rendu.
POST retire le corps de l’URL mais traverse toujours la frontière navigateur-application. Le manifeste peut déclarer application/x-www-form-urlencoded ou multipart/form-data; le récepteur doit refuser un type inattendu et limiter le corps avant analyse. Les fichiers ont leurs propres limites de taille, type et sécurité. Un parsing réussi n’autorise pas la persistance du corps original.
Utilisez un enregistrement borné pour comparer les résultats sans conserver le contenu :
{
"method": "POST",
"route": "/inbox/share",
"fields": ["title", "text", "url"],
"bodyBytes": 4096,
"outcome": "validated-local-draft",
"fixtureRevision": 3
}
Le membre share_target du manifeste selon MDN documente la forme et le mappage. Gardez le même mappage dans le manifeste, le parseur et les tests; un url silencieusement vide est une perte de données.
Validation, confidentialité et repli
Le service worker peut recevoir la navigation et la transmettre à un client contrôlé, ou la page peut traiter la requête après navigation. Dans les deux cas, validez origine, méthode, type MIME, longueur des champs et schéma URL avant affichage. Refusez javascript: et les identifiants intégrés inattendus.
Ne déduisez pas la source grâce à Referer, au user-agent ou au temps : ces valeurs peuvent manquer. Une inscription de service worker ne prouve pas non plus que la page est contrôlée; vérifiez la route visible et le marqueur de version. Le cycle de cache du service worker et la confidentialité explique les réponses servies par un worker ancien.
Traitez un worker périmé comme un échec borné. N’affichez les valeurs qu’après validation, gardez la route d’origine en cas d’échec et proposez réessai ou copie. Ne renvoyez jamais un POST échoué sans clé d’idempotence.
Une source peut réessayer après un délai, et une personne peut invoquer deux fois la même cible. Créez un identifiant de requête propre, dédupliquez sur une courte fenêtre et ne journalisez qu’un état tel que accepted, rejected ou expired. Un identifiant de fixture opaque suffit souvent; évitez texte, octets et URL complète.
Gardez le contenu privé local jusqu’à confirmation de l’action suivante. Un bouton « enregistrer » peut créer une entrée serveur avec son autorisation et sa rétention; ouvrir la cible ne doit pas le faire. Supprimez les données temporaires après acceptation ou annulation. Le cache du service worker ne doit pas devenir une archive involontaire.
La remise navigateur ne crée pas de relation de compte. Une invitation doit être une opération confirmée et auditée séparément. Une cible de partage est une porte d’entrée, pas une décision d’accès. Consultez les limites de permissions de Web Share pour distinguer requête et livraison. Le guide Web Share API et partage déclenché par la personne précise les contraintes d’activation et d’annulation à respecter avant la réception.
Testez des requêtes synthétiques GET et POST, un corps trop grand, un champ inconnu, une URL invalide, un identifiant répété et l’absence du service worker. Vérifiez les états visibles et l’enregistrement borné, pas une feuille de partage native. Un fixture peut vérifier la limite de 4096 octets sans prévoir le contenu d’une vraie application source.
Gardez une navigation /inbox/share, une copie ou une zone de collage lorsque l’installation, le manifeste ou le support manque. Le repli doit préserver la tâche sans importer les mêmes données par une route plus large. Le guide MDN Partager des données entre applications décrit la relation utilisateur, mais pas la politique de rétention.
Implémentation et acceptation
Le manifeste est une configuration, pas un parseur. Lisez son membre share_target lors du build, refusez un action hors du périmètre de l’application et générez une liste autorisée que le runtime pourra comparer à la requête entrante. Un artefact de revue utile consigne action, method, enctype et chaque nom de paramètre. Il doit aussi consigner la révision du manifeste, car un worker et une page peuvent être mis à jour à des moments différents. Une requête traitée par la révision 2 ne doit pas être comparée silencieusement à une attente écrite pour la révision 3.
Pour une cible GET, construisez une URL à partir de l’URL de la requête et ne lisez que les clés déclarées. URLSearchParams.get() renvoie la première valeur, tandis que getAll() permet d’inspecter les clés répétées. Décidez si les répétitions sont refusées ou réduites à une valeur; ne laissez pas les valeurs par défaut du framework décider. Décodez les échappements de pourcentage une seule fois, transformez l’UTF-8 invalide en refus, ne supprimez les espaces que si le contrat du champ l’autorise et appliquez les limites après décodage. Par exemple, contrôlez avant rendu une limite de 120 scalaires Unicode pour le titre et de 4 000 pour le texte, pas après la troncature d’une colonne.
L’URL est sensible même si les valeurs semblent inoffensives. Un proxy inverse peut journaliser le chemin complet, l’historique du navigateur peut le synchroniser, un referrer peut l’exposer à une autre origine et une capture ou une télémétrie peut le copier. Définissez une Referrer-Policy adaptée, retirez la chaîne de requête par une redirection de même origine après création d’un brouillon validé et vérifiez que cette redirection ne transforme pas un refus en acceptation. La redirection nettoie; elle n’autorise pas.
Pour POST, vérifiez d’abord request.method, l’en-tête Content-Type et l’enctype déclaré. Analysez application/x-www-form-urlencoded avec un maximum d’octets et de champs. Pour multipart/form-data, exigez une boundary, refusez les parties multipart imbriquées sauf support explicite et plafonnez les octets totaux comme chaque partie. Vérifiez Content-Length lorsqu’il est présent, mais imposez aussi une limite de streaming, car une requête chunked n’a pas de longueur déclarée fiable. Arrêtez le lecteur du corps dès le dépassement et renvoyez un 413 stable ou l’état visible too-large.
L’exemple ne fixe qu’une frontière de parsing. Le code de production a encore besoin d’un traitement en streaming, d’une bibliothèque multipart avec limite explicite et d’un mappage d’erreurs qui ne réécrit jamais le corps. N’affichez jamais une exception contenant une valeur de champ. Un parseur qui accepte un champ inconnu comme admin, redirect ou callback élargit le contrat même si l’application l’ignore ensuite; refusez les noms inconnus avant la logique métier.
Le champ url a sa propre règle. Analysez-le comme une URL, exigez https: ou une exception http: explicitement revue, refusez les composants utilisateur et mot de passe et décidez si les fragments sont supprimés. Une URL vers le même endpoint de partage peut créer une boucle de redirection, tandis qu’une URL data: peut contenir des mégaoctets encodés. Si le produit n’accepte que des liens publics, refusez les noms d’hôte de réseaux privés côté serveur ainsi que les schémas dangereux dans la page. C’est une validation d’entrée, pas une garantie sur la destination.
Fichiers, rejeu et CSRF. multipart/form-data peut transporter un fichier alors que le produit visible ne demande qu’un titre et une URL. Définissez une liste de fichiers, une taille maximale et un nombre maximal séparés. Utilisez le MIME déclaré pour le routage, puis inspectez les octets magiques dans une quarantaine; l’en-tête vient de l’émetteur. Pour un petit fixture image, une règle peut autoriser image/png et image/jpeg jusqu’à 2 MiB, un seul fichier, avec une limite de pixels décodés. Refusez archives, scripts et fichiers polyglottes sans revue distincte. Ne mettez pas le chemin temporaire téléversé dans le registre d’acceptation.
Conservez les octets du fichier dans une quarantaine courte appartenant à la requête, jamais dans le cache du service worker ou une base de données navigateur partagée. Scannez ou traitez avant un enregistrement approuvé, détachez le nom temporaire du nom d’origine et supprimez au cancel, au timeout, à l’échec de parsing et à l’expiration. Un MIME valide n’est pas un scan de malware, et un brouillon local n’est pas un consentement au téléversement. Si l’environnement ne peut pas inspecter le fichier, affichez file-review-unavailable et gardez le repli au lieu d’accepter en silence.
Web Share Target est une entrée de navigation; les hypothèses CSRF ordinaires restent donc valables. Une requête de même origine peut porter des cookies ambiants, et la route peut être atteinte hors de la feuille de partage du système. Exigez une session applicative, un jeton CSRF bref pour une persistance qui modifie l’état ou une confirmation explicite avant la sauvegarde serveur. La présence de share_target ne prouve pas que le navigateur a ouvert la route via le partage. La route doit rester sûre si elle est collée dans la barre d’adresse ou ouverte par un lien normal.
Une clé d’idempotence empêche les retries de créer deux brouillons, mais n’authentifie pas l’émetteur. Générez un identifiant aléatoire à la frontière applicative, liez-le à la session actuelle et à la révision du manifeste et expirez-le après une fenêtre courte et documentée. Si la même clé arrive avec d’autres détails de méthode ou une autre session, classez-la key-conflict et ne fusionnez pas les enregistrements. Un rejeu identique peut renvoyer le résultat borné d’origine, par exemple accepted-local, duplicate ou expired, sans les champs privés.
N’utilisez pas un horodatage seul comme clé de rejeu. Le décalage d’horloge, la livraison retardée et deux partages légitimes dans la même seconde le rendent ambigu. Ne dérivez pas un marqueur de rejeu du texte brut en le déclarant anonyme: un titre ou une URL courte peut être deviné puis comparé. Préférez un ID de fixture opaque dans les journaux et gardez tout registre de comparaison contrôlé et bref. La frontière de confidentialité comprend télémétrie, rapports de crash, rejeu de session, corps de requêtes en file et exports du support, pas seulement la base principale.
Registres d’acceptation. Un registre est utile s’il permet de reproduire une branche visible sans conserver le contenu partagé. Incluez la révision du fixture, les libellés navigateur et système, la route, la méthode, l’enctype, le nombre d’octets, les champs acceptés, le résultat de validation, la classification du doublon, l’état de repli et l’échéance de suppression. Excluez texte du titre, valeurs d’URL, noms et octets de fichiers, cookies, en-têtes d’autorisation et chaîne de requête complète. Un registre stable se compare entre versions du navigateur sans devenir une archive de contenu.
{
"fixtureRevision": 3,
"route": "/inbox/share",
"method": "POST",
"enctype": "multipart/form-data",
"bodyBytes": 4096,
"fields": ["title", "text", "url"],
"fileCount": 0,
"validation": "accepted-local",
"replay": "new",
"csrf": "confirmed",
"retention": "delete-after-cancel"
}
Un tableau de décision rend le contrat vérifiable:
| Limite | Ce que le résultat établit | Prochaine action sûre |
|---|---|---|
| Manifeste incompatible ou cible non installée | Le navigateur ne peut pas invoquer cette entrée | Garder la navigation normale et le repli par collage |
GET avec champ trop grand ou répété | Le contrat URL est invalide | Retirer la requête, afficher une erreur bornée, ne pas stocker |
POST avec type MIME inattendu | Le contrat du corps déclaré n’est pas respecté | Arrêter l’analyse et renvoyer content-type-rejected |
| Fichier au-delà de la limite par fichier | La règle de fichier est dépassée | Supprimer la partie temporaire et afficher la limite |
| Champs valides sans confirmation | Un brouillon local peut être affiché | Le garder local, sans créer de fiche serveur |
| Même clé d’idempotence et mêmes détails | Une livraison répétée est observée | Renvoyer l’issue générale précédente, sans le corps |
| Même clé avec détails ou session différents | Un conflit de répétition existe | Refuser, alerter sobrement et demander une nouvelle action |
| Service worker absent ou ancien | La route prévue n’est pas disponible | Garder la route et proposer copie ou nouvel essai |
Le tableau sépare ce qu’établit une observation du navigateur de ce que le produit voudrait établir. Un état visible accepted-local prouve que ce fixture a passé les contrôles de la page. Il ne prouve pas que la source n’a envoyé que ces champs, que la personne voulait chaque valeur ou qu’une sauvegarde ultérieure respecte la rétention annoncée.
Capacité et limite de BotBrowser. Pour ce sujet Web Share Target, BotBrowser peut rejouer un fixture autorisé de même origine GET ou POST, inspecter la route du manifeste, exercer la validation du service worker et vérifier les états visibles accepté, refusé, doublon, trop grand, worker absent et repli. La documentation de plateforme BotBrowser décrit la frontière du navigateur contrôlé. BotBrowser ne peut pas ouvrir le sélecteur de partage du système, choisir une vraie application source, observer la décision de divulgation d’une personne, scanner une chaîne de fichiers externe ni certifier une suppression effectuée hors fixture.
Gardez le résultat étroit et explicite: consignez accepted-local, duplicate, rawContentKept=false, osShareSource=not-observed et serverRetention=not-certified au lieu d’affirmer qu’un sélecteur système ou une suppression serveur a été observé.
Rejouez le même fixture après avoir changé une seule variable: action, scope, champs acceptés, enctype, limite du corps, version du service worker, fenêtre d’idempotence ou route de repli. Comparez la première divergence d’état visible. Un succès en contexte contrôlé prouve le contrat de page et de requête; ce n’est ni une compatibilité universelle avec toutes les surfaces de partage ni une certification de confidentialité.
Sources
- Web Share Target de WICG
- MDN : Web Share Target API
- MDN : membre
share_target - MDN : partager des données entre applications
Conclusion pratique
Déclarez un share_target étroit, analysez GET et POST avec les mêmes règles et séparez l’acceptation de la persistance. Un fixture idempotent et un repli visible rendent la variation du navigateur vérifiable sans transformer une remise médiée en identité ou preuve de livraison. Rejouez le fixture après chaque modification du manifeste, du service worker, des champs ou de la rétention.
Cet article fait partie du guide : Surfaces de la plateforme web : carte de revue
Articles Connexes
Web Share API : limites des permissions et replis sûrs
PlateformeWeb Share API et partage déclenché par la personne
PlateformeBadging API : limites des notifications PWA
PlateformeIsolation des content scripts d’extensions de navigateur
PlateformeRécupérer une session de navigateur après une interruption réseau
PlateformeSpeculation Rules : limites de prefetch et prerender
Faites passer BotBrowser de la recherche à la production
Utilisez ces guides pour comprendre le modèle, puis passez à la validation multi-plateforme, aux contextes isolés et au déploiement navigateur prêt pour l'échelle.