spinny:~/writing $ less devsecops-shift-left-security-guide.md
12Một lỗ hổng bảo mật được phát hiện khi đang viết code chỉ tốn vài phút để sửa. Cùng lỗ hổng đó nếu bị phát hiện ở production sẽ tốn cả một sprint. Và nếu kẻ tấn công tìm thấy trước, chi phí lên tới hàng triệu đô la. Đây là luận điểm cốt lõi của **shift-left security** - đưa các kiểm tra bảo mật lên sớm nhất có thể trong vòng đời phát triển.34DevSecOps biến ý tưởng này thành thực tiễn: bảo mật không phải là một giai đoạn riêng biệt ở cuối mà là một quá trình liên tục được đan xen vào mọi giai đoạn phát triển, từ dòng code đầu tiên đến khi deploy lên production.56## Chi phí của Bảo mật Muộn78Báo cáo Cost of a Data Breach của IBM đã liên tục cho thấy chi phí sửa các vấn đề bảo mật tăng theo cấp số nhân khi phát hiện càng muộn:910| Giai đoạn | Chi phí Sửa | Thời gian Sửa |11|-------|------------|-------------|12| **IDE / Local Dev** | Phút | Giây đến phút |13| **Code Review / PR** | Giờ | Phút đến giờ |14| **CI/CD Pipeline** | Ngày | Giờ đến ngày |15| **Staging / QA** | Tuần | Ngày |16| **Production** | Tháng | Tuần đến tháng |17| **Sau khi bị xâm nhập** | Hàng triệu đô la | Tháng đến năm |1819Kết luận rõ ràng: mỗi giai đoạn bạn đưa bảo mật lên sớm hơn sẽ tiết kiệm được một bậc về chi phí và thời gian.2021## DevSecOps Pipeline2223Một DevSecOps pipeline hoàn chỉnh tích hợp kiểm tra bảo mật ở mọi giai đoạn:2425```mermaid26graph LR27 IDE[IDE / Editor] --> PC[Pre-commit Hooks]28 PC --> PR[Pull Request]29 PR --> CI[CI Pipeline]30 CI --> Build[Build / Package]31 Build --> Deploy[Deploy]32 Deploy --> Runtime[Runtime / Production]3334 IDE -.- S1[SAST\nSecret Detection\nLinting]35 PC -.- S2[Secrets Scan\nFormat Check]36 PR -.- S3[Code Review\nDependency Audit]37 CI -.- S4[SAST\nSCA\nContainer Scan\nSBOM]38 Build -.- S5[Image Signing\nArtifact Verification]39 Deploy -.- S6[Policy Enforcement\nAdmission Control]40 Runtime -.- S7[DAST\nWAF\nMonitoring]41```4243Hãy cùng phân tích từng giai đoạn với các công cụ và cấu hình cụ thể.4445## Giai đoạn 1: Bảo mật trong IDE4647Vòng phản hồi nhanh nhất. Bắt lỗ hổng trước khi bạn lưu file.4849### Công cụ Khuyên dùng5051- **Semgrep**: công cụ static analysis nhẹ với community rules cho các lỗ hổng OWASP52- **Snyk IDE Extension**: quét lỗ hổng dependency theo thời gian thực53- **GitLens + GitLeaks**: phát hiện secret trong editor54- **ESLint Security Plugins**: `eslint-plugin-security` cho Node.js, `eslint-plugin-no-unsanitized` cho DOM XSS5556### Ví dụ: Cấu hình ESLint Security5758```json59{60 "extends": ["eslint:recommended"],61 "plugins": ["security", "no-unsanitized"],62 "rules": {63 "security/detect-object-injection": "warn",64 "security/detect-non-literal-regexp": "warn",65 "security/detect-unsafe-regex": "error",66 "security/detect-buffer-noassert": "error",67 "security/detect-eval-with-expression": "error",68 "security/detect-no-csrf-before-method-override": "error",69 "security/detect-possible-timing-attacks": "warn",70 "no-unsanitized/method": "error",71 "no-unsanitized/property": "error"72 }73}74```7576## Giai đoạn 2: Pre-commit Hooks7778Tuyến phòng thủ thứ hai. Tự động chạy trước mọi commit, chặn code nguy hiểm không cho vào repository.7980### Gitleaks: Bắt Secret Trước khi Vào Git8182Lỗi bảo mật phổ biến nhất trong codebase là commit secret - API key, mật khẩu cơ sở dữ liệu, token. Một khi secret đã vào git history, việc xóa hoàn toàn là cực kỳ khó khăn (ngay cả khi force push, các fork và cache vẫn có thể giữ lại).8384```yaml85# .pre-commit-config.yaml86repos:87 - repo: https://github.com/gitleaks/gitleaks88 rev: v8.21.089 hooks:90 - id: gitleaks9192 - repo: https://github.com/semgrep/semgrep93 rev: v1.90.094 hooks:95 - id: semgrep96 args: ['--config', 'auto']97```9899Cài đặt và kích hoạt:100101```bash102pip install pre-commit103pre-commit install104```105106Bây giờ mỗi lần `git commit` sẽ tự động quét secret bị rò rỉ và các lỗ hổng phổ biến. Nếu tìm thấy bất kỳ điều gì, commit sẽ bị chặn.107108### Tùy chỉnh Quy tắc Gitleaks109110Bạn có thể thêm các pattern tùy chỉnh cho secret của tổ chức:111112```toml113# .gitleaks.toml114title = "Custom Gitleaks Config"115116[[rules]]117id = "internal-api-key"118description = "Internal API key detected"119regex = '''INTERNAL_KEY_[A-Za-z0-9]{32}'''120tags = ["key", "internal"]121```122123## Giai đoạn 3: Bảo mật CI/CD Pipeline124125Đây là nơi công việc nặng nhọc diễn ra. CI pipeline của bạn nên chạy nhiều lượt quét bảo mật trên mỗi pull request.126127### SAST (Static Application Security Testing)128129Các công cụ SAST phân tích mã nguồn mà không cần thực thi, tìm kiếm các pattern cho thấy lỗ hổng.130131```yaml132# .github/workflows/security.yml133name: Security Scan134on:135 pull_request:136 branches: [main]137138jobs:139 sast:140 name: Static Analysis141 runs-on: ubuntu-latest142 steps:143 - uses: actions/checkout@v4144145 - name: Run Semgrep146 uses: semgrep/semgrep-action@v1147 with:148 config: >-149 p/owasp-top-ten150 p/typescript151 p/nodejs152 p/react153 generateSarif: true154155 - name: Upload SARIF156 uses: github/codeql-action/upload-sarif@v3157 with:158 sarif_file: semgrep.sarif159```160161Ruleset `p/owasp-top-ten` của Semgrep bắt các lỗ hổng phổ biến nhất: SQL injection, XSS, SSRF, path traversal, insecure deserialization và nhiều hơn nữa.162163### SCA (Software Composition Analysis)164165SCA quét các dependency để tìm lỗ hổng đã biết. Điều này rất quan trọng - hơn 80% code ứng dụng hiện đại đến từ các dependency mã nguồn mở.166167```yaml168 dependency-scan:169 name: Dependency Audit170 runs-on: ubuntu-latest171 steps:172 - uses: actions/checkout@v4173174 - name: Run Snyk175 uses: snyk/actions/node@master176 env:177 SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}178 with:179 args: --severity-threshold=high180181 - name: npm audit182 run: npm audit --audit-level=high183```184185### Bảo mật Container với Trivy186187Nếu bạn build Docker image, việc quét lỗ hổng là thiết yếu. **Trivy** là container scanner mã nguồn mở phổ biến nhất.188189```yaml190 container-scan:191 name: Container Security192 runs-on: ubuntu-latest193 steps:194 - uses: actions/checkout@v4195196 - name: Build image197 run: docker build -t my-app:${{ github.sha }} .198199 - name: Run Trivy200 uses: aquasecurity/trivy-action@master201 with:202 image-ref: my-app:${{ github.sha }}203 format: 'sarif'204 output: 'trivy-results.sarif'205 severity: 'CRITICAL,HIGH'206 exit-code: '1'207208 - name: Upload Trivy SARIF209 uses: github/codeql-action/upload-sarif@v3210 with:211 sarif_file: trivy-results.sarif212```213214### Tạo SBOM215216**Software Bill of Materials (SBOM)** là danh mục đầy đủ mọi component trong ứng dụng của bạn. Ngày càng được yêu cầu bởi các compliance framework và quy định của chính phủ (Lệnh Hành pháp của Mỹ về Cybersecurity yêu cầu SBOM cho phần mềm của liên bang).217218```yaml219 sbom:220 name: Generate SBOM221 runs-on: ubuntu-latest222 steps:223 - uses: actions/checkout@v4224225 - name: Generate SBOM with Syft226 uses: anchore/sbom-action@v0227 with:228 format: spdx-json229 output-file: sbom.spdx.json230231 - name: Upload SBOM232 uses: actions/upload-artifact@v4233 with:234 name: sbom235 path: sbom.spdx.json236```237238## Giai đoạn 4: Docker Image An toàn239240Docker image cho production nên tuân theo nguyên tắc đặc quyền tối thiểu. Đây là một Dockerfile đã được tăng cường:241242```dockerfile243# Build stage244FROM node:22-alpine AS builder245WORKDIR /app246COPY package.json package-lock.json ./247RUN npm ci248COPY . .249RUN npm run build250251# Production stage252FROM node:22-alpine AS runner253WORKDIR /app254255# Install dumb-init before dropping root256RUN apk add --no-cache dumb-init257258# Don't run as root259RUN addgroup -S app && adduser -S app -G app260261# Copy only what's needed262COPY --from=builder --chown=app:app /app/dist ./dist263COPY --from=builder --chown=app:app /app/node_modules ./node_modules264COPY --from=builder --chown=app:app /app/package.json ./265266# Drop to non-root user267USER app268ENTRYPOINT ["dumb-init", "--"]269270# Health check271HEALTHCHECK --interval=30s --timeout=3s --retries=3 \272 CMD wget -qO- http://localhost:3000/health || exit 1273274EXPOSE 3000275CMD ["node", "dist/server.js"]276```277278Các thực hành chính:2792801. **Sử dụng multi-stage build**: giai đoạn builder có dev dependency; giai đoạn runner chỉ có code production2812. **Không chạy bằng root**: tạo non-root user và chuyển sang2823. **Sử dụng Alpine image**: bề mặt tấn công nhỏ hơn (ít package được cài đặt mặc định)2834. **Ghim phiên bản image**: `node:22-alpine` thay vì `node:latest` để tránh supply chain attack2845. **Sử dụng `npm ci`**: cài đặt xác định từ lock file, không phải `npm install`285286## Giai đoạn 5: Quản lý Secret287288Secret được hard-code là nguyên nhân hàng đầu gây ra các vụ xâm nhập trong các sự cố do nhà phát triển gây ra.289290### Điều KHÔNG nên Làm291292```typescript293// NEVER do this294const API_KEY = "sk-1234567890abcdef";295const DB_PASSWORD = "supersecret123";296297const client = new Client({298 connectionString: `postgres://admin:${DB_PASSWORD}@db.example.com/prod`299});300```301302### Điều Nên Làm Thay Thế303304```typescript305// Use environment variables306const client = new Client({307 connectionString: process.env.DATABASE_URL308});309310// Or use a secret manager311import { SecretManagerServiceClient } from '@google-cloud/secret-manager';312313const client = new SecretManagerServiceClient();314const [version] = await client.accessSecretVersion({315 name: 'projects/my-project/secrets/db-password/versions/latest',316});317const dbPassword = version.payload?.data?.toString();318```319320### Phân cấp Quản lý Secret321322```mermaid323graph TD324 A[Secret Manager\nAWS Secrets Manager\nGCP Secret Manager\nHashiCorp Vault] --> B[Best: Rotated, audited, centralized]325 C[Environment Variables\nInjected at deploy time] --> D[Good: Not in code, but static]326 E[.env files\nWith .gitignore] --> F[Acceptable: Local development only]327 G[Hard-coded in source] --> H[NEVER: Instant breach risk]328329 style A fill:#d4edda330 style C fill:#fff3cd331 style E fill:#ffeeba332 style G fill:#f8d7da333```334335## OWASP Top 10: Tham khảo Nhanh336337Mọi nhà phát triển đều nên biết OWASP Top 10. Phiên bản tóm tắt:338339| # | Lỗ hổng | Mô tả | Phòng ngừa |340|---|--------------|-----------|------------|341| 1 | **Broken Access Control** | Người dùng truy cập tài nguyên không được phép | Từ chối mặc định, xác thực phía server |342| 2 | **Cryptographic Failures** | Mã hóa yếu, dữ liệu dạng plaintext | Sử dụng thuật toán mạnh (AES-256, bcrypt), TLS mọi nơi |343| 3 | **Injection** | SQL, NoSQL, OS command injection | Parameterized query, kiểm tra input |344| 4 | **Insecure Design** | Kiến trúc có lỗ hổng | Threat modeling, secure design pattern |345| 5 | **Security Misconfiguration** | Thông tin đăng nhập mặc định, cloud bucket để mở | Giá trị mặc định cứng hóa, kiểm tra config tự động |346| 6 | **Vulnerable Components** | CVE đã biết trong dependency | SCA scanning, cập nhật thường xuyên |347| 7 | **Auth Failures** | Mật khẩu yếu, session bị hỏng | MFA, rate limiting, quản lý session an toàn |348| 8 | **Data Integrity Failures** | Bản cập nhật chưa ký, CI/CD không tin cậy | Code signing, SBOM, pipeline integrity |349| 9 | **Logging Failures** | Không có audit trail | Structured logging, cảnh báo bất thường |350| 10 | **SSRF** | Server-side request forgery | Allowlist URL đầu ra, kiểm tra input |351352## Workflow Bảo mật GitHub Actions Hoàn chỉnh353354Một workflow sẵn sàng cho production kết hợp tất cả những điều trên:355356```yaml357# .github/workflows/security.yml358name: Security Pipeline359on:360 pull_request:361 branches: [main]362 push:363 branches: [main]364365permissions:366 contents: read367 security-events: write368369jobs:370 secrets-scan:371 name: Secret Detection372 runs-on: ubuntu-latest373 steps:374 - uses: actions/checkout@v4375 with:376 fetch-depth: 0377 - uses: gitleaks/gitleaks-action@v2378 env:379 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}380381 sast:382 name: Static Analysis (SAST)383 runs-on: ubuntu-latest384 steps:385 - uses: actions/checkout@v4386 - uses: semgrep/semgrep-action@v1387 with:388 config: p/owasp-top-ten p/typescript p/nodejs389390 dependency-audit:391 name: Dependency Scan (SCA)392 runs-on: ubuntu-latest393 steps:394 - uses: actions/checkout@v4395 - uses: actions/setup-node@v4396 with:397 node-version: 22398 - run: npm ci399 - run: npm audit --audit-level=high400 - uses: snyk/actions/node@master401 env:402 SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}403 with:404 args: --severity-threshold=high405 continue-on-error: true406407 container-scan:408 name: Container Scan409 runs-on: ubuntu-latest410 needs: [sast, dependency-audit]411 steps:412 - uses: actions/checkout@v4413 - run: docker build -t app:${{ github.sha }} .414 - uses: aquasecurity/trivy-action@master415 with:416 image-ref: app:${{ github.sha }}417 severity: CRITICAL,HIGH418 exit-code: '1'419420 sbom:421 name: SBOM Generation422 runs-on: ubuntu-latest423 needs: [container-scan]424 steps:425 - uses: actions/checkout@v4426 - uses: anchore/sbom-action@v0427 with:428 format: spdx-json429 output-file: sbom.spdx.json430```431432```mermaid433graph TD434 PR[Pull Request] --> S1[Secret Detection]435 PR --> S2[SAST - Semgrep]436 PR --> S3[SCA - Snyk + npm audit]437 S2 --> S4[Container Scan - Trivy]438 S3 --> S4439 S4 --> S5[SBOM Generation]440 S5 --> Deploy[Deploy]441442 S1 -.- F1[Block if secrets found]443 S2 -.- F2[Block on critical vulns]444 S3 -.- F3[Block on high severity]445 S4 -.- F4[Block on critical CVEs]446```447448## Chỉ số Cần Theo dõi449450Làm sao biết chương trình DevSecOps của bạn có hiệu quả? Theo dõi các chỉ số này:451452- **Thời gian khắc phục trung bình (MTTR)**: tốc độ sửa lỗ hổng sau khi phát hiện453- **Tỷ lệ lỗ hổng thoát ra**: phần trăm lỗ hổng đến được production454- **Tỷ lệ false positive**: quá nhiều false positive dẫn đến mệt mỏi cảnh báo và bỏ qua các cảnh báo455- **Độ mới của dependency**: tuổi trung bình của dependency (càng cũ càng có khả năng có CVE đã biết)456- **Độ phủ SBOM**: phần trăm dự án có SBOM cập nhật457458## Bắt đầu: Lộ trình Thực tế459460Đừng cố làm tất cả mọi thứ cùng một lúc. Cách tiếp cận theo giai đoạn sẽ hiệu quả hơn:461462```mermaid463flowchart TD464 A[Week 1-2: Foundations] --> B[Week 3-4: CI/CD Integration]465 B --> C[Month 2: Container Security]466 C --> D[Month 3+: Advanced]467468 A --> A1[Add Gitleaks pre-commit hooks]469 A --> A2[Enable npm audit in CI]470 A --> A3[Add .gitignore for .env files]471472 B --> B1[Add Semgrep to GitHub Actions]473 B --> B2[Add Snyk dependency scanning]474 B --> B3[Set up SARIF upload to GitHub]475476 C --> C1[Add Trivy container scanning]477 C --> C2[Harden Dockerfiles]478 C --> C3[Generate SBOMs]479480 D --> D1[Secret manager integration]481 D --> D2[Runtime protection - DAST]482 D --> D3[Policy as code - OPA]483```484485## Kết luận486487DevSecOps không phải là thêm nhiều công cụ hơn vào pipeline - mà là làm cho bảo mật trở thành một phần tự nhiên trong cách bạn xây dựng phần mềm. Mục tiêu không phải chặn mọi PR bằng cảnh báo bảo mật mà là cung cấp phản hồi nhanh cho nhà phát triển để họ có thể sửa lỗi khi code còn mới trong đầu.488489Bắt đầu từ những điều cơ bản: pre-commit hooks cho secret, dependency scanning trong CI và container scanning cho Docker image. Sau đó cải tiến dần dựa trên nhu cầu của đội.490491Bảo mật không phải là một tính năng bạn phát hành một lần. Đó là một thực hành bạn xây dựng vào mọi commit.492493> **Danh sách Kiểm tra Khởi đầu DevSecOps:**494>495> - [x] Cài đặt Gitleaks pre-commit hooks496> - [x] Thêm .env và các file secret vào .gitignore497> - [x] Tích hợp Semgrep SAST vào CI pipeline498> - [x] Sử dụng Snyk hoặc npm audit để quét dependency499> - [x] Sử dụng Trivy để quét container image500> - [x] Sử dụng non-root user trong Dockerfile501> - [x] Lưu secret trong environment variable hoặc secret manager502> - [x] Tạo SBOM mỗi lần release503> - [x] Toàn đội nhận thức về OWASP Top 10504
:DevSecOps cho Nhà phát triển: Hướng dẫn Thực hành Shift-Left Securitylines 1-504 (END) — press q to close