diff --git a/.gitea/workflows/quality.yml b/.gitea/workflows/quality.yml index 0ee9cd4..a96d719 100644 --- a/.gitea/workflows/quality.yml +++ b/.gitea/workflows/quality.yml @@ -1,7 +1,8 @@ name: quality # Reusable Quality-Gate. Scans laufen per DEFAULT (opt-out via skip_*), # Sprach-Linter opt-in (python/node/php). Report-only per Default; -# blocking=true macht SAST/Vuln/Lint hart. Secrets sind IMMER hart. +# blocking=true macht SAST/Vuln/Lint hart. Secrets sind IMMER hart +# (betterleaks - Nachfolger von gitleaks; gitleaks ist feature-frozen). # Runner=catthehacker (Debian, PEP668) -> pip mit --break-system-packages. # KEINE Docker-Hub-Pulls -> Tools via GitHub-Release/pip. on: @@ -22,14 +23,46 @@ jobs: steps: - uses: actions/checkout@v4 with: { fetch-depth: 0 } - - name: gitleaks (Secrets = immer blockierend) + - name: betterleaks (Secrets = immer blockierend) run: | set -eo pipefail - GLV=$(curl -fsSL -o /dev/null -w '%{url_effective}' https://github.com/gitleaks/gitleaks/releases/latest | sed 's#.*/tag/v##') - [ -n "$GLV" ] || GLV=8.21.2 - echo "::notice::gitleaks v$GLV" - curl -fsSL "https://github.com/gitleaks/gitleaks/releases/download/v${GLV}/gitleaks_${GLV}_linux_x64.tar.gz" | tar -xz -C /tmp gitleaks - /tmp/gitleaks detect --source . --redact --no-banner --exit-code 1 + BLV=$(curl -fsSL -o /dev/null -w '%{url_effective}' https://github.com/betterleaks/betterleaks/releases/latest | sed 's#.*/tag/v##') + [ -n "$BLV" ] || BLV=1.8.1 + echo "::notice::betterleaks v$BLV" + curl -fsSL "https://github.com/betterleaks/betterleaks/releases/download/v${BLV}/betterleaks_${BLV}_linux_x64.tar.gz" | tar -xz -C /tmp betterleaks + + # Zentrale Richtlinie: betterleaks-Standardregeln plus Ausschluss von + # strukturellem Rauschen (Beispiel-Dateien, Uebersetzungen, Abhaengigkeiten, + # Build-Artefakte). Echte Funde in .env(.prod)/docker-compose/Code/Config + # bleiben hart und lassen den Job fehlschlagen. + cat > /tmp/betterleaks.toml <<'BE_CFG' + [extend] + useDefault = true + + [allowlist] + description = "digiflo: strukturelles Rauschen (Beispiele, i18n, Abhaengigkeiten, Build)" + paths = [ + '''(?:^|/)node_modules(?:/.*)?$''', + '''(?:^|/)vendor(?:/.*)?$''', + '''(?:^|/)(?:dist|build|coverage|\.next|\.nuxt)(?:/.*)?$''', + '''(?:^|/)(?:package-lock\.json|pnpm-lock\.yaml|yarn\.lock)$''', + '''(?i)(?:^|/)[^/]*\.(?:example|sample|template|dist|bak|orig)$''', + '''(?i)\.env\.(?:example|sample|template)$''', + '''(?i)(?:^|/)(?:i18n|locales?|lang)(?:/.*)?\.json$''', + '''(?i)(?:^|/)templates?/.*\.(?:json|ya?ml|php|ts|js|py|sh)$''', + '''(?i)(?:^|/)(?:__snapshots__|testdata|fixtures?)(?:/.*)?$''', + ] + stopwords = [ + "example", "sample", "placeholder", "changeme", "change_me", + "your_password", "your-password", "dummy", "redacted", "not_a_real", + ] + BE_CFG + + # Repo-eigene Richtlinie hat Vorrang. Akzeptierte Altlasten werden per + # .betterleaksignore im Repo-Root hinterlegt (Fingerprint je Zeile). + CFG=/tmp/betterleaks.toml + if [ -f .betterleaks.toml ]; then CFG=.betterleaks.toml; fi + /tmp/betterleaks git . --config "$CFG" --redact --no-banner --exit-code 1 sast: if: ${{ !inputs.skip_sast }} diff --git a/USAGE.md b/USAGE.md index 454f0a7..6651527 100644 --- a/USAGE.md +++ b/USAGE.md @@ -1,8 +1,30 @@ # ci-templates — org-weites Quality-Gate -Reusable Workflow fuer alle Orgs. Scans (gitleaks/semgrep/trivy/actionlint) laufen per +Reusable Workflow fuer alle Orgs. Scans (betterleaks/semgrep/trivy/actionlint) laufen per **Default**; Sprach-Linter (python/node/php) sind **opt-in**. **Report-only** per Default, -`blocking: true` macht SAST/Vuln/Lint zum harten Gate. **Secrets (gitleaks) sind IMMER hart.** +`blocking: true` macht SAST/Vuln/Lint zum harten Gate. **Secrets (betterleaks) sind IMMER hart.** + +## Secret-Scan: betterleaks statt gitleaks (seit 2026-09-11) +gitleaks ist **feature-frozen** (letztes Release 03/2026, nur noch Security-Patches); +die Maintainer inkl. Original-Autor entwickeln **betterleaks** weiter (v1.8.1, MIT, +aktive Releases). betterleaks findet in denselben Repos deutlich mehr als gitleaks +(Bsp.: 34 -> 58 Treffer), kann Secrets per `validate` auf "noch aktiv?" pruefen und +filtert Rauschen per Expr-Regeln. + +Zentrale Richtlinie liegt inline im Job `secret-scan` (`[extend] useDefault = true` ++ `[allowlist]`): Beispiel-Dateien (`.env.example`, `*.sample`, `*.template`), +Uebersetzungen (`i18n/*.json`), Abhaengigkeiten/Build (`node_modules`, `vendor`, +`dist`, Lockfiles) und Fixtures werden nicht gemeldet. **Nicht** ausgeschlossen: +`.env`/`.env.prod`, `docker-compose*`, Code und echte Config-Dateien - dort laesst +ein Fund den Gate fehlschlagen. + +Pro Repo: +- `.betterleaks.toml` im Repo-Root **ersetzt** die zentrale Richtlinie (Vorrang). +- `.betterleaksignore` im Repo-Root nimmt einzeln akzeptierte Altlasten auf; + Format = `Fingerprint` aus dem JSON-Report: `:::`. + Details zum Fund liefert der Job-Log; Fingerprints lokal per + `betterleaks git . --report-format json --report-path r.json`. +- Inline-Ausnahme direkt im Code: Kommentar `betterleaks:allow` in der Zeile. ## WICHTIG — Sichtbarkeit (Gitea-Limitation, verifiziert 2026-08-25) Private reusable Workflows koennen von anderen Repos NICHT gelesen werden