Quand un argument d'outil MCP devient un intent Android : les sinks de mobile-mcp
CVE-2026-35394 permet à une URL contrôlée par le modèle de déclencher des intents Android arbitraires via l'outil mobile_open_url de mobile-mcp. Couplée à une CVE jumelle de path traversal, elle révèle un motif : des arguments d'outil MCP qui atteignent des sinks sans validation.
En bref
mobile-mcpest un serveur MCP de développement et d’automatisation mobile. CVE-2026-35394, publiée en avril 2026 (CWE-939, vecteur CNA GitHubAV:N/AC:L/PR:N/UI:R/S:U/C:L/I:H/A:H, élevée), permet à une URL transmise à l’outilmobile_open_urlde déclencher des intents Android arbitraires —tel:,sms:, codes USSD,content:— parce que l’outil ne valide jamais le schéma de l’URI. Corrigée en 0.0.50. Un bug jumeau, CVE-2026-33989 (path traversal, corrigé en 0.0.49), relève de la même classe via un autre sink. La leçon ne concerne pas un seul paquet : les arguments d’outil MCP sont accessibles à un attaquant, et tout sink qu’ils atteignent doit les valider.
De quoi s’agit-il ?
Le serveur @mobilenext/mobile-mcp de Mobile Next expose un téléphone ou un émulateur à un agent LLM sous forme d’outils MCP — toucher, saisir, capturer l’écran, ouvrir une URL. Selon l’avis de sécurité GitHub GHSA-5qhv-x9j4-c3vm, les versions antérieures à 0.0.50 transmettent la chaîne fournie à l’outil mobile_open_url directement au système d’intents d’Android, sans aucune liste d’autorisation de schémas. Android résout bien plus que http(s) : tel: passe un appel, sms: ouvre un message, content: atteint un content provider, et des codes du composeur peuvent déclencher des actions USSD. Ainsi, une valeur que le modèle pouvait librement choisir devient une action sur l’appareil.
Le même projet a livré CVE-2026-33989 quelques jours plus tôt (publication NVD le 2026-03-27, corrigée en 0.0.49) : les paramètres saveTo et output des outils de capture et d’enregistrement d’écran étaient écrits sur le disque sans validation, autorisant une traversée de répertoire hors de l’espace de travail. Deux CVE, deux outils, une seule cause racine — des arguments d’outil non validés atteignant un sink puissant.
Comment ça fonctionne
Un argument d’outil MCP n’est pas une « entrée de confiance ». C’est ce que le modèle a produit, et le contexte du modèle contient couramment du texte non fiable : une page web parcourue, un e-mail résumé, un ticket trié. C’est la surface d’injection de prompt indirecte — texte de l’attaquant en amont, appel d’outil en aval. Lorsque l’outil transmet cet argument à un sink sans le vérifier, l’injection se concrétise en action réelle.
Pour mobile_open_url, l’étape dangereuse est l’absence de contrôle du schéma avant la transmission :
// Forme vulnérable (< 0.0.50) : le schéma n'est jamais contraint
async function mobile_open_url(url) {
// url peut être tel:, sms:, content: ou une chaîne du composeur/USSD —
// résolue telle quelle par le système d'intents d'Android.
await device.openUrl(url); // sink : intent arbitraire
}
// Forme corrigée (0.0.50) : on autorise d'abord le schéma
function assertWebScheme(url) {
const ok = ["http:", "https:"];
if (!ok.includes(new URL(url).protocol)) throw new Error("scheme not allowed");
}
Le vecteur CVSS (UI:R) traduit le fait qu’un humain doit encore exécuter l’agent sur l’appareil connecté, mais aucun privilège attaquant n’est requis (PR:N) et la requête est accessible par le réseau (AV:N). L’impact en intégrité et disponibilité est élevé : l’action s’exécute sur un vrai téléphone. Nous ne publions pas de chaîne fonctionnelle ; le propos est la forme de la faille, pas un payload.
Pourquoi c’est important
L’intérêt de MCP est qu’un même agent peut piloter de nombreux outils. Son risque est que chaque outil décide seul s’il fait confiance à ses arguments — il n’existe aucun médiateur central pour dire « cette chaîne provient de la sortie du modèle, à traiter comme non fiable ». mobile-mcp se trouve devant un sink particulièrement puissant (le résolveur d’intents d’un téléphone), mais le motif est partout : un MCP base de données qui interpole un argument dans du SQL, un MCP shell qui le transmet à une commande, un MCP système de fichiers qui le concatène dans un chemin. Chaque nouvel outil est une nouvelle occasion de réintroduire la classe — ce qui explique précisément deux CVE en deux semaines.
Le danger pratique est une frontière illusoire. Les équipes raisonnent sur « l’agent » comme l’objet à sécuriser et oublient que le serveur MCP est un adjoint confus (confused deputy) : il détient les privilèges de l’appareil ou de l’hôte et les emploiera sur des instructions qui remontent in fine à du contenu non fiable.
Défenses
- Mettre à jour.
mobile-mcp≥ 0.0.50 corrige le sink d’intent ; ≥ 0.0.49 corrige le sink de traversée de chemin. Épinglez la version et vérifiez avecnpm list @mobilenext/mobile-mcp. - Lister en autorisation à chaque sink, pas seulement celui-ci. Validez le schéma des sinks d’URL (
http/httpsuniquement), canonicalisez et confinez les chemins des sinks de fichiers, paramétrez les sinks de requêtes. Traitez chaque argument d’outil comme une sortie de modèle non fiable. - Exécuter les serveurs MCP au moindre privilège. Pilotez un émulateur jetable plutôt qu’un appareil personnel ; refusez les permissions téléphonie/SMS dont le flux n’a pas besoin ; isolez le système de fichiers et le réseau pour qu’un mauvais argument n’atteigne pas de données sensibles.
- Auditer votre surface d’outils pour ce motif. Recherchez, dans vos serveurs MCP et ceux de tiers, les arguments qui s’écoulent vers
openUrl,exec, des écritures de fichiers ou des constructeurs de requêtes sans validation, et verrouillez ce contrôle en CI pour qu’un futur outil ne puisse pas le réintroduire. - Journaliser et alerter sur les schémas hors-bande. Une valeur
tel:,sms:,content:ou non-http(s)atteignant un outil d’URL — ou une écriture hors de l’espace de travail — est un signal de chasse utile indiquant qu’un argument a été influencé par un attaquant.
État
| Élément | Référence | Date | Notes |
|---|---|---|---|
| CVE-2026-35394 | GHSA-5qhv-x9j4-c3vm | 2026-04 | Injection d’intent mobile_open_url, CWE-939, vecteur C:L/I:H/A:H |
| Version corrigée | mobile-mcp 0.0.50 | — | Validation de schéma ajoutée |
| CVE-2026-33989 | GHSA-3p2m-h2v6-g9mx | 2026-03-27 (NVD) | Traversée de chemin dans les outils de capture/enregistrement, CWE-22/73 |
| Version corrigée | mobile-mcp 0.0.49 | — | Validation de chemin ajoutée |
Le bon cadrage n’est pas « corriger mobile-mcp ». C’est que chaque argument d’outil MCP est accessible à ce qui se trouve dans le contexte du modèle, et qu’un outil qui le transmet à un sink privilégié sans validation transforme une injection de prompt en amont en action en aval — sur un téléphone, un système de fichiers ou une base de données.
Sources
- → https://www.sentinelone.com/vulnerability-database/cve-2026-35394/
- → https://advisories.gitlab.com/pkg/npm/@mobilenext/mobile-mcp/CVE-2026-35394/
- → https://github.com/mobile-next/mobile-mcp/security/advisories/GHSA-5qhv-x9j4-c3vm
- → https://nvd.nist.gov/vuln/detail/CVE-2026-33989
- → https://github.com/mobile-next/mobile-mcp/security/advisories/GHSA-3p2m-h2v6-g9mx