When Git Push Protection Saves You: Remove Secrets the Right Way (Azure AD/Entra + .NET)

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)

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):

dotnet user-secrets init --project src/MultiTenantApi dotnet user-secrets set "AzureAd:ClientSecret" "<NEW-SECRET>" --project src/MultiTenantApi

Enter fullscreen mode

Exit fullscreen mode

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

Enter fullscreen mode

Exit fullscreen mode

Commit ignore/template if needed:

echo "**/appsettings*.json" >> .gitignore git add .gitignore src/MultiTenantApi/appsettings.json.example git commit -m "chore: ignore appsettings; add .example template"

Enter fullscreen mode

Exit fullscreen mode

git push --force-with-lease origin main

Enter fullscreen mode

Exit fullscreen mode

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.

Long‑Term Hygiene (copy‑paste policy)

.gitignore

# secrets & environment **/appsettings*.json !.*/ # keep hidden folders ignored unless explicitly whitelisted # local env examples !**/appsettings*.json.example

Enter fullscreen mode

Exit fullscreen mode

.gitattributes (line endings, future LFS, etc.)

* text=auto eol=lf

Enter fullscreen mode

Exit fullscreen mode

Pre-commit secret scanning (local guardrail)

gitleaks detect --staged

Enter fullscreen mode

Exit fullscreen mode

.NET practice

FAQ

Q: I already force‑pushed. Am I safe after rotation?

A: Rotation neutralizes the exposed secret. Still scrub history so the leak isn’t public knowledge or referenceable.

Q: Should I choose rebase or filter‑repo?

A: If only a couple of commits were affected, rebase is shortest. If uncertain or widespread, filter‑repo is faster and more reliable.

Q: Team is large and main is protected?

A: Push a sanitize/ branch and open a PR; your platform’s merge will handle policy checks.

Copy‑Ready Incident Runbook

  1. Rotate in Entra; delete old secret.
  2. echo "**/appsettings*.json" >> .gitignore && git add .gitignore
  3. git rm --cached src/MultiTenantApi/appsettings.json && git commit -m "chore: stop tracking appsettings.json; ignore secrets"
  4. Add appsettings.json.example with placeholders; commit.
  5. A) rebase‑amend a few commits or B) git filter-repo to purge history.
  6. Verify with ls-tree, git grep, git log -- path.
  7. Push branch / open PR. Keep push protection on.

— Written by Cristian Sifuentes — Full‑stack developer & Git/DevOps practitioner. Clean histories, zero‑secret repos, reproducible builds.

For further actions, you may consider blocking this person and/or reporting abuse

Залишити відповідь

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *

Читайте також