Context: learn.spikersoft.com is pre-beta (no real users/data), so this is a go-live prerequisite, not an active breach. Today these are dev/test credentials — but the pattern must never reach production, and any secret reused in prod is already burned.
Problem: The entire secret set is committed to git, including the AES master key that would encrypt user PII. There is no production override, so committed values carry straight to prod.
Evidence:
SpikerSoft.Api/appsettings.json:451 — Encryption:MasterKey (wraps every data-encryption key)
Same secrets repeated across ~41 tracked files + SpikerSoft.AI.MCPServer/appsettings.*.json:4
Fix:
Move all secrets to Docker/Swarm secrets or a vault; inject at runtime
Rotate any credential that will be reused in production
Purge from git history (BFG / git-filter-repo)
Add pre-commit + CI secret scanning
Acceptance criteria:
No secrets in any committed appsettings*.json (placeholders only)
Secrets sourced from Swarm secrets/vault at runtime
CI fails on a newly committed secret
Git history scrubbed of the master key & live credentials
Effort: M–L · Prerequisite for the production deployment model (INF-2, this batch).
**Context:** learn.spikersoft.com is pre-beta (no real users/data), so this is a **go-live prerequisite, not an active breach**. Today these are dev/test credentials — but the pattern must never reach production, and any secret reused in prod is already burned.
**Problem:** The entire secret set is committed to git, including the AES master key that would encrypt user PII. There is no production override, so committed values carry straight to prod.
**Evidence:**
- `SpikerSoft.Api/appsettings.json:451` — `Encryption:MasterKey` (wraps every data-encryption key)
- `:268` / `:272` — Keycloak client secrets
- `:295` Stripe · `:446` Twilio · `:413` SMTP · `:307` MSSQL sa · `:212/217` InfluxDB · `:402` Seq
- Same secrets repeated across ~41 tracked files + `SpikerSoft.AI.MCPServer/appsettings.*.json:4`
**Fix:**
- Move all secrets to Docker/Swarm secrets or a vault; inject at runtime
- Rotate any credential that will be reused in production
- Purge from git history (BFG / git-filter-repo)
- Add pre-commit + CI secret scanning
**Acceptance criteria:**
- No secrets in any committed `appsettings*.json` (placeholders only)
- Secrets sourced from Swarm secrets/vault at runtime
- CI fails on a newly committed secret
- Git history scrubbed of the master key & live credentials
**Effort:** M–L · Prerequisite for the production deployment model (INF-2, this batch).
spikerj
added the agentic label 2026-07-05 20:23:42 +00:00
Verified finding — live secrets hardcoded in SpikerSoft.Api/appsettings.json (surfaced while adding webhook-signature validation)
Committed production credentials currently in source (listing keys only, not values):
Twilio:AuthToken — Twilio account auth token (also the key that signs webhook HMACs, so it's security-critical).
Encryption:MasterKey — a base64 AES master key.
InfluxDB:Token / InfluxDashboard:Token — InfluxDB API token (same value in both blocks).
Keycloak:backend-api:secret and Keycloak:health-check:secret — Keycloak client secrets.
Anyone with repo read access has these. Because .NET config layering lets environment variables override appsettings.json, the migration is low-risk per key: inject each as Section__Key env (Docker/Swarm secret), then blank the value in appsettings.json. Rotate every exposed credential after it's out of source (they must be treated as already compromised).
Suggested bounded first slice (no architecture decision needed): pick the highest-risk few (Encryption:MasterKey, Keycloak:*:secret, Twilio:AuthToken) and move them to injected env + blank in source, once the deploy confirms the env vars are actually set (else the app loses the value on boot). I can prep that PR if you confirm the prod deployment already injects — or will inject — these as env/secrets; without that confirmation, blanking them would break boot, so it's the one gate here.
(Context: found while shipping webhook HMAC validation — Twilio #165 (merged), SonarQube #166. Both reference Twilio:AuthToken / a SonarQube secret from config.)
### Verified finding — live secrets hardcoded in `SpikerSoft.Api/appsettings.json` (surfaced while adding webhook-signature validation)
Committed **production** credentials currently in source (listing keys only, not values):
- `Twilio:AuthToken` — Twilio account auth token (also the key that signs webhook HMACs, so it's security-critical).
- `Encryption:MasterKey` — a base64 AES master key.
- `InfluxDB:Token` / `InfluxDashboard:Token` — InfluxDB API token (same value in both blocks).
- `Keycloak:backend-api:secret` and `Keycloak:health-check:secret` — Keycloak client secrets.
Anyone with repo read access has these. Because .NET config layering lets environment variables override `appsettings.json`, the migration is low-risk per key: inject each as `Section__Key` env (Docker/Swarm secret), then blank the value in `appsettings.json`. Rotate every exposed credential after it's out of source (they must be treated as already compromised).
Suggested bounded first slice (no architecture decision needed): pick the highest-risk few (`Encryption:MasterKey`, `Keycloak:*:secret`, `Twilio:AuthToken`) and move them to injected env + blank in source, once the deploy confirms the env vars are actually set (else the app loses the value on boot). I can prep that PR if you confirm the prod deployment already injects — or will inject — these as env/secrets; without that confirmation, blanking them would break boot, so it's the one gate here.
(Context: found while shipping webhook HMAC validation — Twilio #165 (merged), SonarQube #166. Both reference `Twilio:AuthToken` / a SonarQube secret from config.)
Board-sweep status (2026-07-22) — this ticket's notes predate the OpenBao rollout, so catching it up: the epic it seeded (#543/#545/#546) has landed the core: SpikerSoft.Api/appsettings.json now carries blank values for all 12 API credentials (incl. every key the 07-06 comment listed — Twilio:AuthToken, Encryption:MasterKey, Influx tokens, Keycloak client secrets), served from OpenBao with strict fail-fast when Secrets__UseBao=true (merged #546 stage-4, backend 4bcec842). CI secrets are Bao-fetched repo-wide (two AppRole secrets per repo).
Still open before this go-live gate closes: (1) rotation of the previously-committed values — they must be treated as compromised; #600 tracks the Influx token, #633 the dev-environment set; (2) the worker-fleet Bao overlay rollout is ~26 of 60 stacks (#546's remaining batches); (3) plaintext creds in .env-10N files on the shared mount (flagged in #554). Leaving open as the go-live umbrella for those.
Board-sweep status (2026-07-22) — this ticket's notes predate the OpenBao rollout, so catching it up: the epic it seeded (#543/#545/#546) has landed the core: `SpikerSoft.Api/appsettings.json` now carries **blank values for all 12 API credentials** (incl. every key the 07-06 comment listed — Twilio:AuthToken, Encryption:MasterKey, Influx tokens, Keycloak client secrets), served from OpenBao with strict fail-fast when `Secrets__UseBao=true` (merged #546 stage-4, backend `4bcec842`). CI secrets are Bao-fetched repo-wide (two AppRole secrets per repo).
**Still open before this go-live gate closes:** (1) rotation of the previously-committed values — they must be treated as compromised; #600 tracks the Influx token, #633 the dev-environment set; (2) the worker-fleet Bao overlay rollout is ~26 of 60 stacks (#546's remaining batches); (3) plaintext creds in `.env-10N` files on the shared mount (flagged in #554). Leaving open as the go-live umbrella for those.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Context: learn.spikersoft.com is pre-beta (no real users/data), so this is a go-live prerequisite, not an active breach. Today these are dev/test credentials — but the pattern must never reach production, and any secret reused in prod is already burned.
Problem: The entire secret set is committed to git, including the AES master key that would encrypt user PII. There is no production override, so committed values carry straight to prod.
Evidence:
SpikerSoft.Api/appsettings.json:451—Encryption:MasterKey(wraps every data-encryption key):268/:272— Keycloak client secrets:295Stripe ·:446Twilio ·:413SMTP ·:307MSSQL sa ·:212/217InfluxDB ·:402SeqSpikerSoft.AI.MCPServer/appsettings.*.json:4Fix:
Acceptance criteria:
appsettings*.json(placeholders only)Effort: M–L · Prerequisite for the production deployment model (INF-2, this batch).
Prerequisite for the production deployment model INF-2 #414.
Verified finding — live secrets hardcoded in
SpikerSoft.Api/appsettings.json(surfaced while adding webhook-signature validation)Committed production credentials currently in source (listing keys only, not values):
Twilio:AuthToken— Twilio account auth token (also the key that signs webhook HMACs, so it's security-critical).Encryption:MasterKey— a base64 AES master key.InfluxDB:Token/InfluxDashboard:Token— InfluxDB API token (same value in both blocks).Keycloak:backend-api:secretandKeycloak:health-check:secret— Keycloak client secrets.Anyone with repo read access has these. Because .NET config layering lets environment variables override
appsettings.json, the migration is low-risk per key: inject each asSection__Keyenv (Docker/Swarm secret), then blank the value inappsettings.json. Rotate every exposed credential after it's out of source (they must be treated as already compromised).Suggested bounded first slice (no architecture decision needed): pick the highest-risk few (
Encryption:MasterKey,Keycloak:*:secret,Twilio:AuthToken) and move them to injected env + blank in source, once the deploy confirms the env vars are actually set (else the app loses the value on boot). I can prep that PR if you confirm the prod deployment already injects — or will inject — these as env/secrets; without that confirmation, blanking them would break boot, so it's the one gate here.(Context: found while shipping webhook HMAC validation — Twilio #165 (merged), SonarQube #166. Both reference
Twilio:AuthToken/ a SonarQube secret from config.)Board-sweep status (2026-07-22) — this ticket's notes predate the OpenBao rollout, so catching it up: the epic it seeded (#543/#545/#546) has landed the core:
SpikerSoft.Api/appsettings.jsonnow carries blank values for all 12 API credentials (incl. every key the 07-06 comment listed — Twilio:AuthToken, Encryption:MasterKey, Influx tokens, Keycloak client secrets), served from OpenBao with strict fail-fast whenSecrets__UseBao=true(merged #546 stage-4, backend4bcec842). CI secrets are Bao-fetched repo-wide (two AppRole secrets per repo).Still open before this go-live gate closes: (1) rotation of the previously-committed values — they must be treated as compromised; #600 tracks the Influx token, #633 the dev-environment set; (2) the worker-fleet Bao overlay rollout is ~26 of 60 stacks (#546's remaining batches); (3) plaintext creds in
.env-10Nfiles on the shared mount (flagged in #554). Leaving open as the go-live umbrella for those.