The times in this diagram are real. They come from a founder who pushed a config file to a public repo on a Friday afternoon and found the damage on Saturday morning.
Eight minutes passed between the push and the first unauthorized API call. Not eight hours. Eight minutes, and nothing about that number is unusual.

Reading the diagram
Read it left to right, top to bottom. Each column is somebody who learns your key exists, in the order they learn it. You are the leftmost column, and you are also the last row.
Step 1 is the only thing you did. A push, on a Friday afternoon, with a config file in it. Everything after this happens without you.
Step 2 is the part almost nobody knows about. GitHub runs a public events feed that announces every push to every public repository, in near real time, to anyone who asks for it. It is a documented feature and it exists for good reasons. It also means a scanner never has to search for your repository. Your repository is delivered to it, seconds after you push, along with everyone else's.
That is why the scanner column is labelled the way it is. There was no decision to attack you.
The red band is the window you knew nothing about. The scanner tries the key at 4:31, gets told it is valid with full access, and starts launching GPU instances by 4:35. Twelve minutes after the push, someone else's workload is running on your account, in your name, at your expense.
Step 7 is where the money starts, and step 8 is where you find out. Charges accrue quietly, because accruing quietly is what charges do. The alert reaches you the next morning.
The billing alert is not a security control. It sits at the end of the chain by construction: it cannot fire until charges exist, and charges cannot exist until the attacker is already running compute. If your plan for a leaked key is "I would notice the bill", your plan has a built-in delay of hours at best.
Why the order matters more than the clock
It is tempting to read this diagram as being about speed, and to conclude that the fix is faster alerting.
It isn't, quite. Look at the sequence instead of the timestamps. Every actor in the chain learns about your key before you do, and they learn it in an order you cannot reshuffle. GitHub tells the feed. The feed tells the scanner. The scanner tells your cloud provider. Your cloud provider tells billing. Billing tells you.
You are structurally last. Tightening the billing threshold moves step 8 earlier by minutes and changes nothing about steps 2 through 6.
The two interventions that actually work both sit before step 1. Keep the secret out of the repository, so there is nothing on the feed to find. And turn on push protection, which rejects the push itself when it spots a credential, so the announcement never happens.
The source
This diagram is generated from the file below, and the render is checked against it in CI. Copy it into any Mermaid renderer to remix it.
sequenceDiagram
autonumber
participant D as You
participant G as GitHub<br/>(public repo)
participant S as An automated<br/>scanner
participant C as Your cloud<br/>account
participant B as Your billing<br/>alert
D->>G: 4:23 PM git push, a config file carries the key
G->>S: seconds later, the public events feed<br/>announces every push to everyone
rect rgb(254, 242, 242)
S->>C: 4:31 PM tries the key
C-->>S: valid. full access.
S->>C: 4:35 PM launches GPU instances
S->>C: 5:00 PM spreads to more regions
end
C->>B: charges accrue quietly
B-->>D: next morning, the bill tells you
Note over D,B: no one targeted you.<br/>every actor above knew before you did.
How fast do attackers find a key pushed to a public repo?
In the incident these times come from, the first unauthorized API call landed 8 minutes after the push. That is not a coincidence of timing. GitHub publishes every push to a public repository on a real-time events feed that anyone can subscribe to, so a scanner does not have to find your repo. Your repo is announced to it.
Why did nobody get warned before the charges started?
Because billing is downstream of everything else. The charges only exist after the compute is already running, and the alert only fires after the charges cross a threshold. By the time the alert has anything to report, the attacker has been spending for hours. A billing alert is a receipt, not a warning.
Does deleting the commit fix it?
No. The key was published the moment you pushed, and the events feed already handed it out. Force-pushing over the commit removes it from the branch, not from the copies scanners already took. The only fix is rotating the key, and then checking what was done with the old one.
Does this only happen to big or interesting projects?
No, and that is the part worth internalising. Nobody looked at your project and decided to attack it. Scanners consume the whole public firehose and try every credential-shaped string they see. A side project with four users and a company with four million get the same treatment, because the key is the target, not you.
What actually reduces the risk?
Two things, in this order. Keep secrets out of the repo entirely so there is nothing to leak, using environment variables on your host rather than a committed config file. Then turn on push protection and secret scanning on the repo, so a key that does slip in gets blocked at push time instead of announced to the feed.
Is a key already sitting in your deployed app?
A scan reads what your live site actually ships to visitors, which is where leaked keys turn up long after the repo looks clean.