name: "Semgrep — SAST" description: >- Escaneo estático de código, modo auditoría (no bloquea) por default — mismo criterio que los 3 pipelines reales: primera vuelta para revisar hallazgos en conjunto antes de decidir qué reglas deberían bloquear. Corre nativo en un venv, no como contenedor aparte — el runner de Gitea ya ejecuta cada job dentro de un contenedor propio (sibling containers hablando con el Docker del host, no Docker-in-Docker), así que un "docker run -v" desde acá monta rutas que no existen en el host real y falla con "read-only file system". inputs: target: description: "Directorio a escanear." required: true configs: description: >- Rulesets de Semgrep separados por coma, ej. "p/typescript,p/react,p/nextjs,p/security-audit". Elegí el combo según tu stack real — no copies el mismo set para todo (ver README de este snippet, tabla de qué usa cada arquetipo). required: true semgrep_version: description: "Versión de Semgrep a instalar." required: false default: "1.173.0" fail_on_findings: description: "'true' para bloquear el pipeline si hay hallazgos. Default 'false' (auditoría)." required: false default: "false" runs: using: composite steps: - name: Instalar Semgrep shell: bash run: | set -euo pipefail python3 -m venv /tmp/semgrep-venv /tmp/semgrep-venv/bin/pip install --quiet "semgrep==${{ inputs.semgrep_version }}" /tmp/semgrep-venv/bin/semgrep --version - name: Escaneo SAST (Semgrep) shell: bash run: | set -euo pipefail CONFIG_ARGS=() IFS=',' read -ra CONFIGS <<< "${{ inputs.configs }}" for cfg in "${CONFIGS[@]}"; do CONFIG_ARGS+=(--config="${cfg}") done ERROR_FLAG=() if [ "${{ inputs.fail_on_findings }}" = "true" ]; then ERROR_FLAG=(--error) fi /tmp/semgrep-venv/bin/semgrep scan \ "${CONFIG_ARGS[@]}" \ "${ERROR_FLAG[@]}" \ --json \ --output=semgrep-report.json \ "${{ inputs.target }}" echo "=== Resumen Semgrep ===" /tmp/semgrep-venv/bin/python -c " import json data = json.load(open('semgrep-report.json')) results = data.get('results', []) print(f'Hallazgos: {len(results)}') for r in results: print(f\" [{r['extra']['severity']}] {r['check_id']} - {r['path']}:{r['start']['line']}\") " - name: Publicar reporte de Semgrep if: always() uses: actions/upload-artifact@v3 with: name: semgrep-report path: semgrep-report.json if-no-files-found: ignore