
Scanner de malware para imagens de contêiner: sem daemon, com reconhecimento de camadas, ClamAV e YARA
meles é um scanner de malware para imagens de contêiner: um comando sobre uma referência de imagem, sem daemon do Docker, códigos de saída amigáveis para CI. No Kubernetes, ele também verifica cada imagem executada pelos seus pods e, se você quiser, retém novos pods até que a imagem deles seja verificada.
O meles inspeciona o que uma imagem contém antes de ela ser executada. Ele complementa scanners de vulnerabilidade e detecção em tempo de execução, como o Falco; não substitui nenhum dos dois.
O nome vem de Meles meles, o texugo-europeu – ele cava através das camadas.
meles image <ref> faz uma pipeline falhar quando
encontra malware. Saída em tabela, JSON ou SARIF, com
regras de ignorar para falsos positivos.MalwareReport ao lado do workload, com alertas Prometheus opcionais.Experimente na sua máquina (Linux amd64, Docker, bash):
curl -fsSL https://github.com/movray/meles/releases/download/v0.3.3/meles_0.3.3_linux_amd64.tar.gz | tar -xz meles
docker run -d --name clamd -p 127.0.0.1:3310:3310 clamav/clamav:1.4
export MELES_CLAMD=tcp://127.0.0.1:3310
until (exec 3<>/dev/tcp/127.0.0.1/3310 && printf 'zPING\0' >&3 && head -c4 <&3 | grep -q PONG) 2>/dev/null; do sleep 5; done
./meles selftest
./meles image alpine:3.20
Ou em um cluster (administrador do cluster, uma StorageClass padrão, cerca de 2 GB de memória livre em um nó):
kubectl create namespace meles
kubectl label namespace meles pod-security.kubernetes.io/enforce=baseline
helm install meles oci://ghcr.io/movray/charts/meles --version 0.3.3 -n meles --set operator.enabled=true
kubectl -n meles rollout status deploy/meles-clamd --timeout=15m
kubectl get malwarereports -A # every image running in your cluster
kubectl -n meles port-forward svc/meles-server 8080:80 # http://localhost:8080/
O operador agora baixa e escaneia a imagem de cada pod, o que conta
contra os limites de pull dos seus registries; ele apenas reporta e não toca
nos seus pods. Os relatórios aparecem em minutos. Um binário muito grande pode terminar como
Incomplete, o que nunca é limpo: veja
Lendo os resultados.
O port-forward é apenas a forma mais rápida de dar uma olhada. Para uso permanente,
exponha a UI com server.ingress ou server.httpRoute e coloque um login na
frente dela com server.oauth2Proxy, tudo nos values do chart:
Login para a UI web. O meles não tem login próprio,
então não exponha a UI sem um.
Um tour passo a passo, de um arquivo oculto por uma camada posterior até o scan gate no Kubernetes: docs/getting-started.md.
clamd do ClamAV através do seu protocolo de socket. O meles não
linka contra a libclamav e permanece licenciado sob Apache-2.0.Por padrão o meles apenas reporta, e nunca deleta nada. Ele não é substituto para assinatura de imagens, SBOMs ou detecção em runtime.
Cada release vem com binários para Linux e macOS (amd64, arm64), uma imagem multi-arch e o chart Helm:
VERSION=0.3.3
# Binary
curl -fsSLO https://github.com/movray/meles/releases/download/v$VERSION/meles_${VERSION}_linux_amd64.tar.gz
tar -xzf meles_${VERSION}_linux_amd64.tar.gz meles
# Image (linux/amd64, linux/arm64; no shell, runs as non-root)
docker run --rm ghcr.io/movray/meles:$VERSION version
# Helm chart (see Kubernetes below)
helm install meles oci://ghcr.io/movray/charts/meles --version $VERSION -n meles -f my-values.yaml
# From source
go install github.com/movray/meles/cmd/meles@v$VERSION
Binários, imagem e gráfico são construídos pelo fluxo de trabalho de release e carregam proveniência de build assinada. A imagem é escaneada com meles e Trivy antes de ser publicada. Verifique a proveniência com o GitHub CLI:
gh attestation verify meles_${VERSION}_linux_amd64.tar.gz -R movray/meles
gh attestation verify oci://ghcr.io/movray/meles:$VERSION -R movray/meles
gh attestation verify oci://ghcr.io/movray/charts/meles:$VERSION -R movray/meles
A imagem e o gráfico também são assinados com cosign (keyless), para que políticas de admissão como Kyverno ou o Sigstore policy-controller possam verificá-los. As assinaturas são bundles Sigstore armazenados como referrers OCI: verifique com cosign 3 (o cosign 2 requer --new-bundle-format):