Sumário `node-tar` (npm `tar`) contém um exaustão de pila de recuperação descontrolada do DoS no ajudante interno `mapHas` usado pelo `filesFilter`. Quando um consumidor chama `tar.t(...)' ou `tar.x(...)' com uma lista de seleção de membros não vazia, o nodo-tar instala um filtro que fecha sobre o recursivo ` mapHas` (`src/list.ts: 33 - 44 `). `mapHas` caminha um caminho de entrada para cima de uma chamada `path.dirname()` por recursão ** sem cap de segmento**. Um único alcatrão criado com um cabeçalho de caminho longo GNU-`L` (ou PAX-`x`) pode fornecer um caminho de dezenas de milhares de segmentos separados `/` (até `maxMetaEntrySize` = 1 MiB). A recursão transborda a pilha de chamadas, lançando um `RangeError` incaptável que termina o processo de Nó em consumidores async/ streaming. ## Causa Raiz `filesFilter` (`src/ list.ts: 27 - 51 `) é instalado sempre que um chamador passa por uma lista de seleção de membros (`src/list.ts: 119 - 122 `, ` src/ extract.ts: 55 - 57 `). O filtro é invocado em `src/parse.ts: 253 ` (`entry.ignore = entry.ignore.this.filter(entry.path, entry)`) dentro de `Parser[CONSUMEHEADER]` — e, crucialmente ** fora**, a única tentativa/ captura nesse método (que envolve `novo cabeçalho' em `src/parse.ts: 179 - 183 `). `MapHas` recurses uma vez por segmento de caminho sem limite de profundidade. O guarda `Desempacotar` `maxDepth` (`src/unpack.ts: 342 `, em `[CHECKPATH]`) apenas funciona no evento `'entrada'', que dispara *após* `CONSUMEHEADER` já invocou o filtro — então a pilha transborda antes de qualquer guarda de profundidade executar. `tar.t` (lista) não tem nenhum `maxDepth`.
Impacto Negação de serviço não autenticada e remotamente desencadeável: a ~ 188 -byte gzip (ї 26 KB tar) bloqueia qualquer serviço que lista ou extrai * membros selecionados* de um arquivo não confiável (registros de pacotes, restauração de artefato/cache do CI, processadores de upload). No async (`await tar.t(...)`/`tar.x(...)`) e no streaming/`pipe` os consumidores o `RangeError` escapa da promessa como um `uncaughtException` e termina o processo — o padrão defensivo `try/catcha` em torno da chamada async NÃO impede que ela seja capturada. (A API síncronos é pegada; os caminhos async/ stream — o padrão dominante do servidor — não são.) ## Prova do conceito ```js // Construir um tar cuja única entrada tem um longo caminho GNU-L de ~ 12,000 segmentos "a/" (~ 26 KB), // gzip (ї 188 bytes), em seguida, tem uma lista de consumidores/extrato com seleção de membros: const tar = require('tar'); aguarde o tar.t({ arquivo: 'evil.tar.gz', gzip: true }, ['algum membro']); // -> RangeError, processo de saída ```` Reproduzido empiricamente no Nodo v 24.18.0 contra o `dist/commonjs` construído do nó-tar 7.5.20: 188 -byte gzip → 26,112 -byte tar ( 12,000 segmentos) → não capturado `Erro da gama: tamanho máximo da pilha de chamada excedido` → saída do processo. Uma execução de controle sem lista de seleção de membros (filtro não instalado) analisa limpo (saída) 0 ) isolando ` mapHas ' como a única causa.
Cadeia de ataque 1. ** Entrada.** O atacante faz um alcatrão com um cabeçalho de longo percurso GNU `L` (ou PAX `x`) cujo corpo é `"a/"`×~ 12000 (~ 26 KB), seguido de um item de arquivo normal. - **Guard:** `maxMetaEntrySize` cobre o corpo meta em 1 MiB (`src/parse.ts': 241 `). - **Prova de Bypass:** 26 KB ї 1 MiB → aceito (verificado: 26 Arquivo KB analisado até o filtro. 2. **Trigger.** Serviço de vítimas chama `tar.t({file},[sel]]' ou `tar.x({file,cwd},[sel]' (seleção de membros — uma API comum documentada). - **Guard:** `Despack.maxDepth` (por omissão) 1024 ) no ` src/ unpack.ts: 342 `; descompressão-racio- guarda. - **Prova de Bypass:** `maxDepth` vive em `[CHECKPATH]` no evento `'entrada'', que dispara *após* a chamada de filtro de `CONSUMEHEADER` — o colapso ocorre antes dele (extrair saídas 1 com o maxDept. padrão). `tar.t ' não tem o maxDept. Razão é ~ 139 × (trivial); nenhum tampa total de bytes se aplica ao corpo meta não comprimido. 3 **Bolsa.** `This.filter(entry.path)` → `mapHas` recurses uma vez por segmento `/` (`src/list.ts: 39 `). - **Guard:** tentar/ capturar em `CONSUMEHEADER`. - **Prova de Bypass:** o único tente/ captura envolve `novo cabeçalho` (`src/ parse.ts: 179 - 183 `); a chamada `This.filter((...)` em `src/parse.ts: 253 ` está fora dele. O `RangeError` propaga- se fora do caminho do stream write/`'data'` → exceção não capturada (verificada: `process.on('uncaughtException')` fogos; o 'async' `await`+`try/catcha' não intercepta. 4. **Impact.** Finação do processo de nó; a 188 -byte gzip bloqueia qualquer consumidor que lista/ extrai membros selecionados de arquivos não confiados. ## Evidência de Bypass - `mapHas` é a recursão independente do nome de membro: o acidente dispara mesmo quando os membros solicitados não correspondem ao caminho de entrada malicioso — o atacante só precisa que o consumidor use a seleção de membros. - O `mapHas` está em sobrecarga. 20 k– 30 segmentos k; no caminho real de transmissão (topo `escrever → CONSUMECHUNK → CONSUMO TEÚNICO → filtro`) ele falha em ≤ 8 segmentos k (finder's ~ 12 A estimativa do k é precisa para o caminho acessível). - Controle (sem lista de membros → sem filtro) analisa limpo (saída 0 ) isolando `mapHas`.
Versão afetada `<= 7.5.20 ` (npm `tar`). `mapHas` apresenta textual na etiqueta `v 7.5.20 ` (último lançamento do GitHub e npm `dist-tag latest`); nenhum cap de segmento/profundidade no `src/list.ts` ou no caminho de filtro `CONSUMEHEADER`; HEAD == 7.5.20, nenhuma correção não publicada. ## Sugestão de Reescrever o `mapHas` iterativamente (caminhar `dirname` em um loop `while` com um segmento/ cap visitado), ou impor um limite de caminho- segmento rígido em `Header`/ `Parser` independente de `maxMetaEntrySize`, aplicado antes de qualquer execução de filtro por entrada.
Distinção da Nota de Dedup do CVE- 2024 - 28863 / GHSA- f 5 x 3 - 32 g 6 - qm 9 j "falta de validação de profundidade de pastas" (que limita a recursão ` mkdir` durante a *extração* via `maxDepth` em `Despack[ CHECKPATH]` no evento `'entrada'' — um imersão diferente, caminho de código e correção; executa após o filtro e não se aplica a `tar.t`). Também são diferentes dos avisos de falhas PAX NUL/numeric-path (improper- input- to- fs / type confusion, e não recursão) e do aviso de bomba- gzip (exaustão de recursos no disco escreve). Nenhum toque `list.ts`/`filesFilter`/`mapHas` ou requer a seleção de membros.
--- Reportado por **zx (Jace)** — GitHub: @manus-use. Registro de aconselhamento: GHSA-r 292 - 9 mhp- 454 m. Identificadores relacionados: CVE- 2026 - 73566.
Tempo: GitHub Advisory Database publicou este registro em 2026 - 07 - 24 T 16: 26: 16.000 Z e lista a sua última modificação como 2026 - 08 - 21 T 19: 08: 22.000 Z.
Severidade: ALTAMENTE. Dados de pontuação publicados: CVSS_V 3: CVSS: 3.1 /AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H.
Software afetado e informações de versão: tar do pacote npm — ECOSYSTEM: introduzido 0, corrigido 7.5.21.
Classificação e evidência: identificadores de fraqueza CWE- 400, CWE- 674. O registro contém 5 suporte de referências nestes tipos: WEB, AVISO, EMBALAGAMENTO.