A CLI do Basalt.
Escaneie um repositório ou uma conta AWS pelo terminal, verifique cada branch antes do deploy e pergunte ao assistente o que mudou. Ele responde a partir do seu workspace no Basalt e corrige um caminho em uma branch nova, uma mudança aprovada por vez.
$ basalt › quais problemas de segurança apareceram depois do último deploy? ● List .github/workflows/*.yml ⎿ 3 files ● Read .github/workflows/deploy.yml ⎿ 38 lines O deploy roda a cada push em production (.github/workflows/deploy.yml:4), então vou comparar a main com origin/production. ● Pre-deploy check ⎿ block · 2 new · 1 closed vs origin/production ● Overview ⎿ 2 critical, 1 high, 1 medium ● Findings ⎿ 4 findings ● Finding 3f9c1e52-8a4d-4b1e-9c07-2d5e6f1a9b30 ⎿ critical · SupportBot can be prompted to read customer-exports through read_file ● Read support_bot/tools.py ⎿ 31 lines ● Read .cursor/mcp.json ⎿ 24 lines Desde o último deploy (origin/production, merge-base 9c41e07), a main abre 2 caminhos de ataque e fecha 1. Novos 1. CRITICAL SupportBot can be prompted to read customer-exports through read_file support_bot/tools.py:8 dá ao SupportBot uma ferramenta read_file sem limite de caminho. O agente roda com a role support-bot, cuja policy permite s3:GetObject em "*" (infra/iam.tf:22). O último scan da AWS mostra a mesma permissão em arn:aws:iam::412904118823:role/support-bot, então o caminho vale na conta, não só no Terraform. 2. HIGH GITHUB_PERSONAL_ACCESS_TOKEN is stored in plain text .cursor/mcp.json:20, passado ao servidor MCP github. Ele já está no histórico do git, então precisa ser rotacionado, não só removido. Fechado • INTERNAL_API_TOKEN is stored in plain text: o support-api agora lê o token do Secrets Manager. Não veio deste deploy: a ci-deploy confia em "AWS": "*" (infra/iam/ci.tf:7). Esse caminho já estava aberto em production. O caminho do SupportBot fecha com duas edições: limitar a policy a tickets/* e restringir o read_file a um diretório. Quer que eu faça isso em uma branch nova? › sim, começa pelo SupportBot ● Branch basalt/fix-support-bot-s3 Create branchgit switch -c basalt/fix-support-bot-s3 (from main) [y] yes [a] yes, and don't ask again this session [n] no Proceed?
Sessão de exemplo em um repositório de demonstração. A CLI é em inglês; o assistente responde no idioma da pergunta. Os rótulos das ferramentas, as linhas de resultado e o pedido de aprovação seguem a saída real da CLI; as cores foram adaptadas a esta página.
Por que não um agente de código genérico?
Use os dois. Um agente genérico como o Claude Code ou o Cursor foi feito para escrever código em todo o repositório. A CLI do Basalt parte do contexto de segurança da plataforma inteira e mantém as mudanças dentro de limites que a própria CLI impõe.
arquivo:linha e, para recursos da cloud, o ARN. As respostas citam essas referências.
y. Commit, push e pull request são recusados na branch padrão.
git diff; quais caminhos de ataque ele abre fica a cargo do modelo.
basalt check --base <ref> compara a branch com a ref que está em produção e lista os caminhos que ela abre, fecha e deixa abertos.
Funciona ao lado do agente que você já usa
O scan e a verificação pré-deploy também geram JSON (--format json), então o resultado pode ser entregue a qualquer agente ou job de CI. A análise é a mesma nos dois casos.
Comandos
basalt- abre o assistente
basalt login- vincula este terminal ao workspace
basalt scan .- escaneia um repositório localmente
basalt check --base REF- caminhos que uma branch abre ou fecha
basalt scan-aws- escaneia uma conta AWS, somente leitura
Scan local. Nada sai da máquina.
basalt scan e basalt check não fazem chamadas de rede nem enviam nada, com ou sem o terminal vinculado a uma conta.
- O código é lido como árvore sintática. Nunca é importado nem executado.
- Python, TypeScript e JavaScript, Java, Rust e C++, além de Terraform e configs de MCP.
- Secrets em texto puro aparecem por nome e local. O valor não vai para a saída.
- Caminhos listados no
.basaltignoresão ignorados e contados no resumo. - Texto para pessoas, JSON para pipelines, na saída padrão ou em arquivo com
-o.
# achados, correções e inventário em texto $ basalt scan . # o grafo completo e a análise em JSON $ basalt scan . --format json -o basalt.json
sts AssumeRole GetCallerIdentity iam GetAccountAuthorizationDetails GetPolicy GetPolicyVersion s3 ListBuckets GetBucketPolicy GetBucketTagging GetPublicAccessBlock lambda ListFunctions GetFunctionUrlConfig ecs ListTaskDefinitionFamilies DescribeTaskDefinition ec2 DescribeInstances dynamodb ListTables secretsmanager ListSecrets # qualquer outra, inclusive s3:GetObject e secretsmanager:GetSecretValue, # é recusada antes de a requisição sair. A saída JSON lista cada chamada feita.
Verificação pré-deploy no CI
basalt check escaneia a árvore de trabalho e o merge-base com a branch base e mostra só o que esta branch muda. Caminhos que já estavam abertos na base aparecem na lista, mas não quebram o build.
0Passou, ou passou com aviso: caminhos novos de severidade menor, mudanças sem commit ou sem push, branch atrás da base.1A branch abre um caminho de severidade igual ou maior que --fail-on.2Não foi possível rodar, por exemplo fora de um repositório git ou quando a ref base não existe.Pipelines não fazem login pelo navegador: crie um token de CI na página CLI do app (aparece uma vez, com nome, revogável) e salve como o secret BASALT_TOKEN. Ele só libera basalt scan e basalt check; não lê seus achados nem usa o assistente.
A árvore da base é exportada com git archive e apenas lida. Nada no repositório sofre checkout, é alterado ou executado.
name: basalt on: pull_request jobs: check: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 # o check precisa do merge-base - name: Install the Basalt CLI run: | curl -fsSL https://basalt.dev/api/v1/cli/install.sh | sh echo "$HOME/.local/bin" >> "$GITHUB_PATH" - run: basalt check --base origin/${{ github.base_ref }} --fail-on high env: BASALT_TOKEN: ${{ secrets.BASALT_TOKEN }} # token de CI, criado na página CLI do app
O assistente
Rode basalt dentro de um repositório e pergunte em linguagem natural. Ele responde com base nos seus achados e no seu código, e não muda nada até você dizer sim.
O que ele lê
Do seu workspace: achados com evidência, correções, campanhas de red team e verificações do bug watch. Do repositório: arquivos, busca no código, git status e diff, um scan local e a verificação pré-deploy.
O que ele pode mudar
Editar arquivos, criar uma branch, fazer commit, push, abrir um pull request com a GitHub CLI e marcar um achado como aberto, aceito ou corrigido. Nada além disso: ele não tem shell e nunca executa o código do seu projeto.
Toda mudança aparece antes
Antes de cada mudança você vê o diff, o nome da branch, o commit com as estatísticas dos arquivos, o destino do push ou o texto do pull request, e responde y ou n. Qualquer coisa diferente de um sim explícito é um não. Edições e branches novas podem ficar liberadas pelo resto da sessão; commit, push e pull request perguntam toda vez.
Nunca na branch padrão
Ele se recusa a fazer commit, push ou abrir pull request a partir da branch padrão, então toda correção começa em uma branch nova que você aprovou. Nunca faz force-push, merge ou deploy.
Limites garantidos pela CLI, não pelo prompt
- O acesso a arquivos fica dentro do repositório. O diretório
.gite arquivos de secrets, como.env, chaves e state do Terraform, nunca são lidos nem escritos. - Valores com cara de secret são mascarados antes de qualquer coisa sair da sua máquina, inclusive nos diffs que você aprova.
- Só
giteghsão chamados, com argumentos fixos. Sem shell, sem force-push.
Do que ele precisa
- Uma conta vinculada:
basalt login. - Um orçamento mensal do assistente, definido pelo seu plano. Ele renova no dia 1º, e o
/statusmostra quanto já foi usado. - Git para branches e commits, e a GitHub CLI (
gh) para abrir pull requests. - O modelo roda pela API do Basalt. Cada turno envia a conversa e o que o assistente leu, já mascarado; as conversas não ficam armazenadas.
› esta branch pode ir para produção? › por que o caminho do SupportBot é crítico? › corrija a policy S3 com curinga em infra/iam.tf › abra um PR com as correções do último red team
Correções como issues no Linear
Se o seu time prefere corrigir pelo próprio backlog, um botão vai criar issues no Linear a partir das correções, com o escopo já escrito. Ainda não está disponível.
Instalação
Um comando no macOS, Linux ou Windows, ou baixe o instalador. Depois rode basalt login: a CLI funciona com qualquer conta Basalt, e o plano gratuito basta.
$ curl -fsSL https://basalt.dev/api/v1/cli/install.sh | sh
powershell -ExecutionPolicy ByPass -c "irm https://basalt.dev/api/v1/cli/install.ps1 | iex"
uv, um gerenciador isolado de ferramentas Python, se você ainda não tiver.Perguntas
Meu código sai da minha máquina?
Não com scan ou check: os dois rodam localmente e não enviam nada. O scan-aws fala só com a AWS, usando as chamadas somente leitura listadas acima.
O assistente é diferente: para responder, ele envia a conversa e os trechos de arquivos que leu para a API do Basalt, com valores com cara de secret mascarados. As conversas não ficam armazenadas.
O assistente pode dar push na main?
Não. Commit, push e pull request são recusados na branch padrão, e force-push nunca é usado. Cada commit, push e pull request precisa do seu próprio sim.
Preciso de uma conta?
Só para o assistente e para os comandos que leem o seu workspace, como /findings e /fixes. Escanear um repositório, a verificação pré-deploy e o scan de uma conta AWS funcionam sem login.
Do que ele precisa para abrir um pull request?
Do seu remoto git e das suas credenciais para o push, e da GitHub CLI (gh) instalada e autenticada. Sem o gh, a etapa do pull request para com um aviso, e você pode abrir o pull request pelo navegador.
Rode no seu próprio repositório.
Instale com um comando e entre com uma conta gratuita.