From 5f8009e8445582daa3f923d681543b4db1bc7ef3 Mon Sep 17 00:00:00 2001 From: Benjamin Admin Date: Sun, 21 Jun 2026 14:37:54 +0200 Subject: [PATCH] fix(security): remove hardcoded Qdrant key + allowlist doc false-positives MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit secret-scan (gitleaks) had never run on a PR (broken checkout). A real Qdrant dev API key was hardcoded in 4 pre-existing files; removed in favour of env / gitea-secret references (scripts read QDRANT_API_KEY from os.environ; rag-ingest workflow references a gitea Actions secret). The remaining ~52 findings are doc curl examples + .env.example placeholders + a rule_key identifier, allowlisted in .gitleaks.toml (default ruleset kept). gitleaks now reports 0 findings. ACTION REQUIRED: rotate the Qdrant dev API key — the leaked value is in git history. Co-Authored-By: Claude Opus 4.7 --- .gitea/workflows/rag-ingest.yaml | 2 +- .gitleaks.toml | 21 +++++++++++++++++++++ scripts/cleanup-qdrant-duplicates.py | 3 ++- scripts/migrate-qdrant.py | 3 ++- scripts/qa/delete_gpsr_prod.py | 3 ++- 5 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 .gitleaks.toml diff --git a/.gitea/workflows/rag-ingest.yaml b/.gitea/workflows/rag-ingest.yaml index e1486539..07fcfa10 100644 --- a/.gitea/workflows/rag-ingest.yaml +++ b/.gitea/workflows/rag-ingest.yaml @@ -74,7 +74,7 @@ jobs: -e "WORK_DIR=/tmp/rag-ingestion" \ -e "RAG_URL=http://bp-core-rag-service:8097/api/v1/documents/upload" \ -e "QDRANT_URL=https://qdrant-dev.breakpilot.ai" \ - -e "QDRANT_API_KEY=z9cKbT74vl1aKPD1QGIlKWfET47VH93u" \ + -e "QDRANT_API_KEY=${{ secrets.QDRANT_API_KEY }}" \ -e "SDK_URL=http://bp-compliance-ai-sdk:8090" \ alpine:3.19 \ sh -c " diff --git a/.gitleaks.toml b/.gitleaks.toml new file mode 100644 index 00000000..8f6944a9 --- /dev/null +++ b/.gitleaks.toml @@ -0,0 +1,21 @@ +# gitleaks configuration. +# Keeps gitleaks' default ruleset and adds an allowlist for known FALSE POSITIVES +# that surfaced once the CI checkout was fixed (secret-scan had never actually run +# on a PR before). Real leaked credentials are removed in code, NOT allowlisted. + +[extend] +useDefault = true + +[allowlist] +description = "Documentation curl examples, env templates, and non-secret identifiers" +paths = [ + # API reference pages — curl examples with placeholder tokens, not real secrets + '''developer-portal/app/api/.*''', + '''developer-portal/app/development/.*''', + # Template env file — placeholder dev values (e.g. breakpilot123) + '''\.env\.example$''', + # Seed data: "rule_key" identifiers, not credentials + '''backend-compliance/compliance/data/template_rule_seed_data\.py$''', + # SDK deploy template — MINIO placeholder password + '''breakpilot-compliance-sdk/packages/cli/src/commands/deploy\.ts$''', +] diff --git a/scripts/cleanup-qdrant-duplicates.py b/scripts/cleanup-qdrant-duplicates.py index e079a5f0..a3180bf5 100644 --- a/scripts/cleanup-qdrant-duplicates.py +++ b/scripts/cleanup-qdrant-duplicates.py @@ -18,6 +18,7 @@ Run with --dry-run to preview deletions without executing. import argparse import json +import os import sys import time import requests @@ -33,7 +34,7 @@ TARGETS = { }, "production": { "url": "https://qdrant-dev.breakpilot.ai", - "api_key": "z9cKbT74vl1aKPD1QGIlKWfET47VH93u", + "api_key": os.environ.get("QDRANT_API_KEY"), }, } diff --git a/scripts/migrate-qdrant.py b/scripts/migrate-qdrant.py index e7242efb..d114acfe 100755 --- a/scripts/migrate-qdrant.py +++ b/scripts/migrate-qdrant.py @@ -6,6 +6,7 @@ Uses persistent HTTP sessions and rate limiting for hosted Qdrant. """ import json +import os import sys import time import requests @@ -13,7 +14,7 @@ from urllib.parse import urljoin SOURCE_URL = "http://macmini:6333" TARGET_URL = "https://qdrant-dev.breakpilot.ai" -TARGET_API_KEY = "z9cKbT74vl1aKPD1QGIlKWfET47VH93u" +TARGET_API_KEY = os.environ.get("QDRANT_API_KEY", "") BATCH_SIZE = 20 RATE_LIMIT_DELAY = 0.3 # seconds between batches diff --git a/scripts/qa/delete_gpsr_prod.py b/scripts/qa/delete_gpsr_prod.py index 2924e2a0..650d4b58 100644 --- a/scripts/qa/delete_gpsr_prod.py +++ b/scripts/qa/delete_gpsr_prod.py @@ -1,8 +1,9 @@ """Delete eu_2023_988 duplicate from production Qdrant.""" import httpx +import os PROD_URL = "https://qdrant-dev.breakpilot.ai" -HEADERS = {"api-key": "z9cKbT74vl1aKPD1QGIlKWfET47VH93u"} +HEADERS = {"api-key": os.environ.get("QDRANT_API_KEY", "")} # Delete resp = httpx.post(