A secret committed to a public repo used to have a grace period. Not a generous one, but a real one, the window between git push and some human stumbling across it was measured in days, sometimes weeks. That window is what you were implicitly betting on every time you told yourself you’d clean up that config file later.
Microsoft Threat Intelligence just published the receipt that says the window is gone. Here’s how the beats landed, and what each one actually means.
5 November 2026, the report drops
Microsoft documents threat actors using ARTEX, an agentic offensive security framework, to autonomously search GitHub for exposed OAuth application secrets, extract them, compromise the associated OAuth app, and perform authenticated actions inside the app’s tenant. Read that chain slowly. Search, extract, compromise, act, no human in the loop between steps.
The annotation that matters: none of this is novel in isolation. People have scraped GitHub for secrets for years. What changed is that the whole kill chain is now one autonomous loop instead of four manual tasks stitched together by someone who needs sleep. Don’t let anyone sell you “AI hacking autonomously”, a human pointed ARTEX at a target. The agent is the labour, not the intent. That distinction is the only thing standing between sober threat modelling and a Gartner keynote.
The morning after, I went looking in my own tenant
First move, and it’s free: ask Graph which of your app registrations even have a secret that could leak. A client secret in source is only dangerous if the app is still configured to accept one.
Every row is a liability you’re carrying. The ones with secrets expiring in 2027 and beyond are the ones a leak keeps paying out on. Cross-reference the AppId values against a code search, searching for your own AppId GUIDs in public repos is faster and has almost no false positives:
If you have Defender for Cloud Apps, pivot to the OAuth app governance page and sort by permission scope. An app with Mail.ReadWrite or Directory.ReadWrite.All and a leaked secret isn’t an incident, it’s a breach you haven’t noticed yet.
Same day, what I actually changed
Rotation first, blame later. For any app you can’t prove clean, remove the credential and issue a fresh one:
Then the unglamorous structural fix: stop using long-lived secrets. Workload identity federation lets your CI/CD pipeline and Kubernetes workloads get short-lived tokens from their own trusted issuer, no secret to commit, nothing to scrape. GitHub Actions supports OIDC federation to Entra. There is no good reason a build pipeline still carries a static client secret in 2026, and “migration cost” stopped being an excuse the moment an agent started reading your repos faster than you can.
Turn on GitHub push protection org-wide while you’re there (Settings → Code security → Secret scanning → Push protection). It blocks the commit before the secret ever reaches a branch an agent can read. Prevention at the point of the mistake beats detection after the scrape.
The beat that hasn’t happened yet
Here’s the one on the calendar you don’t control. The gap between “secret pushed” and “secret abused” is collapsing toward zero, and defensive scanning runs on the same clock you do, human-reviewed, batched, rate-limited. The attacker’s loop doesn’t take lunch.
So the real remediation isn’t a command. It’s accepting that any secret which can leak eventually will, at machine speed, and architecting so the leak costs nothing. Short-lived tokens. Federated identity. Zero standing secrets. Rotate what you’ve got this week, then spend next quarter making sure there’s nothing worth scraping.