Receber um projeto pronto de uma IA e executar o primeiro comando de instalação parece um passo administrativo. Na prática, esse comando pode baixar dezenas ou centenas de componentes, iniciar scripts do próprio projeto e de dependências, compilar código nativo, acessar a rede e alterar arquivos locais. Antes de rodar qualquer coisa, vale transformar a instalação em uma decisão verificável.
Este guia mostra uma triagem local para projetos Node.js e Python no Windows. A primeira etapa só lê manifestos, arquivos de trava e configurações. Ela não instala pacotes, não executa o código recebido e não conclui que um projeto é seguro. O objetivo é descobrir o que será executado, de onde as dependências virão e quais pontos precisam de validação humana.
Resultado esperado
Ao final, você terá um registro curto com cinco respostas: qual ecossistema o projeto usa, quais arquivos controlam a instalação, quais scripts podem ser acionados, se as versões estão fixadas e em qual ambiente o primeiro teste será feito. A saída correta pode ser liberado para teste isolado, revisão pendente ou não executar.
“Liberado” não significa confiável para produção. Significa apenas que o escopo foi entendido o suficiente para um teste em ambiente descartável, sem credenciais, dados reais ou acesso desnecessário.
Pré-requisitos
- Uma cópia separada do projeto, fora de pastas com documentos pessoais ou corporativos.
- PowerShell 7 para os exemplos de leitura.
- Permissão legítima para analisar o código e as licenças envolvidas.
- Um ambiente descartável para o primeiro teste, como máquina virtual, contêiner apropriado ou Windows Sandbox.
- Nenhuma chave, token, sessão autenticada ou arquivo
.envdentro do diretório de teste.
Se você ainda não separou o material, use o Guia Antes de liberar uma pasta para um agente de IA. Para código desconhecido no Windows, o artigo Código de IA no Windows Sandbox explica como reduzir o alcance do primeiro teste.
Passo 1: pare antes do comando sugerido
Não comece por npm install, npm ci, pip install, poetry install ou um script de preparação. Também não execute um arquivo chamado setup.ps1, install.cmd ou bootstrap.sh só porque o nome parece previsível. Primeiro leia os arquivos que descrevem o processo.
Uma resposta de IA pode sugerir um comando correto para um projeto legítimo e ainda assim omitir efeitos relevantes. O risco não depende apenas do texto que você vê. Ele inclui scripts transitivos, ferramentas chamadas pelo gerenciador, binários distribuídos e configurações herdadas do computador.
Passo 2: inventarie manifestos e arquivos de trava
$projeto = 'C:\Analise\Projeto-IA'
if (-not (Test-Path -LiteralPath $projeto -PathType Container)) {
throw 'A pasta do projeto não foi encontrada.'
}
$nomesControle = @(
'package.json', 'package-lock.json', 'npm-shrinkwrap.json',
'pnpm-lock.yaml', 'yarn.lock', '.npmrc',
'pyproject.toml', 'requirements.txt', 'requirements-dev.txt',
'poetry.lock', 'Pipfile', 'Pipfile.lock',
'setup.py', 'setup.cfg'
)
Get-ChildItem -LiteralPath $projeto -Force -File -Recurse |
Where-Object { $nomesControle -contains $_.Name } |
Select-Object FullName, Length, LastWriteTime
O resultado esperado é uma lista pequena e explicável. Mais de um arquivo de trava para o mesmo ecossistema, como package-lock.json e yarn.lock, exige confirmação de qual ferramenta é a fonte de verdade. A ausência de arquivo de trava também importa, porque deixa a resolução mais dependente do estado atual dos repositórios.
O GitHub descreve seu grafo de dependências como um resumo construído a partir de manifestos e arquivos de trava. Ele pode mostrar versões, licenças, vulnerabilidades conhecidas e relações transitivas, quando o ecossistema é compatível. Isso complementa a leitura local, mas não substitui a inspeção do código que será executado.
Passo 3: leia o package.json sem executar npm
$arquivo = Join-Path $projeto 'package.json'
if (Test-Path -LiteralPath $arquivo) {
$pacote = Get-Content -LiteralPath $arquivo -Raw |
ConvertFrom-Json -Depth 100
[pscustomobject]@{
Nome = $pacote.name
Versao = $pacote.version
PackageManager = $pacote.packageManager
NodeEsperado = $pacote.engines.node
Dependencias = @($pacote.dependencies.PSObject.Properties).Count
DependenciasDev = @($pacote.devDependencies.PSObject.Properties).Count
}
$pacote.scripts.PSObject.Properties |
Select-Object Name, Value
}
ConvertFrom-Json analisa o texto JSON, mas não executa os comandos encontrados. Revise todos os scripts, especialmente preinstall, install, postinstall, prepare, prestart e poststart. Procure chamadas de PowerShell, cmd, Shell, Python, Node, downloadadores, URLs e mudanças fora da pasta.
A documentação oficial do npm registra que npm ci e npm install podem acionar uma sequência de eventos de ciclo de vida. Ela também informa que um pacote instalado diretamente de um repositório Git pode executar prepare. Portanto, um arquivo de trava não elimina a necessidade de revisar scripts.
Passo 4: procure fontes não convencionais no projeto Node.js
$campos = @('dependencies', 'devDependencies', 'optionalDependencies')
foreach ($campo in $campos) {
$grupo = $pacote.$campo
if ($null -eq $grupo) { continue }
$grupo.PSObject.Properties |
Where-Object {
$_.Value -match '^(git\+|https?://|file:|link:|workspace:)' -or
$_.Value -match '[*xX]'
} |
Select-Object @{n='Grupo';e={$campo}}, Name, Value
}
Uma dependência por URL, Git ou caminho local não é automaticamente ruim. Ela apenas foge do fluxo comum do registro e precisa de uma justificativa. Confirme repositório, referência, mantenedor e conteúdo. Versões com curingas ou intervalos muito amplos tornam o resultado menos previsível quando não há trava válida.
Leia também .npmrc como texto. Pare se houver token incorporado, registro privado inesperado, alteração de proxy, redirecionamento para um domínio desconhecido ou configuração que permita scripts de forma diferente do esperado. Não publique nem cole o conteúdo de arquivos de configuração, porque eles podem conter credenciais.
Passo 5: confira se o arquivo de trava corresponde ao manifesto
O package-lock.json descreve uma árvore resolvida e serve para reproduzir uma instalação com mais consistência. O npm informa que npm ci exige um arquivo de trava existente, falha quando ele não corresponde ao package.json e não reescreve o manifesto nem a trava.
Essas propriedades ajudam na repetibilidade, mas não transformam npm ci em uma análise sem execução. O comando ainda instala o projeto e pode rodar eventos como preinstall, install, postinstall e prepare. Trate a divergência entre manifesto e trava como bloqueio de revisão, não como convite para atualizar a trava no computador principal.
Passo 6: revise projetos Python como texto
$arquivosPython = @(
'pyproject.toml', 'requirements.txt',
'requirements-dev.txt', 'setup.py', 'setup.cfg'
)
foreach ($nome in $arquivosPython) {
$caminho = Join-Path $projeto $nome
if (Test-Path -LiteralPath $caminho) {
"### $nome"
Select-String -LiteralPath $caminho -Pattern @(
'requires-python', 'build-system', 'build-backend',
'^-e\s', 'git\+', 'https?://', '--extra-index-url',
'--index-url', '--trusted-host', '--hash='
) -CaseSensitive:$false
}
}
Esse filtro cria uma fila de revisão. Ele não interpreta TOML, não resolve dependências e não prova ausência de comportamento perigoso. Leia integralmente o pyproject.toml, os arquivos requirements e qualquer setup.py. Dê atenção especial ao backend de build, fontes Git, URLs diretas, índices extras, modo editável e código de instalação legado.
A documentação do pip alerta que distribuições podem executar código arbitrário durante a instalação. Ela recomenda o modo de verificação por hash com --require-hashes e, quando aplicável, apenas binários com --only-binary :all:. O modo de hashes exige versões fixadas e hashes para todas as dependências. Um único hash solto não protege o restante da árvore.
Passo 7: separe o que foi fixado do que ainda será resolvido
Monte uma tabela simples. Para cada grupo, registre o arquivo, o gerenciador esperado, a versão do runtime, a origem das dependências e a evidência de fixação. “Tem requirements.txt” não basta. Verifique se há versões exatas, hashes, URLs diretas, referências de Git e dependências transitivas ainda não representadas.
| Pergunta | Evidência | Decisão |
|---|---|---|
| Qual runtime? | engines, .nvmrc ou requires-python |
Versão disponível no ambiente isolado |
| Qual gerenciador? | packageManager, trava ou documentação |
Uma ferramenta definida |
| O que executa? | Scripts e backend de build | Cada comando explicado |
| De onde baixa? | Registro, índice, URL ou Git | Origem reconhecida |
| O que está fixado? | Trava, versões e hashes | Sem resolução inesperada |
Passo 8: procure comandos com alcance externo
$padroes = @(
'Invoke-WebRequest', 'Invoke-RestMethod', 'curl ', 'wget ',
'Start-Process', 'powershell', 'pwsh', 'cmd /c',
'sudo ', 'chmod ', 'Remove-Item', 'rm -',
'reg add', 'schtasks', 'docker ', 'kubectl '
)
Get-ChildItem -LiteralPath $projeto -File -Recurse |
Where-Object { $_.Extension -in '.json', '.toml', '.ini', '.cfg', '.ps1', '.cmd', '.bat', '.sh', '.py', '.js', '.mjs', '.cjs' } |
Select-String -Pattern $padroes -SimpleMatch |
Select-Object Path, LineNumber, Line
O resultado contém falsos positivos, comentários e exemplos. Analise o contexto de cada linha. A presença de curl pode fazer parte de uma documentação, enquanto um postinstall pode invocar um arquivo aparentemente inofensivo. O filtro só ajuda a localizar pontos que merecem leitura.
Pare diante de comandos ofuscados, texto convertido de Base64 sem explicação, download seguido de execução, persistência no sistema, solicitação de privilégio administrativo ou exclusão ampla. Não peça à própria IA que gerou o projeto para ser a única revisora do resultado.
Passo 9: defina o primeiro teste isolado
Crie uma cópia descartável, sem repositórios vizinhos, chaves SSH, tokens de pacote, credenciais de nuvem ou dados reais. Comece sem acesso à rede quando o objetivo for observar o comportamento local. Se a instalação exigir rede, documente os domínios necessários e faça a etapa em ambiente monitorado, com conta sem privilégios e sem segredos.
No npm, --ignore-scripts pode reduzir a execução automática de scripts, mas não deve ser tratado como certificação do pacote. No Python, baixar artefatos para inspeção não equivale a instalar com segurança. Em ambos os casos, o teste controlado vem depois da leitura e não substitui a revisão da origem.
Registre os arquivos criados, processos iniciados, conexões de rede e código de saída. Se o projeto precisa de acesso administrativo para uma tarefa comum, interrompa e peça uma justificativa técnica específica.
Passo 10: confirme o resultado antes de ampliar o uso
Compare o que ocorreu com o plano. O gerenciador usado foi o previsto? O arquivo de trava permaneceu intacto? Surgiram arquivos fora da pasta? Houve download de origem não registrada? Algum script executou em segundo plano? Uma divergência não é necessariamente ataque, mas torna a análise anterior incompleta.
Só então execute testes do próprio projeto, ainda no ambiente isolado. Não conecte produção, banco real, e-mail, navegador autenticado ou nuvem para “ver se funciona”. Primeiro substitua integrações por dados de teste e confirme que as permissões são mínimas.
Erros comuns
- Confiar no nome do comando:
install,prepareestartpodem chamar qualquer executável disponível. - Olhar somente dependências diretas: componentes transitivos também fazem parte da árvore.
- Atualizar a trava para “corrigir” divergência: isso muda a evidência antes de entender a causa.
- Tratar hash como reputação: o hash identifica bytes, mas não prova que o conteúdo é confiável.
- Usar o computador principal como laboratório: isolamento posterior não desfaz uma execução anterior.
- Inserir credenciais para concluir o teste: uma demonstração funcional não justifica acesso a dados reais.
- Confiar em uma varredura sem contexto: ausência de alertas não significa ausência de comportamento indesejado.
Solução de problemas
O projeto não tem arquivo de trava: não gere um automaticamente no ambiente principal. Registre a ausência, identifique o gerenciador esperado e peça ao mantenedor uma versão reproduzível. Se o teste for necessário, faça a resolução em ambiente descartável e guarde a árvore obtida como evidência.
Manifesto e trava não correspondem: pare antes de instalar. Confirme se houve edição incompleta, troca de ferramenta ou arquivo esquecido. O comportamento documentado do npm ci é falhar nessa condição, não atualizar a trava.
Há dependência por Git sem commit fixo: uma branch ou tag pode mudar. Peça um commit específico e valide o repositório. Registre que a referência original não era imutável.
O script usa variável de ambiente: descubra apenas o nome e a finalidade. Não copie um segredo real para a pasta de teste. Use valor fictício quando possível e confirme se o software falha de forma segura sem a credencial.
O projeto mistura Node.js e Python: trate os dois ecossistemas separadamente. Um package-lock.json não fixa pacotes Python, e um arquivo requirements.txt não explica scripts npm.
Limites deste procedimento
A leitura de manifestos não detecta todo comportamento malicioso, vulnerabilidade, erro de lógica ou risco de licença. Pacotes podem conter binários, código gerado, cargas condicionais e comportamento dependente do ambiente. Serviços de grafo e alertas cobrem apenas ecossistemas e dados reconhecidos, e uma base de vulnerabilidades conhecida não representa todos os riscos.
Para código corporativo, projetos com dados regulados ou ferramentas que pedem privilégios elevados, envolva segurança e o responsável pelo sistema. O método reduz surpresa operacional e melhora a evidência, mas não substitui revisão de código, análise de origem, política de software ou teste especializado.
Checklist antes do primeiro comando
- A cópia de teste está separada de arquivos e credenciais reais?
- Manifestos, travas e configurações foram inventariados?
- O runtime e o gerenciador esperados estão definidos?
- Scripts de instalação, preparação, início e build foram lidos?
- URLs, Git, caminhos locais, índices extras e versões amplas foram explicados?
- Manifesto e trava são compatíveis?
- Dependências Python estão fixadas e, quando aplicável, acompanhadas de hashes?
- O ambiente descartável não contém segredos nem privilégios desnecessários?
- Rede, arquivos criados e processos serão observados?
- Existe uma condição clara para parar o teste?
