Skip to content

bug: block Zip Slip in /import extraction and upgrade adm-zip to 0.6.1 (sfind-43966ddb) - #1105

Open
devin-ai-integration[bot] wants to merge 10 commits into
mainfrom
devin/sfind-43966ddb-import-zip-slip
Open

devin-ai-integration[bot] wants to merge 10 commits into
mainfrom
devin/sfind-43966ddb-import-zip-slip

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

Summary

Corrige o Zip Slip (finding sfind-43966ddb, crítico) em exports.import (routes/index.js:247-257): zip.extractAllTo('/tmp/extracted_files', true) com adm-zip 0.4.7 fazia path.resolve(target, entryName) sem checar ../, então um zip anônimo com ../../usr/src/goof/routes/index.js sobrescrevia arquivos do servidor.

Duas camadas:

  1. Validação por entrada (utils.safeExtractZip(zip, targetDir)):
    for entry in zip.getEntries():           // getEntries() falhou -> ZIP_INVALID_ARCHIVE
      dest = path.resolve(root, entry.entryName)
      if !dest.startsWith(root + path.sep): throw ZIP_ENTRY_OUTSIDE_TARGET   // rejeita o arquivo inteiro antes de gravar
    extrai para staging (mkdtemp) -> getData() precisa ser Buffer -> rename para root; staging removido no finally
    
    Na rota: ZIP_ENTRY_OUTSIDE_TARGET / ZIP_INVALID_ARCHIVE (e erro no AdmZip(buffer)) -> 400 Invalid archive.; outros erros -> next(err).
  2. adm-zip 0.4.7 -> 0.6.1 (package.json + package-lock.json com integridade sha512), que também traz a checagem de path traversal/symlink da própria lib.

Commits novos neste PR: (a) uma entrada de diretório ./ (resolve para o próprio root) é aceita, mas só se for diretório; (b) o adm-zip 0.6.x lê o diretório central de forma preguiçosa, então um zip corrompido lança em getEntries(). Isso agora vira ZIP_INVALID_ARCHIVE (400) em vez de 500.

Contrato de API: POST /import com zip malicioso ou corrompido agora retorna 400 Invalid archive.. Antes, o zip malicioso retornava 302 e gravava o arquivo; o corrompido retornava 500 (ou 302 com CRC inválido). Zips válidos e a importação de texto continuam retornando 302.

Fora do escopo: o finding também recomenda autenticação em /import. Não adicionei, porque o formulário de importação da página inicial é usado por visitantes anônimos e isso mudaria o fluxo do app. A correção de Zip Slip acima não depende disso.

Duplicado: os 6 commits de #1075 (sfind-ed54b459) e os 2 commits de adm-zip de #1074 (sfind-91ffb09a) foram aplicados com cherry-pick, mais o commit do item acima. Abri um PR novo para este finding pela regra de um ticket por PR. Só um destes PRs deve ser mergeado (#1075/#1079/#1074/#1082 se sobrepõem).

Como testar

App real (NODE_OPTIONS=--openssl-legacy-provider node app.js, mongod local) + curl -F importFile=@x.zip;type=application/zip localhost:PORT/import:

caso main (adm-zip 0.4.7) este branch (adm-zip 0.6.1)
PoC do finding: ../../home/ubuntu/goof4396-target/routes/index.js 302, arquivo alvo sobrescrito (/* PWNED by zip slip */) 400, alvo intacto, nada extraído
zip com ../ed54-pwned.txt 302, /tmp/ed54-pwned.txt criado 400, nada gravado
zip válido (backup.txt, sub/dir/note.txt) 302, extraído 302, extraído
zip com ./ + ./backup.txt 302, extraído 302, extraído
importação de texto 302 302
zip corrompido / truncado 500 400
zip com CRC inválido 302, extraído 400, nada gravado

O código deste branch também foi testado com adm-zip 0.4.7: a PoC retorna 400 e o alvo fica intacto, então a validação protege mesmo sem o upgrade.

Não há suíte de testes automatizada: npm test é snyk test e precisa de auth.

Devin-Org: engineering

Link to Devin session: https://devin-gtm.devinenterprise.com/sessions/082d863792ed495698cd6559cdcac597
Open in Devin Desktop: https://devin-gtm.devinenterprise.com/desktop/session/082d863792ed495698cd6559cdcac597?variant=devin


Devin Review

Status Commit
⚪ Not started —

Run Devin Review

Enable auto-review to review your pull requests automatically.

Devin Review (Staging)


Devin Review

…rt (sfind-ed54b459)

Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…O errors

Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…entries before writing

Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…er-entry

Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…zip 0.6 (sfind-43966ddb)

Refs sfind-43966ddb
@devin-ai-integration

Copy link
Copy Markdown
Author

I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".

  • Disable automatic comment, CI, and merge conflict monitoring

@socket-security

socket-security Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updatedadm-zip@​0.4.7 ⏵ 0.6.1100 +1100 +5098 +885100

View full report

devin-ai-integration[bot]

This comment was marked as resolved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants