spinny:~/writing $ less devsecops-shift-left-security-guide.md
12Una vulnerabilidad encontrada mientras se escribe codigo le cuesta a un desarrollador minutos en corregirla. La misma vulnerabilidad detectada en produccion cuesta un sprint. Y si un atacante la encuentra primero, cuesta millones. Este es el argumento central de la **shift-left security** - mover los controles de seguridad lo mas temprano posible en el ciclo de vida del desarrollo.34DevSecOps toma esta idea y la convierte en una practica: la seguridad no es una fase separada al final, sino un proceso continuo integrado en cada etapa del desarrollo, desde la primera linea de codigo hasta el despliegue en produccion.56## El coste de la seguridad tardia78El informe Cost of a Data Breach de IBM ha demostrado consistentemente que el coste de corregir problemas de seguridad crece exponencialmente cuanto mas tarde se detectan:910| Etapa | Coste de correccion | Tiempo de correccion |11|-------|---------------------|----------------------|12| **IDE / Desarrollo local** | Minutos | Segundos a minutos |13| **Code review / PR** | Horas | Minutos a horas |14| **Pipeline CI/CD** | Dias | Horas a dias |15| **Staging / QA** | Semanas | Dias |16| **Produccion** | Meses | Semanas a meses |17| **Post-breach** | Millones ($) | Meses a anos |1819La conclusion es clara: cada etapa en la que adelantas la seguridad ahorra un orden de magnitud en coste y tiempo.2021## La pipeline DevSecOps2223Una pipeline DevSecOps madura integra controles de seguridad en cada etapa: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```4243Desglosemos cada etapa con herramientas y configuraciones concretas.4445## Etapa 1: seguridad en el IDE4647El ciclo de feedback mas rapido. Detecta vulnerabilidades antes incluso de guardar el archivo.4849### Herramientas recomendadas5051- **Semgrep**: analisis estatico ligero con reglas de la comunidad para vulnerabilidades OWASP52- **Snyk IDE Extension**: escaneo en tiempo real de vulnerabilidades en dependencias53- **GitLens + GitLeaks**: detecta secrets en tu editor54- **ESLint Security Plugins**: `eslint-plugin-security` para Node.js, `eslint-plugin-no-unsanitized` para DOM XSS5556### Ejemplo: configuracion ESLint para seguridad5758```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## Etapa 2: Pre-commit Hooks7778La segunda linea de defensa. Se ejecutan automaticamente antes de cada commit, bloqueando codigo peligroso para que no entre en el repositorio.7980### Gitleaks: intercepta secrets antes de que lleguen a Git8182El error de seguridad mas comun en los codebases es hacer commit de secrets - claves API, contrasenas de bases de datos, tokens. Una vez que un secret llega al historial de git, es extremadamente dificil eliminarlo por completo (incluso con force pushes, los forks y caches pueden retenerlo).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```9899Instala y activa:100101```bash102pip install pre-commit103pre-commit install104```105106Ahora cada `git commit` escanea automaticamente en busca de secrets filtrados y vulnerabilidades comunes. Si se encuentra algo, el commit se bloquea.107108### Reglas personalizadas de Gitleaks109110Puedes agregar patrones personalizados para los secrets de tu organizacion: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## Etapa 3: seguridad de la pipeline CI/CD124125Aqui es donde ocurre el trabajo pesado. Tu pipeline CI deberia ejecutar multiples escaneos de seguridad en cada pull request.126127### SAST (Static Application Security Testing)128129Las herramientas SAST analizan el codigo fuente sin ejecutarlo, buscando patrones que indican vulnerabilidades.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```160161El ruleset `p/owasp-top-ten` de Semgrep detecta las vulnerabilidades mas comunes: SQL injection, XSS, SSRF, path traversal, deserializacion insegura y mas.162163### SCA (Software Composition Analysis)164165El SCA escanea tus dependencias en busca de vulnerabilidades conocidas. Esto es fundamental - mas del 80 % del codigo de las aplicaciones modernas proviene de dependencias 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### Seguridad de contenedores con Trivy186187Si construyes imagenes Docker, escanearlas en busca de vulnerabilidades es esencial. **Trivy** es el scanner de contenedores open-source mas 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### Generacion de SBOM215216Una **Software Bill of Materials (SBOM)** es un inventario completo de cada componente de tu aplicacion. Es cada vez mas requerida por los marcos de cumplimiento y las regulaciones gubernamentales (la Orden Ejecutiva de EE.UU. sobre Ciberseguridad exige SBOM para el software federal).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## Etapa 4: imagenes Docker seguras239240Una imagen Docker de produccion deberia seguir el principio de minimo privilegio. Asi es como luce un Dockerfile reforzado: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```277278Practicas clave:2792801. **Usa builds multi-stage**: el stage builder tiene las dependencias de desarrollo; el stage runner solo tiene el codigo de produccion2812. **No ejecutes como root**: crea un usuario no-root y cambia a el2823. **Usa imagenes Alpine**: superficie de ataque reducida (menos paquetes instalados por defecto)2834. **Fija las versiones de las imagenes**: `node:22-alpine` en lugar de `node:latest` para evitar ataques a la supply chain2845. **Usa `npm ci`**: instalaciones deterministas desde el lock file, no `npm install`285286## Etapa 5: gestion de secrets287288Los secrets hard-coded son la causa numero uno de las brechas en los incidentes provocados por desarrolladores.289290### Que NO hacer291292```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### Que hacer en su lugar303304```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### Jerarquia de la gestion de secrets321322```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## El OWASP Top 10: referencia rapida336337Todo desarrollador deberia conocer el OWASP Top 10. Version resumida:338339| # | Vulnerabilidad | Que es | Prevencion |340|---|----------------|--------|------------|341| 1 | **Broken Access Control** | Usuarios accediendo a recursos no autorizados | Denegar por defecto, validar en el servidor |342| 2 | **Cryptographic Failures** | Cifrado debil, datos en texto plano | Usar algoritmos robustos (AES-256, bcrypt), TLS en todas partes |343| 3 | **Injection** | SQL, NoSQL, OS command injection | Consultas parametrizadas, validacion de entradas |344| 4 | **Insecure Design** | Arquitectura con fallos | Threat modeling, secure design patterns |345| 5 | **Security Misconfiguration** | Credenciales por defecto, buckets cloud abiertos | Valores por defecto reforzados, auditorias automatizadas de configuracion |346| 6 | **Vulnerable Components** | CVE conocidas en dependencias | Escaneo SCA, actualizaciones regulares |347| 7 | **Auth Failures** | Contrasenas debiles, sesiones comprometidas | MFA, rate limiting, gestion segura de sesiones |348| 8 | **Data Integrity Failures** | Actualizaciones no firmadas, CI/CD no confiable | Code signing, SBOM, integridad de la pipeline |349| 9 | **Logging Failures** | Sin pista de auditoria | Logging estructurado, alertas sobre anomalias |350| 10 | **SSRF** | Server-side request forgery | Allowlist de URLs salientes, validacion de entradas |351352## Workflow completo de seguridad con GitHub Actions353354Un workflow completo y listo para produccion que combina todo lo anterior: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## Metricas a seguir449450Como saber si tu programa DevSecOps esta funcionando? Monitorea estas metricas:451452- **Mean time to remediate (MTTR)**: la rapidez con la que corriges vulnerabilidades tras la deteccion453- **Vulnerability escape rate**: porcentaje de vulnerabilidades que llegan a produccion454- **False positive rate**: demasiados falsos positivos llevan a fatiga de alertas y advertencias ignoradas455- **Dependency freshness**: edad promedio de tus dependencias (mas antiguas = mas probabilidad de CVE conocidas)456- **SBOM coverage**: porcentaje de proyectos con SBOM actualizadas457458## Para empezar: una hoja de ruta practica459460No intentes implementar todo de una vez. Un enfoque gradual funciona mejor: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## Conclusion486487DevSecOps no consiste en agregar mas herramientas a tu pipeline - se trata de hacer que la seguridad sea una parte natural de como construyes software. El objetivo no es bloquear cada PR con advertencias de seguridad, sino dar a los desarrolladores feedback rapido para que puedan corregir los problemas mientras el codigo aun esta fresco en su mente.488489Empieza con lo basico: pre-commit hooks para secrets, dependency scanning en la CI y container scanning para imagenes Docker. Luego itera segun las necesidades de tu equipo.490491La seguridad no es una funcionalidad que se entrega una sola vez. Es una practica que se integra en cada commit.492493> **Checklist inicial DevSecOps:**494>495> - [x] Pre-commit hooks Gitleaks instalados496> - [x] Archivos .env y secrets en el .gitignore497> - [x] Semgrep SAST en la pipeline CI498> - [x] Snyk o npm audit para dependency scanning499> - [x] Trivy para el escaneo de imagenes de contenedores500> - [x] Usuario no-root en los Dockerfiles501> - [x] Secrets en variables de entorno o secret manager502> - [x] Generacion de SBOM en cada release503> - [x] Conocimiento del OWASP Top 10 en todo el equipo504
:DevSecOps para desarrolladores: una guia practica de shift-left securitylines 1-504 (END) — press q to close