Contournement du middleware par le SDK Sentry Next.js (CVE-2026-114139)
Sentry classe CVE-2026-114139 comme critique, CVSS v4.0 9.1 : sur les builds webpack, le SDK @sentry/nextjs ignore le middleware applicatif pour tous les chemins sous un tunnelRoute configuré, alors que la réécriture du tunnel ne traite que son chemin exact. Une requête non authentifiée peut donc atteindre une route sous le tunnel sans autorisation par le middleware. Sont affectés @sentry/nextjs de 9.36.0 à 9.47.1, les versions 10.x antérieures à 10.75.2 et les préversions 11.0.0 antérieures à 11.0.0-rc.1. Corrigé dans 9.47.2, 10.75.2 et 11.0.0-rc.1 ; aucune exploitation réelle n’est connue.
En bref
- @sentry/nextjs encapsule votre middleware Next.js afin de pouvoir l’ignorer pour les requêtes du « tunnel » Sentry. La condition d’exclusion était plus large que le tunnel lui-même : elle ignorait tous les chemins sous le chemin du tunnel, et pas seulement son endpoint.
- Les routes qui correspondent à un chemin sous le tunnel, par exemple une collision directe comme
/monitoring/fooavectunnelRoute: '/monitoring', ou un segment dynamique à la racine commeapp/[locale]/..., reçoivent ces requêtes sans exécution de votre middleware. Si celui-ci est le seul endroit où l’accès à ces routes est autorisé, l’autorisation est contournée. - Sentry classe la faille comme critique, CVSS v4.0 9.1, sous CWE-693 : défaillance d’un mécanisme de protection. Aucune exploitation réelle n’est connue au 24 octobre 2026 et la faille ne figure pas dans le catalogue CISA KEV. Le package npm @sentry/nextjs a enregistré 7 848 686 téléchargements pendant la semaine du 16-22 octobre 2026.
- Mettez à jour vers 9.47.2, 10.75.2 ou 11.0.0-rc.1. Aucun changement de configuration n’est nécessaire. Si vous ne pouvez pas encore effectuer la mise à jour, déplacez tunnelRoute vers un chemin sous lequel aucune de vos routes ne peut correspondre, compilez avec Turbopack ou appliquez l’autorisation dans la route elle-même en plus du middleware.
Suis-je concerné ?
Vous êtes concerné si toutes ces conditions sont réunies :
- Votre application utilise une version affectée de @sentry/nextjs avec l’option
tunnelRoutedéfinie (un chemin sous forme de chaîne outrue). - Votre application est compilée avec webpack. Les builds Turbopack, utilisés par défaut pour
next builddepuis Next.js 16, ne sont pas affectés. - Une route de votre application correspond à un chemin sous le tunnel. Il peut s’agir d’une collision directe,
/monitoring/fooavectunnelRoute: '/monitoring', ou d’un segment dynamique à la racine,app/[locale]/..., qui correspond à n’importe quel premier segment du chemin. - Votre middleware est le seul endroit qui applique l’autorisation pour ces routes.
Le bulletin de Sentry précise aussi ce que le contournement ne fait pas : ignorer le middleware n’accorde aucun privilège à la requête, et les routes qui vérifient la session côté serveur restent protégées. Les services de Sentry eux-mêmes et les données de votre organisation Sentry ne sont pas affectés.
| Package | Versions affectées | Version corrigée |
|---|---|---|
| @sentry/nextjs 9.x | 9.36.0 – 9.47.1 | 9.47.2 |
| @sentry/nextjs 10.x | 10.0.0-alpha.0 – 10.75.1 | 10.75.2 |
| Préversions de @sentry/nextjs 11 | 11.0.0-alpha.0 – 11.0.0-rc.0 | 11.0.0-rc.1 |
Vérifiez la version installée et les conditions qui s’appliquent :
# Installed SDK version
npm ls @sentry/nextjs
node -e "console.log(require('@sentry/nextjs/package.json').version)"
# Lock file check (package-lock.json v2/v3 records the package under "node_modules/@sentry/nextjs")
grep -A1 '"node_modules/@sentry/nextjs"' package-lock.json
# Is the tunnel route configured?
grep -rn "tunnelRoute" next.config.* sentry.* .sentryclirc 2>/dev/null
# Container image check
docker run --rm <your-image> node -e "console.log(require('@sentry/nextjs/package.json').version)"
Vérifiez ensuite quelles routes peuvent correspondre à un chemin sous le tunnel : comparez les segments du répertoire app/ (ou pages/) au premier segment du chemin du tunnel. Un segment dynamique à la racine comme [locale] correspond à n’importe quel premier segment.
Comment corriger le problème ?
Mettez le SDK à jour. L’exclusion ne concerne désormais que les requêtes réellement prises en charge par la réécriture du tunnel, sans changement de configuration :
npm install @sentry/nextjs@10.75.2
# 9.x line: npm install @sentry/nextjs@9.47.2
# 11 prerelease line: npm install @sentry/nextjs@11.0.0-rc.1
# or: pnpm add @sentry/nextjs@10.75.2 | yarn add @sentry/nextjs@10.75.2
Si vous ne pouvez pas effectuer immédiatement la mise à jour, le bulletin de Sentry propose trois solutions de contournement :
- Définir
tunnelRoutesur un chemin sous lequel aucune de vos routes ne peut correspondre, ou supprimer l’option. - Compiler avec Turbopack, utilisé par défaut pour
next builddepuis Next.js 16. - Appliquer l’autorisation dans la route, le layout ou le chemin d’accès aux données, en plus du middleware.
Ces solutions ont des limites : la première dépend du maintien d’une structure de routes sans collision au fil de l’évolution de l’application ; la deuxième modifie votre pipeline de build ; la troisième implique de dupliquer une logique d’autorisation que le middleware devait centraliser. La mise à jour supprime l’incohérence au sein du SDK pour tous les appelants.
Quelle est la cause racine ?
Le middleware Next.js s’exécute avant les routes et sert couramment à appliquer l’autorisation. Lorsque @sentry/nextjs instrumente le middleware dans les builds webpack, il encapsule votre fonction dans wrapMiddlewareWithSentry. Celle-ci vérifie d’abord si la requête entrante est une requête du tunnel Sentry et, si c’est le cas, retourne immédiatement sans appeler votre code.
Le tunnel sert à contourner les bloqueurs de publicité. Les événements du navigateur sont envoyés vers un chemin de votre propre serveur, par exemple /monitoring, puis une réécriture Next.js les transmet à Sentry. La réécriture ne prend en charge que le chemin exact du tunnel avec les paramètres de requête o et p définis, qui transportent les identifiants d’organisation et de projet Sentry.
L’exclusion utilisait un test plus large. Avant le correctif, la fonction d’encapsulation vérifiait seulement si le chemin de la requête se trouvait sous celui du tunnel :
// packages/nextjs/src/common/utils/tunnelPathnameMatch.ts (before the fix)
export function isPathnameUnderSentryTunnelRoute(pathname: string, tunnelPath: string): boolean {
return pathname === tunnelPath || pathname.startsWith(`${tunnelPath}/`);
}
Elle ignorait ensuite le middleware pour tout ce qui correspondait :
// packages/nextjs/src/common/wrapMiddlewareWithSentry.ts (before the fix)
if (tunnelRoute && typeof tunnelRoute === 'string') {
const req: unknown = args[0];
if (req instanceof Request) {
const url = new URL(req.url);
const isTunnelRequest = isPathnameUnderSentryTunnelRoute(url.pathname, tunnelRoute);
if (isTunnelRequest) {
// returns a response that lets the request continue, without calling
// the wrapped middleware
return new Response(null, { status: 200, headers: { 'x-middleware-next': '1' } });
}
}
}
La faille réside dans la différence entre ces deux vérifications. La réécriture prend en charge /monitoring avec des paramètres o et p valides. L’exclusion couvrait /monitoring et tous les chemins commençant par /monitoring/, avec ou sans paramètres. Une requête vers /monitoring/foo n’est pas réécrite vers Sentry : Next.js la route vers votre application. Mais la fonction d’encapsulation a déjà retourné sa réponse ; votre middleware ne s’exécute donc jamais pour cette requête.
En une phrase : l’exclusion du middleware répondait à « ce chemin se trouve-t-il sous la route du tunnel ? » alors qu’elle devait répondre à « cette requête sera-t-elle réellement prise en charge par la réécriture du tunnel ? ». La différence entre ces deux ensembles correspond exactement aux requêtes qui atteignent vos routes sans les vérifications d’authentification du middleware.
Comment la faille est-elle exploitée ?
Aucune preuve de concept publique n’existe et aucune exploitation réelle n’est connue au 24 octobre 2026. Voici le chemin d’attaque décrit par le bulletin et le correctif :
- L’application cible définit
tunnelRoutesur un chemin, généralement/monitoring, et utilise webpack pour le build. - L’application possède une route qui correspond à un chemin sous le tunnel : soit une collision directe, soit un segment dynamique à la racine tel que
app/[locale]/page.tsx, qui accepte/monitoringcomme valeur de locale. - L’attaquant envoie une requête non authentifiée vers ce chemin de route.
- La fonction d’encapsulation du middleware du SDK repère un chemin sous la route du tunnel et renvoie la réponse de poursuite. Le corps du middleware de l’application, y compris sa logique d’autorisation, ne s’exécute jamais.
- Next.js transmet la requête au gestionnaire de route. Si rien entre ce gestionnaire et les données ne vérifie à nouveau la session, la requête est traitée comme si elle avait passé le middleware.
L’exploit est une simple requête HTTP. Son effet dépend entièrement de ce que le middleware de l’application protégeait à lui seul : redirections d’authentification, vérifications de tenant, restriction de fonctionnalités ou autorisation au niveau des routes.
Déroulement de l’attaque
/monitoring/foo ou /[locale]/..."] --> B["Encapsulation du middleware SDK :
le chemin est sous la route du tunnel"] B --> C["La fonction renvoie une réponse de poursuite,
le middleware ne s’exécute jamais"] C --> D["La réécriture du tunnel ne correspond pas :
Next.js route vers l’application"] D --> E["Le gestionnaire traite la requête
sans autorisation par le middleware"] E --> F["L’impact dépend de ce que
le middleware protégeait à lui seul"]
La vérification défaillante se situe en B : la décision d’exclusion est plus large que la réécriture qu’elle est censée servir.
Que peut faire un attaquant ?
Lire ou modifier ce que les routes affectées exposent, sans leurs vérifications de middleware. Le bulletin limite l’impact à la confidentialité et à l’intégrité du système vulnérable, et le vecteur CVSS v4.0 est AV:N/AC:L/AT:P/PR:N/UI:N, sans privilège ni interaction utilisateur. Des conditions d’attaque sont présentes parce que les prérequis de configuration doivent se cumuler : tunnelRoute défini, build webpack, route correspondant à un chemin sous le tunnel et autorisation uniquement dans le middleware.
Selon le bulletin, le contournement n’accorde aucun privilège et les routes qui vérifient la session côté serveur restent protégées. Les services de Sentry et les données de votre organisation Sentry ne sont pas affectés.
Pourquoi le correctif fonctionne-t-il ?
Le correctif, la pull request #24499 avec les rétroportages #24565 et #24760, remplace le test de préfixe de chemin par une fonction qui correspond exactement aux requêtes prises en charge par la réécriture :
// packages/nextjs/src/common/utils/tunnelPathnameMatch.ts (after the fix)
/**
* Returns true only for requests the tunnel rewrite (see `setUpTunnelRewriteRules`) would serve.
*
* This decides whether the user's middleware is skipped, so it must never be broader than the rewrite:
* anything it matches that Next.js does not rewrite to Sentry reaches the app without middleware.
*/
export function isSentryTunnelRequest(request: Request, tunnelPath: string): boolean {
// The SDK transport only ever sends POST requests
if (request.method !== 'POST') {
return false;
}
const url = new URL(request.url);
if (url.pathname !== tunnelPath && url.pathname !== `${tunnelPath}/`) {
return false;
}
// Next.js evaluates `has` conditions against the last value of a repeated query param, so every value has to qualify
return ['o', 'p'].every(key => {
const values = url.searchParams.getAll(key);
return values.length > 0 && values.every(value => /^\d+$/.test(value));
});
}
La fonction d’encapsulation appelle désormais isSentryTunnelRequest(req, tunnelRoute) à la place du test de préfixe. Trois propriétés rendent les deux côtés cohérents : uniquement des requêtes POST (le transport du SDK n’en envoie jamais d’autres), uniquement le chemin exact du tunnel avec ou sans barre oblique finale, et uniquement avec des paramètres o et p présents et constitués exclusivement de chiffres, conformément à l’évaluation des conditions has de réécriture par Next.js. Toute requête qui échoue à l’une de ces vérifications passe désormais par votre middleware comme n’importe quelle autre requête.
Le correctif résout entièrement l’écart décrit : l’exclusion et la réécriture partagent désormais la même définition d’une requête de tunnel, énoncée comme invariant dans le commentaire du code. La fonction d’encapsulation n’existe toujours que dans les builds webpack ; elle n’a jamais été active dans les builds Turbopack, qui n’ont donc jamais été affectés.
Comment vérifier si j’ai été compromis ?
Aucun indicateur de compromission n’a été publié pour ce bulletin et aucune exploitation n’est connue. Si vous utilisez une configuration affectée et souhaitez rechercher ce schéma :
- Dans les journaux d’accès du serveur web ou de Next.js, recherchez les requêtes non authentifiées ayant atteint des routes sous le chemin du tunnel, et comparez-les à ce que votre middleware aurait dû rejeter ou rediriger : requêtes vers des chemins de type
/monitoring/...sans paramètresoetp, et requêtes vers des segments dynamiques à la racine tels que/en/..., depuis des sources que votre middleware aurait bloquées. - Examinez le traitement côté serveur des routes affectées pour repérer toute hypothèse selon laquelle le middleware aurait déjà authentifié l’appelant.
Si vous trouvez des requêtes que le middleware aurait dû arrêter et qu’il n’a pas bloquées, considérez que ces sessions ont atteint la route sans authentification et évaluez ce que cette route a renvoyé.
Chronologie
- 18 septembre 2026 : le correctif est intégré à la branche principale (commit 878b685, « Align tunnel request matching in middleware with tunnel rewrite »).
- 21 septembre 2026 : le rétroportage v10 est intégré (commit d525a2f) ; Sentry publie 11.0.0-rc.1 et 10.75.2 le 22 septembre 2026.
- 24 septembre 2026 : Sentry publie le bulletin GHSA-mchm-gjx6-7h55.
- 28 septembre 2026 : le rétroportage v9 est intégré (commit c122aac) ; Sentry publie 9.47.2 le 29 septembre 2026.
- 21 octobre 2026 : CVE-2026-114139 est publiée par le NVD.
- 22 octobre 2026 : le bulletin est publié et examiné dans la GitHub Advisory Database.
- 24 octobre 2026 : publication de cet article. Aucune exploitation réelle n’est connue ; la faille ne figure pas dans le catalogue CISA KEV.
FAQ
La configuration par défaut est-elle affectée ?
La route du tunnel est facultative : la configuration withSentryConfig par défaut, sans tunnelRoute, n’est donc pas affectée. Les conditions du bulletin constituent la checklist complète : tunnelRoute défini, build webpack, route correspondant à un chemin sous le tunnel et autorisation uniquement dans le middleware.
Les builds Turbopack sont-ils affectés ?
Non. L’encapsulation du middleware avec l’exclusion n’existe que dans l’intégration webpack. Turbopack, utilisé par défaut pour next build depuis Next.js 16, n’a jamais eu cette exclusion. Les commentaires du code du SDK signalent cette différence comme un problème de cohérence entre builds qui reste présent après le correctif.
Cette faille permet-elle aux attaquants d’accéder à mon organisation Sentry ?
Non. Le bulletin de Sentry indique que ses propres services et les données de votre organisation Sentry ne sont pas affectés. Le contournement concerne les routes de votre application, pas celles de Sentry.
Pourquoi un SDK de supervision est-il classé critique ?
Parce que l’impact dépend de votre middleware, pas du SDK. Lorsque le middleware constitue l’unique contrôle d’autorisation pour une route en collision, une requête réseau non authentifiée peut l’atteindre. Le vecteur CVSS v4.0 évalue ce cas à 9.1, avec un impact élevé sur la confidentialité et l’intégrité. Sentry le classe également sous CWE-693 : défaillance d’un mécanisme de protection.
J’utilise le middleware pour les redirections, pas pour l’autorisation. Dois-je tout de même effectuer la mise à jour ?
Oui. Effectuez la mise à jour lorsque cela vous convient : les redirections et les autres usages du middleware sans lien avec l’autorisation n’ont pas d’impact sur la sécurité, mais les structures de routes évoluent, et la mise à jour n’introduit aucun changement incompatible.
Scannez vos applications Next.js avec Ostorlab pour repérer la version de @sentry/nextjs et l’utilisation de tunnelRoute dans vos dépôts.
Références
- Bulletin Sentry GHSA-mchm-gjx6-7h55 : https://github.com/getsentry/sentry-javascript/security/advisories/GHSA-mchm-gjx6-7h55 (consulté le 24 octobre 2026)
- Entrée de la GitHub Advisory Database : https://github.com/advisories/GHSA-mchm-gjx6-7h55 (consultée le 24 octobre 2026)
- Fiche CVE-2026-114139 (CVSS v4.0 9.1, CWE-693, plages affectées) : https://cveawg.mitre.org/api/cve/CVE-2026-114139 (consultée le 24 octobre 2026)
- Pull request du correctif #24499 : https://github.com/getsentry/sentry-javascript/pull/24499 (consultée le 24 octobre 2026)
- Commit du correctif 878b685 (branche principale) : https://github.com/getsentry/sentry-javascript/commit/878b685c85dc12045e47e1932c96f5381d7ac532 (consulté le 24 octobre 2026)
- Commit du rétroportage v10 d525a2f : https://github.com/getsentry/sentry-javascript/commit/d525a2f6015b47384bc139c30d58e0d5435d52e5 (consulté le 24 octobre 2026)
- Commit du rétroportage v9 c122aac : https://github.com/getsentry/sentry-javascript/commit/c122aac4f29541eb6da494296822c91eab3cf5ae (consulté le 24 octobre 2026)
- Version 10.75.2 (publiée le 22 septembre 2026) : https://github.com/getsentry/sentry-javascript/releases/tag/10.75.2
- Version 9.47.2 (publiée le 29 septembre 2026) : https://github.com/getsentry/sentry-javascript/releases/tag/9.47.2
- Version 11.0.0-rc.1 (publiée le 22 septembre 2026) : https://github.com/getsentry/sentry-javascript/releases/tag/11.0.0-rc.1
- Nombre de téléchargements npm de @sentry/nextjs (7 848 686 téléchargements, semaine du 16-22 octobre 2026) : https://api.npmjs.org/downloads/point/last-week/@sentry/nextjs (consulté le 24 octobre 2026)