Skip to main content

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:

  • UNKNOWN
  • LOW
  • MEDIUM
  • HIGH
  • CRITICAL

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

FeatureTrivyCheckov
Speed⚡⚡ Faster⚡ Slower
LanguagesTF, K8s, Docker, ...TF, K8s, CloudFormation, ARM, ...
CoverageGoodExcellent (more checks)
Plan support
Custom policies✅ Rego✅ Python
Maintained byAquaBridgecrew/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