spinny:~/writing $ less devsecops-shift-left-security-guide.md
12Kerentanan yang ditemui semasa menulis kod memerlukan beberapa minit sahaja untuk diperbaiki oleh pembangun perisian. Kerentanan yang sama jika ditangkap di production memerlukan satu sprint penuh. Dan jika penyerang menemuinya terlebih dahulu, kosnya berjuta-juta. Inilah hujah teras di sebalik **shift-left security** - memindahkan pemeriksaan keselamatan seawal mungkin dalam kitaran hayat pembangunan.34DevSecOps mengambil idea ini dan mengubahnya menjadi amalan: keselamatan bukan fasa berasingan di penghujung tetapi proses berterusan yang dijalin ke setiap peringkat pembangunan, dari baris kod pertama hingga deployment production.56## Kos Keselamatan Lewat78Laporan Cost of a Data Breach IBM telah menunjukkan secara konsisten bahawa kos membaiki isu keselamatan meningkat secara eksponen semakin lewat ia ditangkap:910| Peringkat | Kos Pembaikan | Masa Pembaikan |11|-------|------------|-------------|12| **IDE / Local Dev** | Minit | Saat hingga minit |13| **Code Review / PR** | Jam | Minit hingga jam |14| **CI/CD Pipeline** | Hari | Jam hingga hari |15| **Staging / QA** | Minggu | Hari |16| **Production** | Bulan | Minggu hingga bulan |17| **Post-breach** | Jutaan ($) | Bulan hingga tahun |1819Kesimpulannya jelas: setiap peringkat yang anda pindahkan keselamatan lebih awal menjimatkan satu orde magnitud dalam kos dan masa.2021## Pipeline DevSecOps2223Pipeline DevSecOps yang matang mengintegrasikan pemeriksaan keselamatan di setiap peringkat: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```4243Mari kita huraikan setiap peringkat dengan alat dan konfigurasi yang konkrit.4445## Peringkat 1: Keselamatan di IDE4647Gelung maklum balas terpantas. Tangkap kerentanan sebelum anda menyimpan fail.4849### Alat yang Disyorkan5051- **Semgrep**: analisis statik ringan dengan peraturan komuniti untuk kerentanan OWASP52- **Snyk IDE Extension**: pengimbasan kerentanan dependency masa nyata53- **GitLens + GitLeaks**: kesan secrets dalam editor anda54- **ESLint Security Plugins**: `eslint-plugin-security` untuk Node.js, `eslint-plugin-no-unsanitized` untuk DOM XSS5556### Contoh: Konfigurasi 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## Peringkat 2: Pre-commit Hooks7778Barisan pertahanan kedua. Berjalan secara automatik sebelum setiap commit, menghalang kod berbahaya daripada memasuki repositori.7980### Gitleaks: Tangkap Secrets Sebelum Sampai ke Git8182Kesalahan keselamatan paling biasa dalam codebase ialah meng-commit secrets - API keys, database passwords, tokens. Sebaik sahaja secret masuk ke git history, ia amat sukar untuk dikeluarkan sepenuhnya (walaupun dengan force pushes, fork dan cache mungkin masih menyimpannya).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```9899Pasang dan aktifkan:100101```bash102pip install pre-commit103pre-commit install104```105106Kini setiap `git commit` mengimbas secara automatik untuk secrets yang bocor dan kerentanan biasa. Jika sesuatu ditemui, commit akan disekat.107108### Peraturan Gitleaks Tersuai109110Anda boleh menambah corak tersuai untuk secrets organisasi anda: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## Peringkat 3: Keselamatan CI/CD Pipeline124125Di sinilah kerja berat berlaku. Pipeline CI anda harus menjalankan pelbagai imbasan keselamatan pada setiap pull request.126127### SAST (Static Application Security Testing)128129Alat SAST menganalisis kod sumber tanpa melaksanakannya, mencari corak yang menunjukkan kerentanan.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```160161Set peraturan `p/owasp-top-ten` Semgrep menangkap kerentanan paling biasa: SQL injection, XSS, SSRF, path traversal, insecure deserialization, dan banyak lagi.162163### SCA (Software Composition Analysis)164165SCA mengimbas dependency anda untuk kerentanan yang diketahui. Ini amat kritikal - lebih 80% kod aplikasi moden datang dari dependency open-source.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### Container Security dengan Trivy186187Jika anda membina Docker images, mengimbasnya untuk kerentanan adalah penting. **Trivy** ialah container scanner open-source paling popular.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### Penjanaan SBOM215216**Software Bill of Materials (SBOM)** ialah inventori lengkap setiap komponen dalam aplikasi anda. Semakin diperlukan oleh rangka kerja pematuhan dan peraturan kerajaan (US Executive Order on Cybersecurity mewajibkan SBOM untuk perisian persekutuan).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## Peringkat 4: Docker Images yang Selamat239240Docker image production harus mengikuti prinsip keistimewaan minimum. Inilah rupa Dockerfile yang diperkukuh: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```277278Amalan utama:2792801. **Gunakan multi-stage builds**: peringkat builder mempunyai dev dependencies; peringkat runner hanya mempunyai kod production2812. **Jangan jalankan sebagai root**: cipta pengguna bukan root dan bertukar kepadanya2823. **Gunakan Alpine images**: permukaan serangan lebih kecil (lebih sedikit pakej dipasang secara lalai)2834. **Pin versi image**: `node:22-alpine` dan bukannya `node:latest` untuk mengelak serangan rantaian bekalan2845. **Gunakan `npm ci`**: pemasangan deterministik daripada fail kunci, bukan `npm install`285286## Peringkat 5: Pengurusan Secret287288Hard-coded secrets ialah punca nombor satu pelanggaran dalam insiden yang disebabkan pembangun perisian.289290### Apa yang TIDAK Boleh Dilakukan291292```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### Apa yang Perlu Dilakukan Sebaliknya303304```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### Hierarki Pengurusan 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: Rujukan Pantas336337Setiap pembangun perisian harus mengetahui OWASP Top 10. Versi ringkas:338339| # | Kerentanan | Apa Itu | Pencegahan |340|---|--------------|-----------|------------|341| 1 | **Broken Access Control** | Pengguna mengakses sumber yang tidak sepatutnya | Tolak secara lalai, sahkan di sisi pelayan |342| 2 | **Cryptographic Failures** | Penyulitan lemah, data teks biasa | Guna algoritma kuat (AES-256, bcrypt), TLS di mana-mana |343| 3 | **Injection** | SQL, NoSQL, OS command injection | Parameterized queries, pengesahan input |344| 4 | **Insecure Design** | Seni bina yang cacat | Threat modeling, corak reka bentuk selamat |345| 5 | **Security Misconfiguration** | Kelayakan lalai, cloud buckets terbuka | Lalai yang diperkukuh, audit konfigurasi automatik |346| 6 | **Vulnerable Components** | CVE yang diketahui dalam dependency | Imbasan SCA, kemas kini berkala |347| 7 | **Auth Failures** | Kata laluan lemah, sesi rosak | MFA, pengehadan kadar, pengurusan sesi selamat |348| 8 | **Data Integrity Failures** | Kemas kini tidak ditandatangani, CI/CD tidak dipercayai | Tandatangan kod, SBOM, integriti pipeline |349| 9 | **Logging Failures** | Tiada jejak audit | Logging berstruktur, amaran pada anomali |350| 10 | **SSRF** | Server-side request forgery | Senarai putih URL keluar, sahkan input |351352## Aliran Kerja GitHub Actions Security Lengkap353354Aliran kerja lengkap dan sedia production yang menggabungkan semua di atas: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## Metrik untuk Dijejaki449450Bagaimana anda tahu program DevSecOps anda berjaya? Jejaki metrik-metrik ini:451452- **Mean time to remediate (MTTR)**: seberapa cepat anda membaiki kerentanan selepas pengesanan453- **Vulnerability escape rate**: peratusan kerentanan yang sampai ke production454- **False positive rate**: terlalu banyak positif palsu menyebabkan keletihan amaran dan amaran yang diabaikan455- **Dependency freshness**: purata umur dependency anda (lebih lama = lebih berkemungkinan mempunyai CVE yang diketahui)456- **SBOM coverage**: peratusan projek dengan SBOM yang terkini457458## Bermula: Peta Jalan Praktikal459460Jangan cuba melaksanakan semuanya sekaligus. Pendekatan berfasa berfungsi dengan lebih baik: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## Kesimpulan486487DevSecOps bukan tentang menambah lebih banyak alat ke pipeline anda - ia tentang menjadikan keselamatan sebahagian semula jadi daripada cara anda membina perisian. Matlamatnya bukan menyekat setiap PR dengan amaran keselamatan tetapi memberi maklum balas pantas kepada pembangun supaya mereka boleh membaiki isu semasa kod masih segar dalam ingatan mereka.488489Mulakan dengan asas: pre-commit hooks untuk secrets, dependency scanning dalam CI, dan container scanning untuk Docker images. Kemudian buat iterasi berdasarkan apa yang diperlukan pasukan anda.490491Keselamatan bukan ciri yang anda hantar sekali. Ia adalah amalan yang anda bina ke dalam setiap commit.492493> **DevSecOps Starter Checklist:**494>495> - [x] Gitleaks pre-commit hooks dipasang496> - [x] Fail .env dan secret dalam .gitignore497> - [x] Semgrep SAST dalam CI pipeline498> - [x] Snyk atau npm audit untuk imbasan dependency499> - [x] Trivy untuk imbasan container image500> - [x] Pengguna bukan root dalam Dockerfiles501> - [x] Secrets dalam environment variables atau secret manager502> - [x] Penjanaan SBOM pada setiap keluaran503> - [x] Kesedaran OWASP Top 10 di seluruh pasukan504
:DevSecOps untuk Pembangun Perisian: Panduan Praktikal Shift-Left Securitylines 1-504 (END) — press q to close