5 bước kiểm tra bảo mật hàng đầu cần bổ sung vào mọi CI/CD pipeline trong năm 2026
Bối cảnh Software Supply Chain Attack năm 2026 đã thay đổi hoàn toàn so với vài năm trước. Các sự cố như XZ Utils Backdoor (2024), nhiều vụ chiếm quyền gói npm và các GitHub Actions bị xâm nhập cho thấy tin tặc không còn chỉ nhắm vào hệ thống production, mà chuyển sang tấn công công cụ, dependency và pipeline CI/CD dùng để xây dựng phần mềm.
Song song đó, các quy định mới cũng siết chặt yêu cầu bảo mật. Ví dụ, EU Cyber Resilience Act (CRA) yêu cầu doanh nghiệp chứng minh nguồn gốc phần mềm, quy trình quản lý lỗ hổng và tài liệu bảo mật. Vì vậy, mỗi CI/CD pipeline hiện đại nên tích hợp 5 bước kiểm tra bảo mật cốt lõi. Đây không chỉ là yêu cầu tuân thủ mà còn là cách hiệu quả nhất để phát hiện lỗ hổng trước khi mã nguồn được triển khai, với chi phí thấp và thời gian bổ sung chỉ khoảng vài phút cho mỗi pipeline.
Chuyện gì xảy ra nếu khắc phục chậm?
Việc khắc phục một lỗ hổng được phát hiện bởi SAST trong quy trình CI chỉ tốn 15 phút (do lập trình viên vẫn đang nắm bắt bối cảnh khi thay đổi code). Trong khi đó, cùng lỗ hổng này nếu được phát hiện qua penetration test)sẽ tốn tới 4 giờ (bao gồm chuyển đổi ngữ cảnh, xem xét báo cáo, lên lịch và xác minh). Nếu lỗ hổng đó bị khai thác trên môi trường production, chi phí thời gian để xử lý có thể lên tới hàng tuần, chưa kể những tổn hại về uy tín. Các bước kiểm tra bảo mật trong quy trình CI chính là khoản đầu tư tiết kiệm nhất trong tình huống bảo mật này.
#1 SAST - Static Application Security Testing - Phát hiện: SQL injection, path traversal, XSS, giải tuần tự hóa (deserialization) không an toàn, các secrets được mã hóa cứng trong logic.
Khái niệm
SAST phân tích code mà không cần phải thực thi, nhằm tìm kiếm các mẫu (pattern) chỉ ra lỗ hổng bảo mật. Khác với linting (vốn chỉ kiểm tra style và syntax), SAST thực hiện phân tích luồng dữ liệu và theo dõi dữ liệu không an toàn (taint tracking): nó truy vết điểm đầu vào của người dùng (sources) và xác định xem liệu dữ liệu đó có thể đi đến các thao tác nguy hiểm (sinks) mà chưa qua bước làm sạch hay không.
CodeQL - Tiêu chuẩn cho Production
CodeQL của GitHub sử dụng phân tích ngữ nghĩa (Semantic Analysis) để phát hiện những nhóm lỗ hổng mà các công cụ dò mẫu thông thường thường bỏ sót. Công cụ có thể nhận diện trường hợp dữ liệu đầu vào đi qua nhiều hàm, nhiều tệp mã nguồn và truy vấn cơ sở dữ liệu trước khi được sử dụng trong exec(), từ đó xác định nguy cơ Command Injection ngay cả khi luồng dữ liệu trải dài trên nhiều file.
Miễn phí cho repository mã nguồn mở.
Repository riêng yêu cầu GitHub Advanced Security.
Semgrep – Nhanh và dễ tùy chỉnh
Semgrep là công cụ SAST dựa trên Pattern Matching, có tốc độ phân tích nhanh hơn CodeQL và khả năng tùy biến cao. Bộ quy tắc cộng đồng tại registry.semgrep.dev bao phủ hầu hết các lỗ hổng thuộc OWASP Top 10 cho nhiều ngôn ngữ lập trình. Ngoài ra, doanh nghiệp có thể tự viết các Semgrep Rules chỉ trong vài phút để kiểm tra những yêu cầu bảo mật đặc thù mà các công cụ chung chưa hỗ trợ.
Mô hình Tích hợp
Chạy SAST trên mỗi PR, chỉ tập trung vào các file đã thay đổi trong PR đó. Việc quét toàn bộ mã nguồn ở mỗi lần commit sẽ tốn quá nhiều thời gian; trong khi đó, việc chỉ quét các file đã thay đổi vừa nhanh chóng vừa giúp phát hiện các vấn đề mới trước khi code được hợp nhất. Định dạng output của SARIF cho phép hiển thị trực tiếp các kết quả phát hiện lên giao diện review PR của GitHub dưới dạng chú thích ngay trong dòng code.
Những gì SAST không phát hiện được
SAST không phát hiện được: các lỗ hổng trong dependency (hãy sử dụng SCA/Trivy cho trường hợp này), các cấu hình infrastructure sai (hãy sử dụng Checkov/Trivy cho IaC), và các lỗ hổng phát sinh trong quá trình chạy (hãy sử dụng DAST hoặc các công cụ bảo mật runtime). SAST là yếu tố cần thiết nhưng chưa đủ để đảm bảo một trạng thái bảo mật toàn diện.
# Quy trình SAST hoàn chỉnh: CodeQL + Semgrep
name: Security
on:
pull_request: {branches: [main]}
push: {branches: [main]}
jobs:
codeql:
runs-on: ubuntu-latest
permissions:
security-events: write
contents: read
steps:
- uses: actions/checkout@v4
- uses: github/codeql-action/init@v3
with:
languages: python,javascript
queries: security-and-quality
- uses: github/codeql-action/autobuild@v3
- uses: github/codeql-action/analyze@v3
semgrep:
runs-on: ubuntu-latest
container:
image: returntocorp/semgrep
steps:
- uses: actions/checkout@v4
- name: Run Semgrep
run: |
semgrep ci \
— config=p/owasp-top-ten \
— config=p/python \
— sarif \
— output=semgrep.sarif
env:
SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }}
- uses: github/codeql-action/upload-sarif@v3
with: {sarif_file: semgrep.sarif}
#2 Secret Detection – Ngăn chặn thông tin nhạy cảm trước khi vào Git
Phát hiện: API Key, Private Key, JWT Secret, mật khẩu cơ sở dữ liệu và thông tin xác thực Cloud.
Secret Detection là gì?
Secret Detection là bước kiểm tra chuyên biệt nhằm phát hiện các thông tin nhạy cảm bị vô tình đưa vào mã nguồn. Đây là một nhóm lỗ hổng phổ biến và có mức độ rủi ro rất cao, vì một khi secret được commit lên Git, nó gần như được xem là đã bị lộ. Ngay cả với repository riêng tư, bất kỳ ai có quyền truy cập cũng có thể xem toàn bộ lịch sử commit và lấy được các khóa hoặc mật khẩu đó.
GitHub Advanced Secret Scanning có khả năng nhận diện hơn 200 loại token và khóa truy cập từ các nhà cung cấp phổ biến như AWS, GCP, Azure, Stripe, Twilio và GitHub. Khi phát hiện secret trong repository, GitHub sẽ tự động cảnh báo chủ sở hữu; với repository riêng, GitHub còn có thể thông báo cho nhà cung cấp dịch vụ để thu hồi (revoke) token ngay lập tức. Đây là tính năng bảo mật cơ bản nên được bật trên mọi repository.
truffleHog - Quét History sâu
truffleHog quét toàn bộ lịch sử Git, chứ không chỉ trạng thái HEAD hiện tại. Công cụ này sử dụng phương pháp phát hiện dựa trên độ entropy (entropy-based ) và các mẫu biểu thức regex để tìm kiếm các secrets trong bất kỳ commit nào, không chỉ các commit gần đây. Bạn có thể chạy truffleHog để thực hiện kiểm tra một lần trên các repo hiện có hoặc dùng làm bước kiểm tra CI đối với các commit mới.
Pre-commit Hook
Phương pháp phát hiện thông tin nhạy cảm hiệu quả nhất là sử dụng pre-commit hook: phát hiện và ngăn chặn các thông tin nhạy cảm ngay trước khi chúng được commit. Các công cụ như git-secrets (mã nguồn mở của AWS) và detect-secrets (mã nguồn mở của Yelp) hoạt động dưới dạng git hook, giúp chặn các commit có chứa thông tin nhạy cảm đã bị phát hiện. Mặc dù dev cần phải thực hiện setup ban đầu, nhưng việc ngăn chặn thông tin nhạy cảm ngay từ khâu commit vẫn tốt hơn nhiều so với việc phát hiện ra chúng sau khi sự việc đã rồi.
Trở ngại lớn nhất
Việc phát hiện các secret chỉ thực sự hữu ích khi các developer có quy trình rõ ràng về những việc cần làm ngay khi phát hiện ra chúng: thay đổi thông tin xác thực (credential) ngay lập tức (chứ không phải đợi đến khi "hoàn thành xong tính năng này" mới làm), kiểm tra xem thông tin đó đã từng bị sử dụng hay chưa (thông qua CloudTrail hoặc audit log), và tìm hiểu nguyên nhân tại sao nó lại xuất hiện trong code (do lỗ hổng trong quy trình quản lý cấu hình). Công cụ thì dễ triển khai, nhưng thay đổi quy trình làm việc mới là điều khó khăn.
# truffleHog: quét các commit mới trong PR để tìm secrets
secret-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Full history for deep scanning
- name: Scan for secrets with truffleHog
uses: trufflesecurity/trufflehog@main
with:
path: ./
base: ${{ github.event.repository.default_branch }}
head: HEAD
extra_args: — only-verified
# — only-verified: only report secrets that can be
# programmatically verified as valid (reduces false positives)
# detect-secrets: pre-commit hook (developer-side)
# Install: pip install detect-secrets
# Baseline: detect-secrets scan > .secrets.baseline
# Pre-commit config (.pre-commit-config.yaml):
repos:
- repo: https://github.com/Yelp/detect-secrets
rev: v1.5.0
hooks:
- id: detect-secrets
args: [' — baseline', '.secrets.baseline']
# Các developer phải xem xét và xác định rõ ràng các trường hợp báo động sai
#3 SBOM Generation – Software Bill of Materials cho tuân thủ
Tạo ra: Danh sách đầy đủ mọi dependency và phiên bản có trong Docker image.
SBOM là gì?
SBOM (Software Bill of Materials) là một inventory có cấu trúc, ở định dạng máy có thể đọc được, ghi lại toàn bộ thành phần tạo nên một phần mềm. Đối với Docker image, SBOM bao gồm các OS package, runtime, thư viện ứng dụng và tất cả dependency trực tiếp lẫn gián tiếp cùng phiên bản của chúng trong mọi layer.
SBOM giúp doanh nghiệp biết chính xác phần mềm đang sử dụng những thành phần nào, hỗ trợ quản lý lỗ hổng, truy vết nguồn gốc (provenance) và đáp ứng các yêu cầu tuân thủ như EU CRA hay SBOM trong quy trình phát triển phần mềm an toàn.
Vì sao SBOM cần thiết trong năm nay
Các tiêu chuẩn ở thị trường như Châu Âu và Mỹ đang đặt yêu cầu bắt buộc cho việc sử dụng SBOM
Tạo SBOM bằng Trivy
Lệnh `trivy image --format cyclonedx --output sbom.cyclonedx.json myimage:tag` sẽ tạo ra SBOM ở định dạng CycloneDX, trong khi `trivy image --format spdx-json` tạo ra định dạng SPDX. Cả hai định dạng này đều được chấp nhận bởi các khuôn khổ tuân thủ. CycloneDX được sử dụng rộng rãi hơn cho các mục đích bảo mật, còn SPDX là tiêu chuẩn của Linux Foundation.
SBOM Attestation
SBOM chỉ thực sự có giá trị khi được ký số và gắn với đúng Docker image mà nó mô tả. Sử dụng Cosign Attestation để đính kèm SBOM dưới dạng chữ ký số, giúp bất kỳ ai tải image đều có thể xác minh SBOM được tạo từ CI/CD pipeline của bạn và chưa bị chỉnh sửa.
Continuous SBOM Monitoring
SBOM chỉ phản ánh trạng thái tại thời điểm tạo. Khi các lỗ hổng (CVE) mới được công bố, những dependency đã triển khai vẫn có thể trở nên dễ bị tấn công. Vì vậy, hãy sử dụng Dependabot hoặc các công cụ SCA (Software Composition Analysis) để liên tục theo dõi SBOM và cảnh báo khi các phiên bản đang sử dụng xuất hiện lỗ hổng mới.
- name: Generate SBOM
uses: aquasecurity/trivy-action@master
with:
image-ref: ghcr.io/github.repository@{{ steps.build.outputs.digest }}
format: cyclonedx
output: sbom.cyclonedx.json
- name: Attest SBOM to image (signed by Cosign)
run: |
cosign attest — yes \
— predicate sbom.cyclonedx.json \
— type cyclonedx \
ghcr.io/github.repository@{{ steps.build.outputs.digest }}
- name: Upload SBOM as release asset
uses: actions/upload-artifact@v4
with:
name: sbom-${{ github.sha }}
path: sbom.cyclonedx.json
# Verify SBOM attestation (by downstream consumer):
# cosign verify-attestation \
# — type cyclonedx \
# — certificate-identity-regexp 'https://github.com/yourorg/.*' \
# — certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \
# ghcr.io/yourorg/payments-api@sha256:abc123
# Returns the SBOM JSON if the attestation is valid
#4 Container Image Signing – Xác minh nguồn gốc Docker Image
Đảm bảo: Chỉ những Docker image được tạo bởi CI/CD pipeline mới được phép triển khai lên production.
Container Image Signing là gì?
Container Image Signing sử dụng chữ ký số để chứng minh rằng một Docker image cụ thể (xác định bằng immutable digest) đã được tạo bởi CI/CD pipeline, tại một thời điểm xác định và từ đúng repository cùng commit Git. Nhờ đó, bất kỳ ai tải image đều có thể xác minh nguồn gốc (provenance) mà không cần phải tin tưởng vào registry.
Container Image Signing không làm được gì?
Image Signing chỉ xác minh nguồn gốc, không đảm bảo image an toàn. Một image đã signed vẫn có thể chứa lỗ hổng hoặc mã độc nếu chúng đã tồn tại trước đó. Vì vậy, Image Signing cần được kết hợp với SAST và quét lỗ hổng (Trivy/SCA) để xây dựng một quy trình bảo mật CI/CD hoàn chỉnh.
Ký số không cần khóa (Keyless) với Cosign
Sigstore Keyless Signing sử dụng khóa tạm thời gắn với danh tính OIDC của GitHub Actions. Nhờ đó, không cần lưu trữ khóa ký dài hạn, giúp loại bỏ rủi ro và sự phức tạp trong việc quản lý key riêng. Mỗi lần ký đều được ghi vào Rekor (nhật ký minh bạch công khai), nên có thể kiểm tra và truy vết.
Thực thi tại thời điểm tiếp nhận (Admission)
Chuỗi tin cậy (Trust Chain)
Pipeline CI sẽ ký số image, còn Kyverno sẽ xác minh chữ ký khi triển khai. Điều này tạo ra một chuỗi tin cậy có thể xác minh bằng mật mã từ mã nguồn đến container đang chạy.
Nhờ đó, bạn có thể xác định chính xác workflow CI đã tạo ra mỗi container và phát hiện mọi image được triển khai không thông qua pipeline CI.
# Complete signing workflow
- name: Install Cosign
uses: sigstore/cosign-installer@v3
- name: Sign the container image
run: |
cosign sign — yes \
ghcr.io/github.repository@{{ steps.build.outputs.digest }}
# Kyverno ClusterPolicy: enforce signing in production
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-signed-images
spec:
validationFailureAction: Enforce
background: false
rules:
- name: verify-image-signature
match:
resources:
kinds: [Pod]
namespaces: [production, staging]
verifyImages:
- imageReferences:
- 'ghcr.io/yourorg/*'
attestors:
- count: 1
entries:
- keyless:
subject: >-
.github/workflows/ci.yml@refs/heads/main
issuer: https://token.actions.githubusercontent.com
rekor:
url: https://rekor.sigstore.dev
#5 Quét bảo mật IaC — Phát hiện cấu hình sai trước khi triển khai
Có thể phát hiện: S3 bucket công khai, security group không an toàn, RDS chưa mã hóa và IAM cấp quyền quá mức.
IaC Security Scanning là gì?
IaC Security Scanning là quá trình phân tích mã hạ tầng như Terraform, CloudFormation, Kubernetes YAML, Helm Chart, Dockerfile và Ansible Playbook để phát hiện các cấu hình bảo mật sai trước khi triển khai.
Có thể xem đây là phiên bản SAST dành cho Infrastructure as Code, giúp phát hiện lỗ hổng ngay từ mã cấu hình thay vì sau khi hạ tầng đã được tạo.
Trivy – Giải pháp toàn diện
Lệnh `trivy config ./terraform/` thực hiện quét Terraform; `trivy config ./k8s/` quét các tệp YAML của Kubernetes; và `trivy config ./helm-chart/` quét các Helm chart. Chỉ với một công cụ duy nhất và format output đồng bộ, tích hợp upload kết quả dưới định dạng SARIF tương tự như khi quét image. Đối với hầu hết các team dev, tính năng config scanning của Trivy đáp ứng đầy đủ các yêu cầu về bảo mật IaC.
Checkov dành cho các chính sách nâng cao
Checkov cung cấp các cơ chế policy check chuyên sâu hơn cùng khả năng hỗ trợ tùy chỉnh (sử dụng Rego hoặc Python). Policy library phong phú của Checkov gồm có các chuẩn CIS dành cho AWS, GCP và Azure, cũng như các chuẩn bảo mật Kubernetes. Các policy tùy chỉnh cho phép triển khai những yêu cầu cụ thể của tổ chức mà các policy thông thường không thể thực hiện hết được.
Dừng Pipeline thay vì chỉ đưa ra cảnh báo
Các IaC scanner chỉ report vấn đề mà không dừng pipeline thực chất chỉ là hình thức đối phó về mặt bảo mật. Cấu hình exit code để dừng pipeline khi phát hiện các vấn đề ở mức HIGH (Cao) và CRITICAL (Nghiêm trọng) trong các tệp cấu hình Terraform và Kubernetes. Các vấn đề mức MEDIUM (Trung bình) sẽ được đánh dấu nhưng không chặn pipeline (do một số vấn đề có thể phụ thuộc vào môi trường cụ thể). Chính cơ chế này tạo ra áp lực thực sự thúc đẩy việc khắc phục lỗi.
Phát hiện sai lệch cấu hình (drift) trong quá trình vận hành
IaC scan giúp phát hiện các cấu hình sai ngay từ giai đoạn viết code. Kết hợp với tính năng phát hiện sai lệch cấu hình trong quá trình vận hành (runtime drift detection): Trivy k8s - công cụ này sẽ quét cluster đang hoạt động hàng tuần để tìm ra các cấu hình đã bị thay đổi so với định nghĩa IaC ban đầu. Nhờ đó, các cấu hình sai phát sinh bên ngoài IaC workflow sẽ được phát hiện và xử lý trước khi chúng trở thành cố định.
iac-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Scan Terraform for misconfigurations
uses: aquasecurity/trivy-action@master
with:
scan-type: config
scan-ref: ./terraform/
format: sarif
output: iac-results.sarif
severity: HIGH,CRITICAL
exit-code: '1'
- name: Scan Kubernetes manifests
uses: aquasecurity/trivy-action@master
with:
scan-type: config
scan-ref: ./k8s/
format: sarif
output: k8s-results.sarif
severity: HIGH,CRITICAL
exit-code: '1'
- name: Upload IaC scan results
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: iac-results.sarif
# Weekly drift detection (Kubernetes CronJob):
# trivy k8s — severity HIGH,CRITICAL — report all cluster
Timeline tích hợp các bước kiểm tra bảo mật
Kiểm tra | Tích hợp ở đâu | Thời gian thêm | Hành động khi lỗi | Phạm vi tuân thủ |
SAST (CodeQL) | Trên PR (chỉ các file đã thay đổi) | 3–5 phút | Chặn merge | EU CRA Điều 13, NIST SSDF |
Phát hiện bí mật (Secret Detection) | Mỗi commit (pre-commit) | < 30 giây | Chặn commit | Tất cả framework |
Tạo SBOM | Sau build (mỗi lần merge) | 1–2 phút | Chỉ cảnh báo (vẫn tạo SBOM) | EU CRA, US EO 14028, SLSA |
Ký image (Image Signing) | Sau quét, trước khi push | < 30 giây | Chặn push nếu chưa ký | NIST SSDF, EU CRA |
Quét IaC (IaC Scanning) | Trên PR (chỉ các file IaC đã thay đổi) | 2–3 phút | Chặn merge đối với lỗi HIGH/CRITICAL | CIS Benchmarks, EU CRA |
BỘ GIẢI PHÁP BẢO MẬT CHUỖI CUNG ỨNG
Năm bước kiểm tra trong hướng dẫn này tạo thành một chương trình bảo mật chuỗi cung ứng hoàn chỉnh, tuân thủ quy định: SAST phát hiện các lỗ hổng trong mã nguồn của bạn, phát hiện bí mật ngăn chặn rò rỉ thông tin đăng nhập, tạo SBOM ghi lại các thành phần của bạn, ký hình ảnh chứng minh nguồn gốc và quét IaC ngăn ngừa cấu hình sai. Cùng nhau, chúng giải quyết phần lớn các vectơ tấn công chuỗi cung ứng phần mềm hiện đại. Không có bước nào phức tạp. Tất cả đều có sẵn miễn phí với GitHub Actions. Câu hỏi không phải là liệu bạn có đủ khả năng để triển khai chúng hay không — mà là liệu bạn có đủ khả năng để không triển khai chúng hay không.




















