When Git Push Protection Saves You: Remove Secrets the Right Way (Azure AD/Entra + .NET)
Jenkins
Source: Dev.to | Dec 18, 2025 (UTC)
When Git Push Protection Saves You: Remove Secrets the Right Way (Azure AD/Entra + .NET)
TL;DR — GitHub push protection flagged an Azure AD (Microsoft Entra) client secret committed to src/MultiTenantApi/appsettings.json. Do this: (0) rotate secret, (1) stop tracking and ignore, (2) scrub history (rebase or git-filter-repo), (3) verify, (4) keep protection on and add local tooling (User Secrets, gitleaks).
The Message You Saw
GH013: Repository rule violations found for refs/heads/main Push cannot contain secrets … Azure Active Directory Application Secret … commit: 07e7743697089bad3b902fee5d5df5faef954abb path: src/MultiTenantApi/appsettings.json:13
Enter fullscreen mode
Exit fullscreen mode
This is a good block. Treat it as an incident: rotate → remove → verify.
0) Rotate the secret now (don’t skip)
Entra portal → App registrations → your app → Certificates & secrets → New client secret.
Update everywhere it’s used (Azure Key Vault, App Service config, pipeline variables).
Delete the old secret.
Rotating first ensures even a past leak can’t be used.
1) Remove secrets from the working tree and prevent re‑adds
From repo root:
# Ignore appsettings across the repo echo "**/appsettings*.json" >> .gitignore git add .gitignore # Keep your local file, but stop tracking it git rm --cached src/MultiTenantApi/appsettings.json git commit -m "chore: stop tracking appsettings.json; ignore secrets"
Enter fullscreen mode
Exit fullscreen mode
Add a safe template so newcomers know the shape:
cp src/MultiTenantApi/appsettings.json src/MultiTenantApi/appsettings.json.example # open the .example and replace real values with placeholders git add src/MultiTenantApi/appsettings.json.example git commit -m "docs: add appsettings.json.example (no secrets)"
Enter fullscreen mode
Exit fullscreen mode
.NET local dev → User Secrets (keeps secrets out of Git):
2) Scrub the secret from history (what GitHub flagged)
Choose one path.
A) Only a few recent commits contain the secret
Interactive rebase and amend those commits.
git fetch origin git switch -c sanitize/remove-secret origin/main git rebase -i origin/main~20 # pick a base far enough back # mark commits that touched appsettings.json as: edit # for each paused commit git rm --cached src/MultiTenantApi/appsettings.json git commit --amend --no-edit git rebase --continue
Enter fullscreen mode
Exit fullscreen mode
Push as a PR (safe if main is protected):
git push -u origin sanitize/remove-secret
Enter fullscreen mode
Exit fullscreen mode
B) The secret may appear anywhere in history
Use git-filter-repo (modern, recommended over BFG).
# install once pip install git-filter-repo # safety tag git tag backup-before-sanitize-$(date +%Y%m%d%H%M%S) git switch main git filter-repo --force --path src/MultiTenantApi/appsettings.json --invert-paths
git switch -c sanitize/remove-secret git push -u origin sanitize/remove-secret # open a PR
Enter fullscreen mode
Exit fullscreen mode
Azure DevOps note: branch policies may also block direct pushes; PR path is standard.
3) Verify before pushing
# 1) File no longer tracked git ls-tree -r HEAD | grep appsettings || echo "✅ no tracked appsettings.json" # 2) No literal secrets left (search for a known token or pattern) git grep -n "CLIENT_SECRET_VALUE" || echo "✅ literal secret not found" # 3) History scrubbed (no commits still referencing the path) git log --oneline -- src/MultiTenantApi/appsettings.json || echo "✅ no history entries"
Enter fullscreen mode
Exit fullscreen mode
If verification passes, push your branch / open the PR.
4) About the “Allow this secret” link
GitHub provides a temporary allow‑push URL. Do not use it unless: 1) you have rotated the secret and
2) you have completely removed it from history.
Otherwise you will publish compromised credentials.
Залишити відповідь