
layerleak – o Scanner de Segredos do Docker Hub
Consulte CONTRIBUTING.md para diretrizes de contribuição.
O site publicado é construído a partir de web/ no branch main por .github/workflows/pages.yml. A fonte da documentação e a demonstração simulada do navegador estão ambas sob esse diretório.
Pré-requisitos:
Instale com Go:
go install github.com/brumbelow/layerleak@latest
layerleak --help
O destino de instalação canônico é a raiz do módulo. Para fixar uma versão explicitamente:
go install github.com/brumbelow/[email protected]
Substitua v1.0.0 pela tag v1.x.y publicada desejada.
Certifique-se de que seu diretório GOBIN ou GOPATH/bin esteja no PATH.
O caminho do módulo é github.com/brumbelow/layerleak, então go install @latest resolve para a tag v1.x.y mais alta publicada. Uma versão v2.x.y do módulo exigiria que o caminho do módulo mudasse para github.com/brumbelow/layerleak/v2. Binários instalados via módulo reportam a versão do módulo resolvida através de layerleak --version; compilações a partir de checkout local reportam a versão que o Go incorpora para o checkout, caindo para dev quando nenhuma versão de módulo está disponível.
Compile a partir do código-fonte:
git clone https://github.com/brumbelow/layerleak.git
cd layerleak
go build -o layerleak .
./layerleak --help
Execute a API com uma imagem de contêiner:
docker pull ghcr.io/brumbelow/layerleak:latest
docker run --rm \
-p 8080:8080 \
-e LAYERLEAK_DATABASE_URL='postgres://<user>:<password>@<host>:5432/layerleak?sslmode=disable' \
ghcr.io/brumbelow/layerleak:latest
A imagem do contêiner executa a API por padrão e define LAYERLEAK_API_ADDR=0.0.0.0:8080.
Configuração de ambiente opcional:
cp .env.example .env
Configuração de resultados e banco de dados:
export LAYERLEAK_LOG_LEVEL=info
export LAYERLEAK_FINDINGS_DIR=findings
export LAYERLEAK_API_ADDR=127.0.0.1:8080
export LAYERLEAK_PERSIST_RAW_SECRETS=0
export LAYERLEAK_TAG_PAGE_SIZE=100
export LAYERLEAK_HTTP_TIMEOUT=30s
export LAYERLEAK_MAX_FILE_BYTES=1048576
export LAYERLEAK_MAX_LAYER_BYTES=536870912
export LAYERLEAK_MAX_LAYER_ENTRIES=50000
export LAYERLEAK_MAX_MANIFEST_BYTES=0
export LAYERLEAK_MAX_CONFIG_BYTES=0
export LAYERLEAK_MAX_TAG_RESPONSE_BYTES=8388608
export LAYERLEAK_MAX_REPOSITORY_TAGS=0
export LAYERLEAK_MAX_REPOSITORY_TARGETS=0
export LAYERLEAK_REGISTRY_REQUEST_ATTEMPTS=2
# Sobrescritas opcionais de registro; geralmente deixe não definido.
export LAYERLEAK_REGISTRY_BASE_URL=
export LAYERLEAK_REGISTRY_AUTH_URL=
export LAYERLEAK_DATABASE_URL=postgres://postgres:postgres@localhost:5432/layerleak?sslmode=disable
As mesmas variáveis e seus padrões estão em .env.example, que é a fonte da verdade para valores padrão.
Quando qualquer um dos limites MAX_* é definido como um valor positivo, excedê-lo falha a varredura com um erro claro em vez de truncar o trabalho silenciosamente.
Comportamento dos resultados:
findings e impulsionam o status de saída da varredura não-zero.total_findings.disposition, disposition_reason e line_number para facilitar a triagem e revisão de falsos positivos.1 porque a varredura está incompleta.Layerleak fornece migrações SQL versionadas sob migrations/.
As migrações são manuais intencionalmente. O scanner não cria ou atualiza automaticamente o esquema.
Layerleak requer servidor PostgreSQL >= 16.13 para API com banco de dados e persistência do scanner.
Aplique as migrações com psql em ordem:
psql "$LAYERLEAK_DATABASE_URL" -f migrations/0001_initial.up.sql
psql "$LAYERLEAK_DATABASE_URL" -f migrations/0002_finding_occurrence_metadata.up.sql
psql "$LAYERLEAK_DATABASE_URL" -f migrations/0003_scan_runs.up.sql
Ou aplique migrações usando o comando auxiliar do contêiner:
docker run --rm \
-e LAYERLEAK_DATABASE_URL="$LAYERLEAK_DATABASE_URL" \
ghcr.io/brumbelow/layerleak:latest \
layerleak-migrate-up
layerleak-migrate-up é seguro de reexecutar quando as migrações já estão aplicadas.
Se detectar um estado de migração parcial, sai com código não-zero e solicita intervenção manual.
O auxiliar também impõe a versão do servidor >= 16.13 e valida que o postgresql-client-16 empacotado usa o pacote Ubuntu PGDG 24.04 (.pgdg24.04+) na versão >= 16.13-1.pgdg24.04+1.
Reverta as migrações na ordem inversa:
psql "$LAYERLEAK_DATABASE_URL" -f migrations/0003_scan_runs.down.sql
psql "$LAYERLEAK_DATABASE_URL" -f migrations/0002_finding_occurrence_metadata.down.sql
psql "$LAYERLEAK_DATABASE_URL" -f migrations/0001_initial.down.sql
Padrões operacionais:
first_seen_at e last_seen_at, e também armazena o histórico de varreduras somente anexado em scan_runs.(manifest_digest, fingerprint), e trechos de contexto idênticos repetidos são colapsados antes da persistência.Nota de segurança de segredos:
LAYERLEAK_PERSIST_RAW_SECRETS=1, o Postgres também armazena valores brutos de resultados e trechos brutos.scan_runs.result_json permanece ocultado.Mostre a ajuda da CLI:
layerleak --help
layerleak scan --help

Execute uma varredura contra uma imagem OCI pública em qualquer registro suportado:
./layerleak scan ubuntu
./layerleak scan library/nginx:latest --format json
./layerleak scan alpine:latest --platform linux/amd64
./layerleak scan mongo
./layerleak scan ghcr.io/homebrew/core/hello:latest
./layerleak scan quay.io/prometheus/busybox:latest
./layerleak scan gcr.io/distroless/static:nonroot
./layerleak scan public.ecr.aws/docker/library/alpine:3.20
./layerleak scan mcr.microsoft.com/hello-world:latest

Toda varredura escreve um arquivo JSON de resultados no diretório de saída de resultados.
Se LAYERLEAK_FINDINGS_DIR não estiver definido, o diretório de saída padrão é findings/ sob o diretório pai mais próximo contendo go.mod (tipicamente a raiz do repositório), com fallback para o diretório de trabalho atual quando nenhuma raiz do repositório é encontrada.
Esses arquivos de resultados salvos contêm registros de resultado com redacted_value, context_snippet ocultado, localização exata da fonte, metadados de disposição e número de linha para cada resultado.
Se LAYERLEAK_PERSIST_RAW_SECRETS=1, os arquivos de resultados salvos também incluem value bruto e raw_context_snippet.
Se a persistência Postgres estiver habilitada, findings.value bruto e finding_occurrences.raw_snippet permanecem vazios a menos que LAYERLEAK_PERSIST_RAW_SECRETS=1.
Para imagens multi-arquitetura, o layerleak pula manifestos de atestação e proveniência, como application/vnd.in-toto+json, em vez de contá-los como varreduras de plataforma falhas.
Varreduras de repositório simples:
mongo, enumera todas as tags públicas nesse repositório, resolve cada tag para um digest, agrupa digests duplicados e varre os alvos distintos.mongo:latest ou mongo@sha256:....Sintaxe do comando:
layerleak [command]
layerleak scan <image-ref> [flags]
Flags de escopo para varreduras de repositório (cada uma sobrescreve a variável de ambiente correspondente para um único comando):
Layerleak também fornece uma API JSON mínima sob cmd/api.
A API é baseada em Postgres e requer LAYERLEAK_DATABASE_URL; ela não serve a partir dos arquivos de resultados no disco.
Inicie com:
go run ./cmd/api
Ou execute o contêiner da API:
docker run --rm \
-p 8080:8080 \
-e LAYERLEAK_DATABASE_URL='postgres://<user>:<password>@<host>:5432/layerleak?sslmode=disable' \
ghcr.io/brumbelow/layerleak:latest
Endpoints atuais:
GET /healthPOST /api/v1/scansGET /api/v1/scans/{id}GET /api/v1/repositoriesGET /api/v1/repositories/{repository}/scansGET /api/v1/repositories/{repository}/findingsGET /api/v1/findings/{id}GET /health retorna {"status":"ok"} e não requer um armazenamento ou scanner configurado.
É adequado para verificações de prontidão do Kubernetes e alvos healthcheck do Docker Compose.
POST /api/v1/scans permanece síncrono. Aceita um corpo JSON com reference e platform opcional, e retorna scan_run_id sempre que a persistência Postgres está habilitada.
As respostas da API de varredura reutilizam o mesmo esquema de resultado ocultado que a saída JSON da CLI.
GET /api/v1/scans/{id} retorna os metadados da execução persistida mais o snapshot do resultado ocultado armazenado.
Os endpoints de repositório e resultado também permanecem ocultados: eles retornam redacted_value e context_snippet ocultado, nunca valores brutos de segredos ou trechos brutos do Postgres.
GET /api/v1/repositories/{repository}/scans e GET /api/v1/repositories/{repository}/findings aceitam um parâmetro de consulta registry opcional (por exemplo ?registry=ghcr.io). Quando omitido, o registro assume docker.io para compatibilidade reversa. Use isso para buscar varreduras de repositórios no GHCR, Quay, GCR, MCR, Amazon ECR Public, ou qualquer registro auto-hospedado.
Endpoints de lista (/repositories, /repositories/{repository}/scans, /repositories/{repository}/findings) aceitam ?limit= e ?offset= para paginação. limit assume 50 e tem limite máximo de 200. /repositories/{repository}/findings também aceita ?disposition=actionable|suppressed|all; quando omitido, a resposta inclui apenas resultados acionáveis.
A API não inclui autenticação. Para implantações organizacionais, mantenha-a em uma rede privada e coloque na frente seu próprio gateway de autenticação/autorização ou política de proxy reverso.
Este repositório fornece uma pilha Compose em docker-compose.yml com serviços db, migrate e api.
O serviço db de base está fixado em postgres:16.13-alpine.
Se você usar uma imagem Postgres diferente, mantenha a versão do servidor em 16.13 ou mais nova.
Defina as variáveis de implantação (exporte no shell ou coloque em um arquivo .env ao lado de docker-compose.yml):
export LAYERLEAK_IMAGE=ghcr.io/brumbelow/layerleak:latest
export LAYERLEAK_DB_NAME=layerleak
export LAYERLEAK_DB_USER=layerleak
export LAYERLEAK_DB_PASSWORD=replace-me
export LAYERLEAK_API_PORT=8080
Valide a configuração Compose renderizada antes da implantação:
docker compose config
Execute as migrações uma vez antes de iniciar a API:
docker compose --profile manual run --rm migrate
Inicie o serviço da API:
docker compose up -d api
No Dockge ou Komodo, importe o mesmo arquivo Compose e execute o serviço migrate uma vez antes de habilitar o serviço api de longa duração.
Lançado sob a Licença MIT — veja LICENSE.
Se este repositório economizou seu tempo ou ajudou você, pode apoiar futuras atualizações aqui:
Obrigado :) isso genuinamente ajuda a manter o projeto mantido.
| Variável | Padrão | Propósito |
|---|
LAYERLEAK_LOG_LEVEL | info | Nível de log: debug, info, warn ou error. |
LAYERLEAK_FINDINGS_DIR | não definido | Onde escrever arquivos de resultados JSON. Se não definido, assume findings/ sob o pai mais próximo contendo go.mod, caindo para o diretório de trabalho atual. |
LAYERLEAK_API_ADDR | 127.0.0.1:8080 | Endereço de ligação para o servidor da API. A imagem do contêiner sobrescreve para 0.0.0.0:8080. |
LAYERLEAK_PERSIST_RAW_SECRETS | 0 | Defina como 1 para escrever valores brutos de segredos e trechos brutos de contexto no disco e no Postgres. Os resultados permanecem ocultados por padrão. |
LAYERLEAK_HTTP_TIMEOUT | 30s | Tempo limite por requisição para cada chamada de registro (manifestos, blobs, páginas de tags, tokens de autenticação). Aceita qualquer duração Go (30s, 2m, 1h). |
LAYERLEAK_MAX_FILE_BYTES | 1048576 (1 MiB) | Máximo de bytes descomprimidos armazenados em buffer por arquivo dentro de uma camada. Arquivos maiores que isso são ignorados como muito grandes. Deve ser maior que zero. |
LAYERLEAK_MAX_LAYER_BYTES | 536870912 (512 MiB) | Máximo de bytes do fluxo de camada descomprimido por camada. 0 desabilita o limite. |
LAYERLEAK_MAX_LAYER_ENTRIES | 50000 | Máximo de entradas tar por camada. 0 desabilita o limite. |
LAYERLEAK_MAX_MANIFEST_BYTES | 0 | Máximo de bytes do corpo do manifesto. 0 desabilita o limite. |
LAYERLEAK_MAX_CONFIG_BYTES | 0 | Máximo de bytes do corpo da configuração de imagem. 0 desabilita o limite. |
LAYERLEAK_MAX_TAG_RESPONSE_BYTES | 8388608 (8 MiB) | Máximo de bytes por página de resposta da lista de tags do registro. 0 desabilita o limite. |
LAYERLEAK_TAG_PAGE_SIZE | 100 | Tamanho da página da lista de tags do registro para varreduras em todo o repositório. |
LAYERLEAK_MAX_REPOSITORY_TAGS | 0 | Máximo de tags enumeradas por varredura de repositório. 0 desabilita o limite. |
LAYERLEAK_MAX_REPOSITORY_TARGETS | 0 | Máximo de alvos distintos resolvidos por varredura de repositório. 0 desabilita o limite. |
LAYERLEAK_REGISTRY_REQUEST_ATTEMPTS | 2 | Número de tentativas (incluindo a primeira) para cada requisição de registro. |
LAYERLEAK_REGISTRY_BASE_URL | não definido | Sobrescrita opcional. Normalmente o layerleak deriva isso de cada referência de imagem; defina apenas para forçar varreduras através de um proxy ou endpoint alternativo. |
LAYERLEAK_REGISTRY_AUTH_URL | não definido | Sobrescrita opcional. Normalmente descoberto a partir do desafio WWW-Authenticate do registro. |
LAYERLEAK_DATABASE_URL | não definido | Se definido, o layerleak escreve varreduras no Postgres e falha o comando se a persistência não for bem-sucedida. |
| Flag | Propósito |
|---|
--tag-page-size | Tamanho da página da lista de tags do registro para varreduras de repositório. Deve ser maior que zero. Sobrescreve LAYERLEAK_TAG_PAGE_SIZE. |
--max-repository-tags | Máximo de tags enumeradas por varredura de repositório. 0 desabilita o limite. Sobrescreve LAYERLEAK_MAX_REPOSITORY_TAGS. |
--max-repository-targets | Máximo de alvos distintos resolvidos por varredura de repositório. 0 desabilita o limite. Sobrescreve LAYERLEAK_MAX_REPOSITORY_TARGETS. |