Trivy
Trivy = open-source vulnerability + misconfig scanner — ตรวจ Terraform + container + Kubernetes ด้วย tool เดียว
ทำไม Trivy?
- 🔍 ตรวจ Terraform misconfig (รวม CloudFormation, K8s, Docker)
- 🐛 ตรวจ vulnerabilities ใน container images
- 🔑 ตรวจ secrets ที่หลุดใน code
- 🎯 All-in-one — ไม่ต้องติดตั้งหลาย tool
- ✅ Free + open-source
Install
# macOS
brew install trivy
# Linux
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin
# Docker
docker run --rm -v $(pwd):/path aquasec/trivy config /path
Verify:
trivy --version
Scan Terraform Config
trivy config .
หรือเฉพาะ Terraform:
trivy config --terraform-vars-files terraform.tfvars .
Output:
main.tf (terraform)
==================
Tests: 12 (SUCCESSES: 8, FAILURES: 4, EXCEPTIONS: 0)
Failures: 4 (HIGH: 2, CRITICAL: 1)
HIGH: S3 Bucket does not have logging enabled
═════════════════════════════════════════════
S3 access logging helps with security monitoring.
main.tf:8
──────────────
resource "aws_s3_bucket" "data" {
bucket = "my-data"
}
CRITICAL: S3 Bucket has acl set to public-read
═══════════════════════════════════════════════
ตัวอย่าง: Scan Result
Issue 1: Unencrypted S3
resource "aws_s3_bucket" "data" {
bucket = "my-data"
# ไม่มี server_side_encryption_configuration
}
Trivy:
HIGH: AVD-AWS-0017
S3 Bucket does not have encryption configured
แก้:
resource "aws_s3_bucket" "data" {
bucket = "my-data"
}
resource "aws_s3_bucket_server_side_encryption_configuration" "data" {
bucket = aws_s3_bucket.data.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
Issue 2: Open Security Group
resource "aws_security_group_rule" "ssh" {
type = "ingress"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"] # ❌ open SSH to world
}
Trivy:
CRITICAL: AVD-AWS-0107
SSH should not be exposed to the internet
แก้:
cidr_blocks = ["10.0.0.0/8"] # ✅ internal only
Severity Levels
trivy config . --severity HIGH,CRITICAL
Levels:
UNKNOWNLOWMEDIUMHIGHCRITICAL
Output Formats
# Table (default)
trivy config .
# JSON
trivy config . --format json --output report.json
# SARIF (GitHub Code Scanning)
trivy config . --format sarif --output trivy.sarif
# Compact
trivy config . --format table --quiet
Skip Specific Checks
Inline annotation
# trivy:ignore:AVD-AWS-0017
resource "aws_s3_bucket" "test" {
bucket = "test-no-encryption-needed"
}
Config file
.trivyignore
AVD-AWS-0017
AVD-AWS-0040
Scan Container Images Used in TF
resource "aws_ecs_task_definition" "app" {
container_definitions = jsonencode([{
image = "myapp:1.2.3"
}])
}
# Scan image
trivy image myapp:1.2.3
# จะแสดง vulnerabilities + misconfigs
Scan Secrets
trivy fs --scanners secret .
จับ:
- AWS keys (
AKIA...) - GitHub tokens (
ghp_...,ghs_...) - Slack webhooks
- ฯลฯ
CI/CD Integration
GitHub Actions
.github/workflows/trivy.yml
on: pull_request
jobs:
trivy:
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write # for SARIF upload
steps:
- uses: actions/checkout@v4
- name: Trivy Scan
uses: aquasecurity/trivy-action@master
with:
scan-type: config
format: sarif
output: trivy.sarif
severity: HIGH,CRITICAL
- name: Upload SARIF
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: trivy.sarif
→ Issues ปรากฏใน Security tab ของ GitHub
GitLab CI
.gitlab-ci.yml
trivy:
image: aquasec/trivy:latest
script:
- trivy config --severity HIGH,CRITICAL .
Pre-commit
.pre-commit-config.yaml
- repo: https://github.com/aquasecurity/trivy
rev: v0.55.0
hooks:
- id: trivy
args: [config, --severity, HIGH,CRITICAL]
Trivy + Terraform Plan
Scan plan output (more accurate):
# 1. Generate plan
terraform plan -out=tfplan
terraform show -json tfplan > plan.json
# 2. Scan plan
trivy config plan.json
→ Trivy เห็นค่า variable + computed values ที่จริงๆ จะ apply
Compare with Other Scanners
Trivy vs Checkov
| Feature | Trivy | Checkov |
|---|---|---|
| Speed | ⚡⚡ Faster | ⚡ Slower |
| Languages | TF, K8s, Docker, ... | TF, K8s, CloudFormation, ARM, ... |
| Coverage | Good | Excellent (more checks) |
| Plan support | ✅ | ✅ |
| Custom policies | ✅ Rego | ✅ Python |
| Maintained by | Aqua | Bridgecrew/Prisma |
→ ใช้ทั้งคู่ได้ — overlap แต่ครอบคลุมมากขึ้น
Trivy vs tfsec
ก่อนหน้านี้ tfsec เป็น Terraform-specific scanner Trivy ตอนนี้รวม tfsec ใน — เป็น replacement
Custom Policies (Rego)
policies/no-public-s3.rego
package builtin.terraform.s3
import data.lib.terraform
deny[res] {
resource := input.resource_changes[_]
resource.type == "aws_s3_bucket"
resource.change.after.acl == "public-read"
res := {
"msg": sprintf("S3 bucket %v is public", [resource.address]),
"id": "CUSTOM-001",
"severity": "HIGH",
}
}
trivy config --policy ./policies .
Cache + Updates
# Update vulnerability database
trivy --update-cache
# Skip update (use cache)
trivy config --skip-update .
Best Practices
✅ DO:
- Run Trivy ใน PR + main branch
- Use SARIF + GitHub Code Scanning
- Severity HIGH,CRITICAL อย่าง strict
- Ignore false positives ผ่าน .trivyignore
- Combine with Checkov for max coverage
❌ DON'T:
- ห้าม ignore เพราะอ่านยาก
- ห้าม skip update database
- ห้ามคิดว่า scanner = security
- ห้าม disable scan ใน CI
Trivy Operator (Kubernetes)
# Install in K8s
kubectl apply -f https://raw.githubusercontent.com/aquasecurity/trivy-operator/main/deploy/static/trivy-operator.yaml
# Scan running cluster
kubectl get vulnerabilityreports
→ Continuous scanning ของ workloads ใน K8s
ตัวอย่าง Workflow
# 1. Format
terraform fmt -check -recursive
# 2. Validate
terraform validate
# 3. Lint (TFLint)
tflint --recursive
# 4. Security (Trivy)
trivy config --severity HIGH,CRITICAL .
# 5. Compliance (Checkov)
checkov -d . --framework terraform
# 6. Cost (Infracost)
infracost breakdown --path .
# 7. Plan
terraform plan
สรุป
- Trivy = all-in-one scanner (Terraform + container + secret + K8s)
- Open-source + free
- ตรวจ misconfig + vulnerabilities + secrets
- Integration กับ GitHub SARIF, GitLab, pre-commit
- ใช้คู่กับ Checkov ครอบคลุมกว่า
- รวม tfsec เข้าใน Trivy แล้ว
ต่อไป → KICS