Menu da documentação
Primeiros passos
Painel e análises
- Painel em resumo
- Análise de custo
- Desempenho de pipeline
- Insights de otimização
- Knowledge Base
- Conecte seu agente de IA
Runners gerenciados
- Visão geral dos runners
- Execute seu primeiro job
- Migre dos hospedados pelo GitHub
- A página de Runners
- Runners personalizados (AI Scan)
- Autorreparo
- Imagem e software do runner
- Provisionamento e pools a quente
- Limites e concorrência
Cache
Equipe e notificações
Faturamento e planos
Ajuda
Arquitetura de segurança
Como o Latchkey isola cada job de CI: VMs dedicadas de uso único, nenhuma rede de entrada, credenciais efêmeras, criptografia em repouso e em trânsito, e as restrições sob as quais o agente de autorreparo é executado.
Esta página foi escrita para uma revisão de segurança. Ela descreve como a plataforma de runners é realmente construída - a fronteira de isolamento, o que sai da máquina, como as credenciais são tratadas e o que o agente de autorreparo tem e não tem permissão de fazer. Para o que o GitHub App pode ler e escrever nos seus repositórios, veja Segurança e permissões do GitHub.
Isolamento: um job, uma máquina#
O Latchkey não compartilha uma máquina entre jobs. Cada job roda em uma máquina virtual EC2 dedicada (classe m6a, Ubuntu 24.04 LTS) lançada para aquele job. Seu job não é um contêiner compartilhando um kernel com outro inquilino, e não é um processo em um host compartilhado de longa duração.
O uso único é imposto na camada de registro do GitHub, não apenas por convenção. Runners de cold start se registram com uma configuração just-in-time, que o GitHub aceita para exatamente um job. Runners de warm pool se registram com a flag --ephemeral, que faz o mesmo. Nos dois casos, a instância é configurada para terminar no desligamento, então não pode ser reutilizada mesmo que algo dê errado.
| Fronteira | Como ela é imposta |
|---|---|
| Um job por máquina | Configuração just-in-time do GitHub (cold start) ou registro com --ephemeral (warm pool) |
| A máquina não pode ser reutilizada | O comportamento de desligamento iniciado pela instância é definido como terminar, tanto no launch template quanto no caminho de lançamento direto |
| O disco não sobrevive | O volume EBS raiz é criptografado e marcado como delete-on-termination |
| Jobs descontrolados são recolhidos | Um processo de limpeza termina instâncias que passam do limite de 4 horas por job (teto rígido de 8 horas) |
| Runners são vinculados a um único workspace | As instâncias são marcadas com o ID da organização e registradas em um único grupo de runners da organização |
Grupos de runners são criados com visibility: selected e uma lista explícita de repositórios, então um runner registrado para o seu workspace só recebe jobs dos repositórios que você habilitou.
O que roda como root, e por que isso está contido#
Dentro da sua própria VM, seu job tem controle total: o usuário runner tem sudo sem senha e acesso ao Docker. Isso é normal em CI - builds instalam pacotes e executam contêineres - e é seguro justamente porque o raio de alcance é uma única máquina de vida curta, sem rede de entrada, que é destruída ao final do job. Preferimos afirmar isso claramente a insinuar um sandbox que não existe.
Rede#
O que está bloqueado
- Os runners são lançados em subnets privadas e sem endereço IP público
- O security group do runner tem zero regras de entrada - nada na internet consegue abrir uma conexão com um runner
- IMDSv2 é obrigatório, com o limite de hops definido como 1, para que um contêiner em rede bridge não consiga alcançar as credenciais da instância através do host
- O tráfego interno da AWS usa gateway endpoints e interface endpoints da VPC em vez da internet pública
- Um WAF (limitação de taxa, AWS Common Rule Set, Known Bad Inputs) fica na frente das aplicações web
O que o seu build ainda consegue alcançar
- O tráfego de saída é aberto, porque a CI precisa alcançar npm, PyPI, Docker Hub, sua nuvem e seus próprios serviços
- Trate qualquer segredo que você exponha a um job como alcançável por esse job - o mesmo modelo dos runners hospedados pelo GitHub
Credenciais e segredos#
As credenciais de runner são emitidas por job
Uma configuração de runner just-in-time é gerada para um único job e gravada no AWS Systems Manager Parameter Store como um SecureString criptografado, com escopo daquela instalação e daquele job.
O runner a lê uma vez e depois a apaga
Na inicialização, a instância busca o parâmetro e o apaga imediatamente, porque ele contém material de chave. O mesmo padrão vale para os tokens de registro de warm pool, que são mantidos em cache apenas durante sua vida útil de 55 minutos.
O acesso ao GitHub é de curta duração
O GitHub App assina um JWT com sua chave privada e o troca por um installation access token de curta duração a cada operação. Não existe nenhum token do GitHub de longa duração armazenado em um runner.
Os segredos da plataforma ficam fora do alcance dos runners
A chave privada do GitHub App fica no Parameter Store como um SecureString. O segredo que um runner pode ler é deliberadamente mínimo e separado do segredo de configuração da plataforma, de modo que um papel de instância comprometido não consegue ler credenciais da plataforma.
Os deploys se autenticam na AWS por assunção de papel via GitHub OIDC. Não há chaves de acesso AWS de longa duração na CI. As chaves de API da integração MCP são armazenadas apenas como um hash SHA-256 - a chave em texto puro é exibida uma vez na criação e nunca é persistida.
Criptografia#
| Dado | Em repouso | Em trânsito |
|---|---|---|
| Disco raiz do runner | EBS criptografado (gp3), excluído na terminação | n/a |
| Cache de build (S3) | SSE-S3 (AES-256), expiração em 14 dias | TLS |
| Banco de dados da aplicação | Armazenamento criptografado, sem acesso público | TLS |
| Camada de cache / fila | Criptografia em repouso e em trânsito habilitada | TLS |
| Configurações de runner e chaves do app | SecureString do Parameter Store | TLS |
| Tráfego de API | n/a | TLS 1.2 no mínimo no domínio da API |
Isolamento do cache de build#
Os objetos de cache são armazenados no S3 sob um prefixo de chave derivado do ID da sua organização, e o ID do inquilino é injetado pelo control plane a partir da requisição do job - um job não pode se declarar outro inquilino definindo uma variável de ambiente. Os objetos expiram após 14 dias.
O que sai do runner#
Dois tipos de dados saem da máquina, e vale ser preciso sobre o segundo.
- Metadados de execução e de job - nomes, tempos, status, labels e o YAML de workflow - que alimentam os recursos de análise e de otimização.
- Saída do passo que falhou. Quando um passo falha, o pipeline de autorreparo captura a saída padrão e a saída de erro daquele passo (limitadas a 1 MiB cada) e as armazena para que a falha possa ser diagnosticada e, quando pertinente, transformada em uma correção proposta. A retenção é de 90 dias.
Como o agente de autorreparo é restringido#
O autorreparo é a parte em que um revisor deve pressionar mais forte, porque é o único componente que altera um job em execução. Veja exatamente o que ele pode fazer.
- Ele roda como o usuário
runner, não como root, na forma de um serviço systemd. - Ele escuta em um socket de domínio Unix com permissões restritas ao grupo. Não tem listener TCP nem superfície de rede.
- Ele é invocado por um shim que intercepta apenas os scripts de passo do próprio agente do runner; todos os demais comandos passam direto, sem alteração.
- Ele falha aberto: se o agente atinge o tempo limite, recusa ou dá erro, o comando roda exatamente como rodaria sem o Latchkey. Um reparador quebrado não pode quebrar o seu build.
As operações privilegiadas que ele pode executar são definidas por allowlist, não por filtragem:
| Controle | O que significa |
|---|---|
| Allowlist de sudo | Exatamente um padrão ancorado é permitido - um apt-get install não interativo de um único pacote. Qualquer outra coisa começando com sudo é rejeitada antes de o processo ser criado. |
| Allowlist de pacotes | Os pacotes instaláveis vêm de uma lista definida em tempo de compilação, aplicada de forma independente em dois estágios, porque um dos estágios monta comandos a partir de saída de build não confiável. |
| Piso de segurança do ambiente | Definir LD_PRELOAD, LD_LIBRARY_PATH, PATH, BASH_ENV ou ENV é negado, assim como metacaracteres de shell e substituição de comandos. |
| Negação de caminhos sensíveis | Leituras em /etc, /root, /proc, /sys, /var/log, ~/.ssh, ~/.aws e ~/.config/gh são negadas. |
| Sandbox das ferramentas de IA | As ferramentas do estágio 3 rodam dentro de um sandbox baseado em bubblewrap que começa negando tudo por padrão - sem rede, sem caminhos de escrita - e é ampliado por ferramenta até o conjunto mínimo necessário. |
| Nenhuma chave de IA residente | O passo de raciocínio se autentica no AWS Bedrock pelo papel da instância, então não há nenhuma chave de API de modelo de longa duração em uma máquina que executa o seu código. |
| Interruptor de desligamento | O autorreparo pode ser desativado por workspace. |
O que o GitHub App pode acessar#
Cada permissão abaixo existe para viabilizar um recurso específico. Elas estão agrupadas pelo propósito, em vez de uma lista plana, para que você veja o motivo ao lado da concessão.
| Propósito | Acesso | Permissões |
|---|---|---|
| Executar seus jobs em runners do Latchkey | Leitura e escrita | Runners auto-hospedados da organização, administração, administração da organização |
| Ver o que seus pipelines fizeram | Leitura | Actions, metadados de artefatos, metadados |
| Reagir aos jobs conforme eles acontecem | Leitura e escrita | Hooks da organização, hooks de repositório |
| Ler workflows e propor correções como PRs | Leitura e escrita | Workflows, código, pull requests |
| Modelar seus custos do GitHub com precisão | Leitura | Plano da organização |
| Verificar quem está na sua organização | Leitura | Membros |
| Exibir achados de segurança no seu painel | Leitura | Alertas do Dependabot, alertas de secret scanning, eventos de segurança, segredos do Dependabot |
| Construir imagens de runner adequadas à sua stack | Leitura | Imagens personalizadas de runner da organização |
Alterações nos seus repositórios#
O Latchkey nunca faz push na sua branch padrão. Toda alteração é um pull request que você revisa, e o caminho de escrita é restringido de três formas:
- O caminho do arquivo precisa ser resolvido como editável contra um manifesto por repositório. Caminhos sem correspondência são, por padrão, não editáveis - a verificação falha fechada.
- Pull requests originados de forks são rejeitados, e um sinal de fork ausente também é rejeitado, em vez de presumido seguro.
- Uma correção proposta precisa corresponder à sua assinatura de falha nos logs capturados, ou é suprimida.
Segurança operacional#
- As imagens de runner são reconstruídas semanalmente, para que os patches de segurança do sistema operacional cheguem à frota em uma cadência definida.
- O papel de instância do runner é de menor privilégio, incluindo uma negação explícita que restringe o acesso ao Parameter Store em toda a conta, concedido por uma política gerenciada pela AWS, apenas aos caminhos de runner do próprio Latchkey.
- Toda ação administrativa que altera estado é gravada em um log de auditoria com operador, ação, alvo, parâmetros e resultado.
- O acesso ao painel e à API é autenticado por um autorizador JWT no API gateway. Os papéis de workspace são Owner, Admin e Member, com os owners protegidos contra remoção ou rebaixamento.
Retenção de dados#
O que o Latchkey armazena, e por quanto tempo.
| Dado | Retenção |
|---|---|
| Seu código-fonte no runner | Destruído junto com a instância ao final do job |
| Objetos do cache de build | 14 dias a partir da última escrita |
| Saída do passo que falhou, capturada para diagnóstico | 90 dias |
| Registros de tentativas de autorreparo | 90 dias |
| Registros de correções propostas | 365 dias |
| Metadados de execução e de job que alimentam seus painéis | Retidos enquanto o repositório permanecer habilitado |
Desabilitar um repositório interrompe a coleta para ele. Excluir o seu workspace remove os dados dele. Se você precisa de uma janela de retenção específica para a sua organização, peça e conversaremos a respeito.
Reportando uma vulnerabilidade#
Envie um e-mail para security@latchkey.dev. Por favor, não abra uma issue pública no GitHub para um relato de segurança.
Meu código-fonte permanece no runner depois do job?
Não. A instância e seu volume raiz criptografado são destruídos quando o job termina. Nada do que você fez checkout sobrevive, além das entradas de cache de build que você habilitou explicitamente, que expiram após 14 dias.
O job de outro cliente consegue ver o meu?
Não. Cada job roda em sua própria máquina virtual, registrada para um único workspace e destruída após esse único job. Os runners não têm acesso de rede de entrada.
O agente de autorreparo pode executar comandos arbitrários no meu build?
Não. As ações privilegiadas são definidas por allowlist em vez de filtradas: um único padrão de sudo permitido, uma lista fixa de pacotes, negação de variáveis de ambiente que possibilitam injeção de código e um sandbox de negação por padrão para o estágio de ferramentas de IA. Se o agente falhar por qualquer motivo, o seu comando roda exatamente como rodaria sem ele.
Meus segredos de build são visíveis para o Latchkey?
Não. Seus segredos do GitHub Actions são injetados pelo GitHub diretamente no seu job em tempo de execução, exatamente como nos runners hospedados pelo GitHub, e o Latchkey nunca solicita nem armazena seus valores. O GitHub mascara os segredos registrados na saída de log antes que qualquer parte dela chegue até nós.