Xây Dựng Pipeline DevSecOps Trên Linux Với GitHub Actions: Trivy, Semgrep Và Gitleaks

Hướng dẫn chi tiết xây dựng pipeline DevSecOps trên Linux với GitHub Actions, tích hợp Gitleaks v8.28, Semgrep và Trivy v0.69 để tự động quét secrets, SAST, SCA và container security.

Tại Sao Bạn Cần Một Pipeline DevSecOps Trong 2026

Bạn đã gia cố SSH bằng FIDO2, bật SELinux ở chế độ enforcing, thiết lập nftables cẩn thận, triển khai Wazuh để giám sát tập trung — tuyệt vời. Nhưng thật lòng mà nói, vẫn còn một lỗ hổng mà nhiều người bỏ qua: code mà đội ngũ phát triển đẩy lên production mỗi ngày.

Nếu một API key bị hardcode trong source code, một thư viện có CVE nghiêm trọng lọt vào container image, hoặc một đoạn code chứa lỗ hổng SQL injection — thì mọi lớp bảo mật hạ tầng bạn dày công xây dựng đều vô nghĩa. Nghe hơi cực đoan, nhưng đó là sự thật.

Đó chính là lý do DevSecOps — tích hợp bảo mật vào mọi giai đoạn của quy trình phát triển — không còn là "nice-to-have" nữa mà là bắt buộc. Theo báo cáo State of DevSecOps 2026 của Datadog, pipeline CI/CD và GitHub Actions đang trở thành mục tiêu hàng đầu của các cuộc tấn công chuỗi cung ứng. Chi phí trung bình cho một vụ vi phạm pipeline CI/CD đã lên tới 5,1 triệu USD, và số lượng tấn công chuỗi cung ứng tăng 45% so với năm trước. Con số đó không hề nhỏ.

Tin tốt là bạn hoàn toàn có thể xây dựng một pipeline DevSecOps mạnh mẽ với ba công cụ mã nguồn mở miễn phí: Gitleaks cho secrets scanning, Semgrep cho phân tích tĩnh mã nguồn (SAST), và Trivy cho quét container cùng dependencies (SCA). Bài viết này sẽ hướng dẫn bạn từng bước — từ cài đặt trên Linux cho đến tích hợp vào GitHub Actions với security gates tự động.

Kiến Trúc Pipeline DevSecOps: Bốn Lớp Bảo Mật

Trước khi bắt tay vào cấu hình, mình muốn bạn nắm rõ kiến trúc tổng thể trước. Một pipeline DevSecOps hiệu quả cần bao phủ bốn lớp:

  • Lớp 1 — Pre-commit: Chặn secrets và lỗi bảo mật ngay trước khi code được commit. Đây là tuyến phòng thủ đầu tiên, chạy ngay trên máy của developer.
  • Lớp 2 — SAST (Static Application Security Testing): Phân tích tĩnh mã nguồn trên mỗi pull request để phát hiện các pattern nguy hiểm — SQL injection, XSS, command injection — mà không cần chạy ứng dụng.
  • Lớp 3 — SCA (Software Composition Analysis): Quét dependencies và container images để tìm lỗ hổng đã biết (CVE). Hầu hết ứng dụng sử dụng hàng trăm thư viện bên thứ ba, và mỗi thư viện là một vector tấn công tiềm năng.
  • Lớp 4 — Security Gates: Chặn merge hoặc deploy nếu kết quả quét vượt ngưỡng cho phép. Không có security gates thì tất cả các lớp trên chỉ là cảnh báo suông — developer sẽ bỏ qua dần.

Pipeline mà chúng ta sẽ xây dựng gồm: Gitleaks (Lớp 1 + 2), Semgrep (Lớp 2), Trivy (Lớp 3), và policy enforcement (Lớp 4) — tất cả chạy tự động qua GitHub Actions trên máy chủ Linux.

Gitleaks — Phát Hiện Secrets Và Credentials Bị Lộ

Gitleaks là gì và tại sao cần nó

Gitleaks là công cụ quét mã nguồn mở chuyên phát hiện secrets bị hardcode trong repository Git — bao gồm API keys, mật khẩu, private keys, tokens, và mọi thông tin nhạy cảm khác. Với hơn 24.400 sao trên GitHub và 6,8 triệu lượt tải Docker, đây là secret scanner được tin dùng nhất trong cộng đồng bảo mật hiện nay.

Phiên bản mới nhất Gitleaks v8.28.0 (tính đến tháng 3/2026) có khá nhiều cải tiến đáng chú ý:

  • Composite Rules: Kết hợp rule chính với các rule phụ trợ, chỉ báo cáo finding khi tất cả cùng khớp trong một phạm vi cụ thể. Điều này giảm false positives đáng kể — một vấn đề nhức nhối từ các phiên bản trước.
  • Archive Scanning: Tự động giải nén và quét nội dung của file zip, tarball. Secrets ẩn trong archive? Không thoát được.
  • Encoded Secret Detection: Giải mã tự động hex, Base64, URL encoding để tìm secrets bị mã hóa.
  • Đa dạng output: Xuất kết quả dạng JSON, CSV, JUnit, SARIF — tích hợp trực tiếp với GitHub Advanced Security.

Cài đặt Gitleaks trên Linux

# Cách 1: Tải binary trực tiếp (nhanh nhất)
GITLEAKS_VERSION="8.28.0"
wget https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz
tar -xzf gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz
sudo mv gitleaks /usr/local/bin/
gitleaks version

# Cách 2: Cài qua Go (luôn có phiên bản mới nhất)
go install github.com/gitleaks/gitleaks/v8@latest

# Cách 3: Docker
docker pull zricethezav/gitleaks:latest
docker run -v $(pwd):/repo zricethezav/gitleaks:latest detect --source /repo

Quét repository cục bộ

# Quét toàn bộ Git history (phát hiện secrets trong commits cũ)
gitleaks detect --source /path/to/repo --report-format json --report-path gitleaks-report.json

# Quét chỉ thư mục hiện tại (không quét Git history)
gitleaks dir --source /path/to/repo

# Quét commit chưa push (staged changes)
gitleaks protect --staged --source /path/to/repo

Thiết lập pre-commit hook

Đây là bước quan trọng nhất, và cũng là bước mình khuyên bạn nên làm đầu tiên. Lý do đơn giản: chặn secrets trước khi chúng vào Git history. Một khi secret đã được commit, ngay cả khi bạn xóa nó trong commit tiếp theo, nó vẫn tồn tại trong lịch sử Git và hoàn toàn có thể bị trích xuất. Nhiều đội ngũ đã học bài học này theo cách đau đớn nhất.

# Cài đặt pre-commit framework
pip install pre-commit

# Tạo file .pre-commit-config.yaml trong root của repository
cat << 'EOF' > .pre-commit-config.yaml
repos:
  - repo: https://github.com/gitleaks/gitleaks
    rev: v8.28.0
    hooks:
      - id: gitleaks
EOF

# Kích hoạt hook
pre-commit install

# Test thử: tạo file chứa fake secret
echo 'AWS_SECRET_ACCESS_KEY="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"' > test-secret.txt
git add test-secret.txt
git commit -m "test" # Sẽ bị Gitleaks chặn!

Tùy chỉnh rules với .gitleaks.toml

Trong thực tế, bạn sẽ cần allowlist cho test fixtures, ví dụ trong docs, và các pattern nội bộ. Nếu không tùy chỉnh, chuẩn bị tinh thần bị "nhồi" cảnh báo giả — đặc biệt là với các repo có nhiều file test:

# .gitleaks.toml — đặt ở root repository
title = "Custom Gitleaks Config"

# Thêm custom rule cho internal API key
[[rules]]
id = "internal-api-key"
description = "Internal API Key Pattern"
regex = '''internal_key_[a-zA-Z0-9]{32}'''
tags = ["api", "internal"]

# Allowlist: bỏ qua test files và docs
[allowlist]
paths = [
  "test/fixtures/.*",
  "docs/examples/.*",
  ".*_test\\.go$",
  ".*\\.test\\.js$"
]
regexes = [
  "example\\.com",
  "localhost",
  "EXAMPLE",
  "changeme"
]

Semgrep — Phân Tích Tĩnh Mã Nguồn Đa Ngôn Ngữ (SAST)

Semgrep là gì

Semgrep là công cụ phân tích tĩnh mã nguồn mở, hỗ trợ hơn 30 ngôn ngữ lập trình. Khác với các công cụ SAST truyền thống (thường chậm và cho ra cả đống false positives), Semgrep sử dụng cú pháp pattern matching gần giống code thật. Cá nhân mình thấy đây là một trong những điểm khiến Semgrep nổi bật — developer nhìn vào rule là hiểu ngay, không cần đọc tài liệu dài dòng.

Bản cập nhật tháng 2/2026 mang đến nhiều cải tiến khá thú vị:

  • Tích hợp Claude Code và Cursor: Hooks tự động kéo custom rules từ Semgrep Registry khi sử dụng AI coding tools — rất hữu ích nếu đội bạn đang dùng AI để viết code.
  • Cải thiện Taint Tracking: Giảm false positives bằng cách theo dõi luồng dữ liệu chính xác hơn qua các phép gán.
  • Malicious Dependency Detection (GA): Phát hiện dependency độc hại với hơn 80.000 SCA rules — đã chính thức stable.
  • CLI Memory Policy: Flag --x-mem-policy mới cho phép tối ưu bộ nhớ khi quét dự án lớn (rất cần thiết nếu repo của bạn có hàng nghìn files).

Cài đặt Semgrep trên Linux

# Cách 1: pip (khuyến nghị)
pip install semgrep
semgrep --version

# Cách 2: Docker
docker pull semgrep/semgrep:latest
docker run --rm -v $(pwd):/src semgrep/semgrep semgrep scan --config auto /src

# Cách 3: Homebrew (nếu dùng Linuxbrew)
brew install semgrep

Chạy quét SAST cục bộ

# Quét với bộ rules bảo mật tổng hợp (auto = tự chọn rules phù hợp)
semgrep scan --config auto .

# Quét cụ thể với bộ rules OWASP Top 10
semgrep scan --config p/owasp-top-ten .

# Quét security audit + secrets
semgrep scan --config p/security-audit --config p/secrets .

# Chỉ báo cáo mức ERROR (nghiêm trọng)
semgrep scan --config p/security-audit --severity ERROR --json --output semgrep-report.json .

# Quét riêng cho Python
semgrep scan --config p/python --config p/bandit .

Viết custom rule cho Semgrep

Điểm mạnh lớn nhất của Semgrep, theo mình, là khả năng viết custom rules bằng cú pháp gần giống code thật. Ví dụ dưới đây phát hiện việc sử dụng subprocess.call với shell=True trong Python — một vector command injection phổ biến mà mình đã thấy khá nhiều lần trong các code review:

# custom-rules/no-shell-true.yaml
rules:
  - id: dangerous-subprocess-shell
    patterns:
      - pattern: subprocess.call(..., shell=True, ...)
    message: |
      Sử dụng subprocess với shell=True có thể dẫn đến
      command injection. Hãy dùng shell=False và truyền
      arguments dạng list thay vì string.
    languages: [python]
    severity: ERROR
    metadata:
      cwe:
        - "CWE-78: OS Command Injection"
      owasp:
        - A03:2021 Injection
      references:
        - https://docs.python.org/3/library/subprocess.html

  - id: hardcoded-database-password
    pattern: |
      $DB_PASSWORD = "..."
    message: |
      Phát hiện mật khẩu database được hardcode. Hãy sử dụng
      biến môi trường hoặc secrets manager như HashiCorp Vault.
    languages: [python, javascript, typescript]
    severity: WARNING
# Chạy với custom rules
semgrep scan --config custom-rules/ .

Trivy — Quét Lỗ Hổng Container, Dependencies Và IaC

Trivy là gì

Nếu phải chọn một scanner "tất-cả-trong-một" thì Trivy là lựa chọn khó bỏ qua. Đây là scanner bảo mật có khả năng quét lỗ hổng trong container images, filesystem (dependencies), Kubernetes manifests, Terraform configs, và tạo SBOM (Software Bill of Materials). Phiên bản v0.69.3 (tháng 3/2026) tiếp tục mở rộng khả năng:

  • Julia vulnerability scanning: Hỗ trợ quét lỗ hổng cho ngôn ngữ Julia (trước đó chỉ hỗ trợ SBOM).
  • PHP Composer dev dependencies: Quét cả dev dependencies với flag --include-dev-deps.
  • AnalyzedBy field: Chỉ rõ analyzer nào phát hiện từng package — hữu ích khi debug kết quả quét.
  • JSON Schema cho trivy.yaml: Hỗ trợ autocomplete và validation trong editor.
  • Trivy checks bundle v2: Bộ rules kiểm tra cấu hình được cập nhật toàn diện.

Cài đặt Trivy trên Linux

# Ubuntu/Debian
sudo apt-get install -y wget apt-transport-https gnupg
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | sudo gpg --dearmor -o /usr/share/keyrings/trivy.gpg
echo "deb [signed-by=/usr/share/keyrings/trivy.gpg] https://aquasecurity.github.io/trivy-repo/deb generic main" | sudo tee /etc/apt/sources.list.d/trivy.list
sudo apt-get update && sudo apt-get install -y trivy

# RHEL/CentOS/AlmaLinux
cat << 'EOF' | sudo tee /etc/yum.repos.d/trivy.repo
[trivy]
name=Trivy repository
baseurl=https://aquasecurity.github.io/trivy-repo/rpm/releases/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://aquasecurity.github.io/trivy-repo/rpm/public.key
EOF
sudo yum install -y trivy

# Kiểm tra phiên bản
trivy version

Quét container images

# Quét image Docker — chỉ hiển thị lỗ hổng CRITICAL và HIGH
trivy image --severity CRITICAL,HIGH nginx:latest

# Quét image đã build cục bộ
trivy image --severity CRITICAL,HIGH myapp:v1.0

# Xuất kết quả dạng JSON cho xử lý tự động
trivy image --format json --output trivy-image-report.json myapp:v1.0

# Xuất SARIF cho GitHub Security tab
trivy image --format sarif --output trivy.sarif myapp:v1.0

# Tạo SBOM (Software Bill of Materials) dạng CycloneDX
trivy image --format cyclonedx --output sbom.json myapp:v1.0

Quét filesystem — dependencies và source code

# Quét dependencies trong project hiện tại
trivy fs --severity CRITICAL,HIGH .

# Quét kèm secret detection
trivy fs --scanners vuln,secret,misconfig .

# Quét và exit code 1 nếu có CRITICAL (dùng trong CI)
trivy fs --exit-code 1 --severity CRITICAL .

Quét Infrastructure-as-Code (Terraform, Kubernetes)

# Quét Terraform configs
trivy config --severity CRITICAL,HIGH ./terraform/

# Quét Kubernetes manifests
trivy config --severity CRITICAL,HIGH ./k8s/

# Quét Dockerfile
trivy config Dockerfile

Tích Hợp Vào GitHub Actions — Pipeline DevSecOps Hoàn Chỉnh

Được rồi, giờ là phần quan trọng nhất: kết hợp cả ba công cụ vào một pipeline GitHub Actions tự động. Pipeline này sẽ chạy trên mỗi push và pull request, quét song song để tiết kiệm thời gian, và chặn merge nếu phát hiện vấn đề nghiêm trọng.

Cấu trúc thư mục

.github/
  workflows/
    security-pipeline.yml    # Pipeline chính
.gitleaks.toml               # Cấu hình Gitleaks
custom-rules/
  semgrep-rules.yaml         # Custom Semgrep rules
trivy.yaml                   # Cấu hình Trivy (tùy chọn)
Dockerfile                   # Nếu ứng dụng dùng container

Pipeline hoàn chỉnh: .github/workflows/security-pipeline.yml

Đây là file workflow mà bạn sẽ dành nhiều thời gian nhất. Mình đã chia thành 6 jobs riêng biệt để dễ maintain — mỗi job có trách nhiệm rõ ràng:

name: DevSecOps Security Pipeline

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]
  schedule:
    - cron: '0 6 * * 1'  # Quét toàn bộ mỗi thứ Hai lúc 6h sáng UTC

permissions:
  actions: read
  contents: read
  security-events: write
  pull-requests: write

jobs:
  # ============================================
  # JOB 1: Secret Scanning với Gitleaks
  # ============================================
  secret-scan:
    name: "Secrets Detection (Gitleaks)"
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          fetch-depth: 0  # Full history để quét mọi commit

      - name: Run Gitleaks
        uses: gitleaks/gitleaks-action@v2
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

  # ============================================
  # JOB 2: SAST với Semgrep
  # ============================================
  sast-scan:
    name: "SAST Analysis (Semgrep)"
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Run Semgrep
        uses: returntocorp/semgrep-action@v1
        with:
          config: >-
            p/security-audit
            p/secrets
            p/owasp-top-ten
          generateSarif: true

      - name: Upload SARIF to GitHub Security
        if: always()
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: semgrep.sarif

  # ============================================
  # JOB 3: Dependency Scanning với Trivy (SCA)
  # ============================================
  dependency-scan:
    name: "Dependency Scan (Trivy SCA)"
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Scan filesystem dependencies
        uses: aquasecurity/[email protected]
        with:
          scan-type: fs
          scan-ref: .
          format: sarif
          output: trivy-fs.sarif
          severity: CRITICAL,HIGH
          exit-code: 1

      - name: Upload dependency scan results
        if: always()
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: trivy-fs.sarif

  # ============================================
  # JOB 4: Container Scanning với Trivy
  # ============================================
  container-scan:
    name: "Container Scan (Trivy Image)"
    runs-on: ubuntu-latest
    needs: [secret-scan, sast-scan]  # Chỉ build sau khi qua secrets + SAST
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Build Docker image
        run: docker build -t myapp:${{ github.sha }} .

      - name: Scan container image
        uses: aquasecurity/[email protected]
        with:
          image-ref: myapp:${{ github.sha }}
          format: sarif
          output: trivy-image.sarif
          severity: CRITICAL,HIGH
          vuln-type: os,library
          exit-code: 1

      - name: Upload container scan results
        if: always()
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: trivy-image.sarif

  # ============================================
  # JOB 5: IaC Security Scan
  # ============================================
  iac-scan:
    name: "IaC Security Scan (Trivy Config)"
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Scan IaC configurations
        uses: aquasecurity/[email protected]
        with:
          scan-type: config
          scan-ref: .
          format: sarif
          output: trivy-iac.sarif
          severity: CRITICAL,HIGH

      - name: Upload IaC scan results
        if: always()
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: trivy-iac.sarif

  # ============================================
  # JOB 6: SBOM Generation
  # ============================================
  sbom:
    name: "Generate SBOM"
    runs-on: ubuntu-latest
    needs: [container-scan]
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Build Docker image
        run: docker build -t myapp:${{ github.sha }} .

      - name: Generate SBOM
        uses: aquasecurity/[email protected]
        with:
          image-ref: myapp:${{ github.sha }}
          format: cyclonedx
          output: sbom-cyclonedx.json

      - name: Upload SBOM artifact
        uses: actions/upload-artifact@v4
        with:
          name: sbom
          path: sbom-cyclonedx.json

Thiết Lập Security Gates — Chặn Code Không An Toàn

Pipeline bảo mật mà không có security gates thì giống như có camera giám sát nhưng không ai xem — phát hiện vấn đề mà không ai hành động. Security gates đảm bảo rằng không ai có thể bỏ qua kết quả quét, kể cả team lead hay admin.

Cấu hình Branch Protection Rules trên GitHub

Vào Settings → Branches → Branch protection rules cho nhánh main:

  1. Bật "Require status checks to pass before merging"
  2. Thêm các required status checks: secret-scan, sast-scan, dependency-scan, container-scan
  3. Bật "Require branches to be up to date before merging"
  4. Bật "Do not allow bypassing the above settings" — ngay cả admin cũng không bypass được. Đây là cài đặt mà mình thấy nhiều đội bỏ qua, rồi lại có người "tiện tay" merge khi pipeline đang fail.

Chiến lược xử lý exit codes

Trong pipeline ở trên, chú ý tham số exit-code: 1 ở Trivy. Khi tìm thấy lỗ hổng ở mức CRITICAL hoặc HIGH, job sẽ fail và ngăn merge. Đây là chiến lược mình khuyến nghị — bắt đầu nghiêm ngặt rồi điều chỉnh dần:

  • CRITICAL: Luôn chặn — không có ngoại lệ. Đây là lỗ hổng có thể bị khai thác ngay.
  • HIGH: Chặn trên nhánh main, cảnh báo trên nhánh feature. Cho developer thời gian sửa trước khi merge.
  • MEDIUM: Cảnh báo nhưng không chặn — ghi nhận như tech debt để xử lý trong sprint tiếp theo.
  • LOW/INFO: Chỉ logging — không hiển thị trong PR để tránh alert fatigue (vấn đề này nghiêm trọng hơn bạn nghĩ).

Cấu hình ngưỡng bảo mật với file policy

# security-policy.yml — định nghĩa ngưỡng chấp nhận được
thresholds:
  sast:
    critical: 0   # Chặn merge nếu có bất kỳ CRITICAL nào
    high: 0       # Chặn merge nếu có HIGH
    medium: 10    # Cho phép tối đa 10 MEDIUM
  sca:
    critical: 0
    high: 5       # Cho phép nếu chưa có bản vá
  container:
    critical: 0
    high: 5
exemptions:
  require_approval: true
  approvers:
    - security-team
  max_duration_days: 30  # Ngoại lệ hết hạn sau 30 ngày

Giám Sát Kết Quả Và Tích Hợp Với GitHub Security Tab

Một lợi thế lớn khi sử dụng format SARIF (và mình nghĩ đây là lý do bạn nên dùng SARIF thay vì JSON thuần) là tất cả kết quả từ Gitleaks, Semgrep, và Trivy được tập trung vào GitHub Security tab. Một nơi duy nhất để xem toàn bộ bức tranh bảo mật — không cần mở từng report riêng lẻ.

Cách khai thác GitHub Security tab

  • Code scanning alerts: Tổng hợp findings từ Semgrep và Trivy, phân loại theo mức độ nghiêm trọng.
  • Secret scanning alerts: Kết quả từ Gitleaks hiển thị với thông tin chi tiết về vị trí và loại secret.
  • Dependency graph: Cây dependencies với cảnh báo lỗ hổng tự động từ Trivy SCA.

Tích hợp với Wazuh

Nếu bạn đã triển khai Wazuh SIEM (theo hướng dẫn trước đó của chúng tôi), bạn có thể chuyển tiếp alerts từ GitHub Actions về Wazuh để có cái nhìn tổng thể. Thêm step sau vào cuối pipeline:

      - name: Forward alerts to Wazuh
        if: failure()
        run: |
          curl -k -X POST "https://${{ secrets.WAZUH_API }}/active-response" \
            -H "Authorization: Bearer ${{ secrets.WAZUH_TOKEN }}" \
            -H "Content-Type: application/json" \
            -d '{"command": "custom-alert", "arguments": ["github-security", "${{ github.repository }}", "${{ github.sha }}"]}';

Tối Ưu Hiệu Suất Pipeline

Mình phải nói thẳng: một pipeline DevSecOps chạy quá lâu sẽ bị developer ghét và tìm cách bypass. Chuyện này xảy ra nhiều hơn bạn tưởng. Dưới đây là các kỹ thuật tối ưu thực tế mà mình thấy hiệu quả.

Chạy jobs song song

Trong pipeline ở trên, các jobs secret-scan, sast-scan, dependency-scan, và iac-scan chạy song song vì không phụ thuộc nhau. Chỉ container-scan mới cần chờ (vì phải build image trước). Kết quả? Tổng thời gian pipeline giảm từ tổng cộng tất cả jobs xuống chỉ bằng job chạy lâu nhất.

Sử dụng cache cho Trivy database

Trivy database khá nặng và tải lại mỗi lần chạy sẽ thêm 1-2 phút. Cache nó lại:

      - name: Cache Trivy database
        uses: actions/cache@v4
        with:
          path: /home/runner/.cache/trivy
          key: trivy-db-${{ hashFiles('.github/workflows/security-pipeline.yml') }}
          restore-keys: trivy-db-

Giới hạn scope quét

# .trivyignore — bỏ qua CVE đã đánh giá không ảnh hưởng
CVE-2023-XXXXX  # Không ảnh hưởng vì module này không được sử dụng
CVE-2024-YYYYY  # Đã có mitigation ở layer khác

# Semgrep: bỏ qua test files
# Trong workflow, thêm exclude patterns
semgrep scan --config auto --exclude "test_*" --exclude "*_test.go" .

Lộ Trình Mở Rộng Pipeline

Pipeline ba công cụ ở trên là nền tảng vững chắc, nhưng đừng dừng ở đó. Khi đội ngũ đã quen với workflow mới, hãy mở rộng dần theo lộ trình sau:

  • Giai đoạn 1 (hiện tại): Gitleaks + Semgrep + Trivy — bao phủ secrets, SAST, SCA, container scanning. Đủ cho phần lớn các dự án.
  • Giai đoạn 2: Thêm OWASP ZAP cho DAST — quét ứng dụng đang chạy trên staging environment. Đây là lớp bổ sung quan trọng vì SAST không phát hiện được mọi thứ.
  • Giai đoạn 3: Tích hợp Sigstore/Cosign cho artifact signing — xác minh tính toàn vẹn của container images theo chuẩn SLSA Level 3.
  • Giai đoạn 4: Thêm OPA (Open Policy Agent) cho policy-as-code — tự động hóa tuân thủ PCI DSS, HIPAA, ISO 27001.

Câu Hỏi Thường Gặp

DevSecOps khác gì so với DevOps truyền thống?

DevOps tập trung vào tốc độ phát triển và triển khai liên tục. DevSecOps bổ sung thêm lớp bảo mật vào mọi giai đoạn — từ commit code đến deploy production. Sự khác biệt cốt lõi nằm ở "shift-left security": thay vì kiểm tra bảo mật ở cuối quy trình (penetration testing trước khi go-live), DevSecOps phát hiện lỗ hổng ngay khi developer viết code. Theo triết lý "shift smart" đang phổ biến năm 2026, phản hồi bảo mật phải thông minh, có ngữ cảnh, và hành động được — không phải hàng trăm cảnh báo mà chẳng ai đọc.

Gitleaks, Semgrep và Trivy có thực sự miễn phí không?

Có. Cả ba đều có phiên bản mã nguồn mở hoàn toàn miễn phí và đủ mạnh cho production. Gitleaks dùng MIT license, Trivy là Apache 2.0, và Semgrep có phiên bản Community miễn phí. Các phiên bản trả phí (Semgrep Pro, Aqua Platform) cung cấp thêm dashboard tập trung, SSO, custom policies — nhưng thành thật mà nói, phiên bản miễn phí đã đủ cho hầu hết đội ngũ từ nhỏ đến trung bình.

Làm sao để giảm false positives trong pipeline DevSecOps?

Ba chiến lược hiệu quả nhất mà mình đã áp dụng: (1) Bắt đầu chỉ với severity CRITICAL và HIGH, sau đó mở rộng dần — đừng bật tất cả rules cùng lúc, đội bạn sẽ bị ngập trong cảnh báo. (2) Sử dụng allowlist/ignore files cho các trường hợp đã đánh giá rủi ro — như .trivyignore cho Trivy hoặc allowlist trong .gitleaks.toml. (3) Với Semgrep, viết custom rules thay vì dùng tất cả rule packs mặc định. Mỗi dự án có threat model riêng — không nên quét bừa bãi.

Pipeline DevSecOps có làm chậm quá trình phát triển không?

Nếu thiết kế đúng thì không đáng kể. Các jobs chạy song song giữ tổng thời gian pipeline dưới 5 phút cho hầu hết dự án. Mẹo quan trọng nhất: cache database Trivy giữa các lần chạy, giới hạn quét chỉ các files thay đổi trên PR (incremental scan), và chỉ chạy container scan khi Dockerfile thực sự thay đổi. Vài phút chờ đợi luôn tốt hơn nhiều so với chi phí xử lý một vụ vi phạm bảo mật trong production — cả về tiền bạc lẫn uy tín.

Nên bắt đầu từ đâu nếu chưa có kinh nghiệm DevSecOps?

Bắt đầu từ Gitleaks pre-commit hook. Nghiêm túc, chỉ bước này thôi đã chặn được rất nhiều vấn đề. Mất khoảng 5 phút cài đặt và ngay lập tức ngăn secrets bị commit. Tiếp theo, thêm Semgrep vào GitHub Actions với config p/security-audit — bộ rules này được cộng đồng duy trì và đã tối ưu để giảm false positives. Cuối cùng, thêm Trivy khi bạn bắt đầu containerize ứng dụng.

Đừng cố làm tất cả cùng lúc — mỗi tuần thêm một công cụ mới là nhịp độ hợp lý. Quan trọng hơn cả công cụ là mindset: bảo mật không phải là checklist để hoàn thành, mà là thói quen cần xây dựng.

Về Tác Giả Editorial Team

Our team of expert writers and editors.