Trivy: Kompleksowy skaner bezpieczeństwa dla twojego pipeline'u CI/CD
Jeśli budujesz obrazy Docker i wdrażasz je na produkcję, musisz wiedzieć, jakie podatności się w nich kryją. Trivy to darmowy, open-source'owy skaner bezpieczeństwa od Aqua Security, który stał się de facto standardem skanowania bezpieczeństwa kontenerów.
Co właściwie robi Trivy
Trivy skanuje wiele celów w poszukiwaniu problemów bezpieczeństwa:
- Obrazy kontenerów – znajduje CVE w twoich obrazach Docker
- Systemy plików – skanuje twoją lokalną bazę kodu
- Repozytoria Git – audytuje zdalne repozytoria bezpośrednio
- Klastry Kubernetes – sprawdza całe twoje wdrożenie K8s
- Pliki IaC – wykrywa błędy konfiguracji w Terraform, CloudFormation, itp.
Poza podatnościami, Trivy wykrywa również ujawnione sekrety (klucze API, hasła), ryzyka licencyjne i generuje SBOM (Software Bill of Materials).
Szybki start
Zainstaluj Trivy i zeskanuj obraz w kilka sekund:
# Instalacja na Ubuntu/Debian
sudo apt-get install trivy
# Lub przez skrypt instalacyjny
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin
# Skanowanie obrazu Docker
trivy image nginx:latest
Output pokazuje podatności pogrupowane według ważności (CRITICAL, HIGH, MEDIUM, LOW) z identyfikatorami CVE i rekomendacjami naprawy.
Integracja z GitHub Actions
Oto minimalny workflow, który skanuje twój obraz Docker przy każdym push:
name: Security Scan
on:
push:
branches: [main]
pull_request:
jobs:
trivy-scan:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Build image
run: docker build -t myapp:${{ github.sha }} .
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
with:
image-ref: 'myapp:${{ github.sha }}'
severity: 'CRITICAL,HIGH'
exit-code: '1'
Ustawienie exit-code: '1' powoduje niepowodzenie pipeline'u, gdy zostaną znalezione krytyczne lub wysokie podatności – dokładnie to, czego chcesz dla bramki bezpieczeństwa.
Skanowanie twojej bazy kodu
Możesz również skanować swoje repozytorium w poszukiwaniu podatności w zależnościach:
# Skanowanie bieżącego katalogu
trivy filesystem .
# Skanowanie z określonymi skanerami
trivy filesystem --scanners vuln,secret,misconfig .
To wyłapuje podatne pakiety npm, zależności Pythona, ujawnione pliki .env i źle skonfigurowane Dockerfile przed ich dotarciem na produkcję.
Przetestuj sam: Wykrywanie sekretów w akcji
Przed zaufaniem jakiemukolwiek narzędziu bezpieczeństwa w produkcji, powinieneś zweryfikować, że faktycznie działa. Prostym sposobem na przetestowanie wykrywania sekretów przez Trivy jest dodanie pliku z fałszywymi sekretami do repozytorium i uruchomienie skanu.
Utwórz plik o nazwie test-secrets.js w swoim repo:
// This file contains secrets that should be detected
const config = {
// NPM token - should trigger detection
npmToken: 'npm_ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890',
// OpenAI API key - should trigger detection
openaiApiKey: 'sk-ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789012345678901234',
// GitHub token - should trigger detection
githubToken: 'ghp_ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890',
// AWS access key - should trigger detection
awsAccessKey: 'AKIA1234567890ABCD',
// Stripe API key - should trigger detection
stripeKey: 'sk_live_ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890',
// Google API key - should trigger detection
googleApiKey: 'AIzaSyABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'
};
// Environment variables - should trigger detection
process.env.API_KEY = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890';
process.env.SECRET_KEY = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890';
// JWT secret - should trigger detection
const jwtSecret = 'JWT_SECRET=ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789012345678901234567890';
// OAuth token - should trigger detection
const oauthToken = 'oauth_token:ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789012345678901234567890';
Teraz uruchom Trivy z włączonym skanowaniem sekretów i niestandardową konfiguracją:
trivy fs --scanners secret --secret-config trivy-secret.yaml .
Otrzymasz szczegółowy raport pokazujący dokładnie, co zostało znalezione:
Report Summary
┌───────────┬──────┬─────────┐
│ Target │ Type │ Secrets │
├───────────┼──────┼─────────┤
│ config.js │ text │ 11 │
└───────────┴──────┴─────────┘
config.js (secrets)
Total: 11 (HIGH: 0, CRITICAL: 11)
CRITICAL: GitHub (github-pat)
══════════════════════════════════════════════════════════════════════════════
GitHub Personal Access Token
──────────────────────────────────────────────────────────────────────────────
config.js:10 (offset: 358 bytes)
──────────────────────────────────────────────────────────────────────────────
8
9 // GitHub token - should trigger detection
10 [ githubToken: '****************************************',
11
──────────────────────────────────────────────────────────────────────────────
CRITICAL: general (openai-api-key)
══════════════════════════════════════════════════════════════════════════════
OpenAI API Key
──────────────────────────────────────────────────────────────────────────────
config.js:7 (offset: 238 bytes)
──────────────────────────────────────────────────────────────────────────────
5
6 // OpenAI API key - should trigger detection
7 [ openaiApiKey: '**************************************************34',
8
──────────────────────────────────────────────────────────────────────────────
CRITICAL: general (stripe-api-key)
══════════════════════════════════════════════════════════════════════════════
Stripe API Key
──────────────────────────────────────────────────────────────────────────────
config.js:16 (offset: 553 bytes)
──────────────────────────────────────────────────────────────────────────────
14
15 // Stripe API key - should trigger detection
16 [ stripeKey: '********************************************',
17
──────────────────────────────────────────────────────────────────────────────
... i 8 więcej znalezisk (tokeny NPM, sekrety JWT, tokeny OAuth, itp.)
Trivy oznacza 11 krytycznych znalezisk – tokeny NPM, GitHub PAT, klucze OpenAI, klucze Stripe, sekrety JWT i więcej. Jeśli twój pipeline CI wyłapie te testowe sekrety, wiesz, że złapie też prawdziwe.
Niestandardowe reguły wykrywania sekretów
Dla większej kontroli nad tym, co Trivy wykrywa, utwórz plik konfiguracyjny trivy-secret.yaml:
# trivy-secret.yaml
# Niestandardowe reguły wykrywania sekretów (specyficzne dla Frontend/Node.js/Angular)
rules:
# Node.js / npm specific
- id: npm-token
category: general
title: NPM Token
severity: CRITICAL
regex: 'npm_[A-Za-z0-9]{36}'
- id: npm-auth-token
category: general
title: NPM Auth Token
severity: CRITICAL
regex: '//registry\.npmjs\.org/:_authToken\s*=\s*[A-Za-z0-9+/=]{40,}'
# API Keys
- id: openai-api-key
category: general
title: OpenAI API Key
severity: CRITICAL
regex: 'sk-[A-Za-z0-9]{48}'
- id: google-api-key
category: general
title: Google API Key
severity: CRITICAL
regex: 'AIza[0-9A-Za-z_-]{35}'
- id: stripe-api-key
category: general
title: Stripe API Key
severity: CRITICAL
regex: 'sk_live_[A-Za-z0-9]{24,}'
- id: stripe-publishable-key
category: general
title: Stripe Publishable Key
severity: HIGH
regex: 'pk_live_[A-Za-z0-9]{24,}'
# OAuth and JWT tokens
- id: oauth-token
category: general
title: OAuth Token
severity: CRITICAL
regex: 'oauth_token\s*[:=]\s*[A-Za-z0-9_-]{32,}'
- id: jwt-secret
category: general
title: JWT Secret
severity: CRITICAL
regex: 'JWT_SECRET\s*[:=]\s*[A-Za-z0-9+/=]{32,}'
# Environment variables with secrets
- id: env-secret
category: general
title: Environment Secret
severity: HIGH
regex: '(API_KEY|SECRET_KEY|PRIVATE_KEY|ACCESS_TOKEN|REFRESH_TOKEN)\s*[:=]\s*[A-Za-z0-9+/=_-]{20,}'
# AWS credentials
- id: aws-access-key
category: general
title: AWS Access Key ID
severity: CRITICAL
regex: 'AKIA[0-9A-Z]{16}'
- id: aws-secret-key
category: general
title: AWS Secret Access Key
severity: CRITICAL
regex: 'aws_secret_access_key\s*[:=]\s*[A-Za-z0-9/+=]{40}'
# GitHub tokens
- id: github-token
category: general
title: GitHub Personal Access Token
severity: CRITICAL
regex: 'ghp_[A-Za-z0-9]{36}'
- id: github-oauth
category: general
title: GitHub OAuth Token
severity: CRITICAL
regex: 'gho_[A-Za-z0-9]{36}'
allow-rules:
# Pozwól na przykładowe/zastępcze wartości
- id: example-values
description: Allow example placeholder values
regex: '(example|placeholder|your-.*-here|xxx+|CHANGE_ME|test|demo)'
# Pozwól na plik .env.example
- id: env-example
description: Allow .env.example file
path: '\.env\.example$'
# Pozwól na pliki testowe
- id: test-files
description: Allow test files
path: '(\.spec\.|\.test\.|/test/|/tests/)'
# Pozwól na pliki dokumentacji
- id: documentation
description: Allow documentation files
path: '(README|\.md|\.txt)$'
Ta konfiguracja definiuje niestandardowe wzorce regex dla popularnych typów sekretów i zawiera allow-rules do redukcji fałszywych pozytywów w plikach testowych, dokumentacji i wartościach zastępczych.
Ważne: Pamiętaj o usunięciu pliku z testowymi sekretami po weryfikacji lub dodaj go do .trivyignore, jeśli chcesz zachować go jako stały element testowy.
Dlaczego Trivy?
Po ocenie kilku skanerów podatności, Trivy wyróżnia się z kilku powodów:
- Zero konfiguracji – działa od razu po instalacji
- Szybki – skany kończą się w sekundach, nie minutach
- Brak zewnętrznych zależności – pojedynczy binarny, nie potrzeba serwera bazy danych
- Szerokie wsparcie ekosystemu – integruje się z Harbor, GitLab, Azure i innymi
- Licencja Apache 2.0 – w pełni open source, bez vendor lock-in
Narzędzie jest aktywnie utrzymywane i zaufane przez firmy takie jak GitLab, MasterCard i Deutsche Bahn.
Podsumowanie
Dodanie Trivy do twojego pipeline'u CI/CD zajmuje 5 minut i daje ci ciągły wgląd w stan twojego bezpieczeństwa. Dla każdego zespołu wdrażającego kontenery jest to niezbędne narzędzie, które powinno być częścią każdego buildu.
Sprawdź oficjalną dokumentację na trivy.dev i repozytorium GitHub na aquasecurity/trivy.




