Azure DevOps: "VS403654: The push was rejected because it contains one or more secrets."
Push protection in Azure Repos found something that looks like a credential in one of the commits you pushed, and refused the whole push. The branch on the server did not change. The message names the commit, the file and the line. Take the secret out of that commit, not only out of the current files, and push again.
The whole message
From git push, as posted in a public LibGit2Sharp issue (the organization and branch replaced):
remote: Analyzing objects... (3/3) (27 ms) remote: Validating commits... (1/1) done (0 ms) remote: Checking for credentials and other secrets... done (59 ms) error: remote unpack failed: error VS403654: The push was rejected because it contains one or more secrets. To https://dev.azure.com/<organization>/<project>/_git/<repo> ! [remote rejected] <branch> -> <branch> (VS403654: The push was rejected because it contains one or more secrets. Resolve the following secrets before pushing again. For help, see …
The list that follows looks like this one, from a public report in the Aspire repository (August 2026):
VS403654:BypassableBlock The push was rejected because it contains one or more secrets. commit: 59219d7439b183a5171e95811c9e6174636b0a26 /src/Aspire.Dashboard/Model/ConnectionStringParser.cs(187,29-37) : SEC101/033 : MongoDbCredentials /tests/Aspire.Dashboard.Tests/ConnectionStringParserTests.cs(127,33-41) : SEC101/033 : MongoDbCredentials
Each line gives the file, the line and the columns, a rule ID and the kind of secret. The word after VS403654: says whether the block can be bypassed; public reports also show NonbypassableBlock. LibGit2Sharp, which is built on libgit2, shows only unpacking the sent packfile failed on the remote, so run the same push with the git command line to see the list.
Why the push was refused
Microsoft's Set up secret scanning: push protection checks every incoming push for high-confidence secrets and stops it. It comes with GitHub Advanced Security for Azure DevOps, or with the standalone GitHub Secret Protection for Azure DevOps, so someone turned it on for the repository, the project or the organization. Edits in the web interface are checked too.
Microsoft's page says to remove the secret from the commit history, not only from the file. A newer commit that deletes it does not help, as the Aspire report explains: the commit with the secret is still part of the history being pushed.
Look at what it found
git show 59219d7:src/Aspire.Dashboard/Model/ConnectionStringParser.cs
Go to the line in the message; the columns mark the characters it flagged. Leave out the leading / of the path: with it, Git answered fatal: path '/appsettings.json' does not exist in our test.
Take it out of the history
None of these commits reached the server, so you can rewrite them.
If the secret came in with your last commit, remove it from the file and amend that commit:
git commit --amend -a
git push
If it came in further back, edit that commit, as Microsoft's page describes:
git rebase -i 59219d7~1
In the editor, change pick to edit on the line of that commit and save. Remove the secret from the file, then:
git commit --amend -a
git rebase --continue
When a later commit had already deleted the secret, that commit has nothing left to do. In our test Git stopped on it with The previous cherry-pick is now empty, possibly due to conflict resolution., and git rebase --skip dropped it and finished the rebase.
When the commits don't need to stay separate, there is a shorter way. Delete the secret in the files first, then make one new commit from the branch you started on:
git reset --soft origin/main
git commit -m "Describe the change"
Before you push, check that no commit still holds it. Both ways left nothing for this command in our test:
git log -S "<part of the secret>" --oneline origin/main..HEAD
If it was a real credential, replace it too, and keep the new one out of the code, for example in Azure Key Vault, as Microsoft's page advises.
Example values and false positives
For a made-up value in an example or a test, Microsoft's page says to put Placeholder in front of it. The Aspire repository did that for example MongoDB passwords (pull request 20790), though it notes that it had not yet pushed the change through push protection.
For a false positive that has to stay as it is, Microsoft's page lets you bypass push protection: put skip-secret-scanning:true in the commit message. In the Aspire report, a newer commit on top whose message held that string let the whole history through, the flagged commit included. Azure DevOps still raises an alert for the secret under Advanced Security; dismissing it takes Project administrator permissions. Don't bypass a real credential.
Create the pull request from IntelliJ IDEA and Rider
Azure DevOps Pull Requests, a plugin by Lesstep for JetBrains IDEs 2024.1 or later and Android Studio, adds Git → Create Azure DevOps Pull Request…. Once the push goes through, it opens a pull request from the branch you are on, into the repository's default branch unless you pick another, optionally as a draft. If the branch is not on Azure DevOps yet, it says so and opens the IDE's push dialog first. Creating pull requests is Pro (US$1 a month, with a 30-day free trial); the review inbox is free.
Get it on JetBrains Marketplace
Azure DevOps and Azure Repos are trademarks of Microsoft Corporation; IntelliJ IDEA and Rider are trademarks of JetBrains s.r.o. This page is not affiliated with or endorsed by Microsoft or JetBrains.
More: "TF402455: Pushes to this branch are not permitted" · "TF401027: You need the Git 'GenericContribute' permission" · 日本語