ProdutoCLISegurançaDocsPreços
Entrar

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.

~/acme/platform
$ 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.

Tema Um agente de código genérico A CLI do Basalt
contexto O que você abre, o que ele busca no repositório e o que você cola no chat. O seu workspace no Basalt: o grafo de caminhos de ataque, os achados abertos com a evidência de cada um e as correções agrupadas por causa raiz.
IAM da cloud Fica fora da vista, a menos que você passe credenciais ou cole as policies. Achados do scan somente leitura da AWS: roles, relações de trust e permissões avaliadas na conta inteira. Durante a conversa, a CLI não faz nenhuma chamada à AWS.
histórico Parte do código como ele está na sessão. O histórico de scans do workspace: o último scan, o que abriu e o que foi corrigido nos últimos sete dias e a tendência de 12 semanas.
determinismo As conclusões são a leitura que o modelo faz do código, então duas execuções podem divergir. Os caminhos vêm do scanner, não do modelo: árvores sintáticas e avaliação de policies IAM. Mesmo código e mesma configuração, mesmos caminhos. O modelo explica e edita em cima desse resultado.
evidência Pode apontar os arquivos que leu. Todo achado traz arquivo:linha e, para recursos da cloud, o ARN. As respostas citam essas referências.
aprovações Dependem da ferramenta e da sua configuração. Cada edição, branch, commit, push e pull request aparece antes e espera um y. Commit, push e pull request são recusados na branch padrão.
diff do deploy Pode ler 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
Todos os comandos e opções →

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 .basaltignore são ignorados e contados no resumo.
  • Texto para pessoas, JSON para pipelines, na saída padrão ou em arquivo com -o.
terminal
# 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
scan-aws: as únicas chamadas que ele pode fazer
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.

.github/workflows/basalt.yml
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.

[r]

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.

[w]

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.

y/n

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.

!main

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 .git e 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ó git e gh sã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 /status mostra 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.
o que perguntar
› 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
Em breve

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.

terminal
$ curl -fsSL https://basalt.dev/api/v1/cli/install.sh | sh
Abra o zip, clique com o botão direito em Install Basalt.command e escolha Abrir; na primeira vez o macOS pede confirmação. O instalador configura o 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.