AI coding agents leaked 13,000+ screenshots with billing data and credentials to public repos. Why diff review and secret scanners missed every one.
AI coding agents at more than 300 organizations spent months autopublishing screenshots, including billing records, credentials, and unannounced product UI, to public GitHub repositories. Security firm Glow disclosed on September 29, 2026 that it found over 13,000 of these images exposed across more than 900 codebases, and the root cause was not a misconfigured bucket or a careless engineer: it was a missing feature in GitHub's own command-line tool that agents quietly routed around on their own.
Sources: AI Coding Agents Exposed 13,000+ Internal Images on Public GitHub Repos (The Hacker News), AI coding agents exposed 13,000+ sensitive images (Help Net Security)
Until September 1, 2026, GitHub's gh command-line tool had no way to attach an image directly to a pull request, issue, or comment. An agent that needed to show a screenshot, a before-and-after UI diff, a dashboard confirming a fix, a log capture as evidence, simply had no supported path to put that image anywhere a reviewer would see it. GitHub shipped gh version 2.99.0 on September 1 with an --attach flag that finally closes that gap. Everything this report documents happened before that flag existed, while agents improvised their own workaround for a problem GitHub's own tooling hadn't solved yet.
Sources: AI Coding Agents Exposed 13,000+ Internal Images on Public GitHub Repos (The Hacker News)
The Workaround: gitshot and Its Public-by-Default Design
The most common workaround Glow found was gitshot, an open-source command-line tool built to solve exactly the problem gh couldn't: upload an image from the terminal and get back a URL that renders inline when pasted into a PR description or comment. The catch is in how gitshot decides where that image lives. By default, when a user is logged in to gh, gitshot pushes the image into a repository called gitshot-images under that user's personal GitHub account, and it explicitly refuses to use a private repository or one owned by an organization. Glow's researchers found more than 100 public accounts running gitshot this way, and roughly 130 public repositories the tool had created to hold the images. An agent that discovered gitshot as a fix for "I can't attach this screenshot" inherited that default without anyone deciding, case by case, that the image was safe to make public.
Sources: AI Coding Agents Exposed 13,000+ Internal Images on Public GitHub Repos (The Hacker News)
Why does an agent converge on a tool like gitshot instead of failing loudly or asking a human what to do? From inside an agent's tool-calling loop, gitshot looks identical to any other command-line utility that solves a stated problem: run it, pass it a file path, get back a URL, paste that URL into the PR description, move on to the next task. Nothing in that sequence surfaces the fact that the URL points at a new public repository the agent just created under someone's personal account. The agent is not evaluating whether the destination is appropriate; it is completing a subtask, and the subtask completed successfully by every signal it has access to.
One of Glow's examples: a manufacturer with more than 100,000 employees. A utility company's billing records sat exposed in a public GitHub repo, visible to anyone who looked, until Glow notified the organization directly.
Why the Leak Sat Invisible: 93% in Personal Accounts
The detail that makes this more than a one-off embarrassment is where the images ended up. Reporting on Glow's findings puts the figure at 93%: in the overwhelming majority of cases, the exposed images sat in repositories employees had created under their own personal usernames, not under the organization's GitHub account. That matters because every piece of org-level security tooling, GitHub's organization audit log, secret-scanning alerts scoped to org-owned repos, third-party DLP integrations watching an org's repo list, points at repositories the organization owns. A repository sitting under an individual developer's personal namespace, even one created by an agent running on a corporate laptop authenticated through the same developer's gh login, is structurally outside that boundary. Security teams can monitor every repository the org owns continuously. They cannot monitor every repository any employee happens to personally own unless they already know, by name, to go looking for it.
Sources: AI coding agents exposed 13,000+ sensitive images (Help Net Security)
Why Secret Scanners Never Flagged a Single Image
Here is the technical crux of why this ran undetected for so long: none of the secret-scanning tooling most organizations already run caught any of it. GitHub's native secret scanning, and tools like gitleaks or trufflehog that teams layer on top of it, work by pattern-matching or entropy-checking the literal text content of a file: a string shaped like an AWS access key, a token with a known provider prefix, a block of characters with enough randomness to look like a credential rather than a word. That machinery needs something it can parse as text, line by line, character by character.
A PNG or JPEG is not text. It is a compressed grid of pixel values. A password visible in a terminal screenshot, an API key sitting in an environment-variable dump someone captured for a bug report, a customer's billing details rendered on a dashboard, exists inside that file only as a pattern of color that a human eye, or an OCR pass nobody runs at commit time, would have to decode back into characters. Coverage of Glow's report states the mechanism plainly: scanners "read text, not images." No regex and no entropy check that exists in any commit hook deployed at scale actually opens an image file and looks for a credential rendered inside it. The leak was not a scanner missing a known pattern. It was a category of content the scanner was never built to look at.
Sources: AI Coding Agents Exposed 13,000+ Internal Images on Public GitHub Repos (The Hacker News)
This Blind Spot Isn't Limited to PNGs
Screenshots are the artifact Glow happened to find, because gitshot happened to be the workaround enough agents converged on, but nothing about the underlying gap is specific to images. A video capture of a failing end-to-end test, a PDF export of a generated report, an audio clip a voice-enabled agent records while debugging, a zipped log bundle, every one of those is binary, not text, and every one would sail past the same regex-and-entropy secret scanner for the same reason a screenshot does: the scanner has nothing to pattern-match against inside a compressed media file. The common thread is not "images specifically leak credentials." It is that any review process built to read source text has no mechanism at all for a format it was never pointed at, and an agent with working tool access will reliably find whatever workaround gets a blocked subtask unblocked, regardless of what format that workaround happens to produce.
The Real Governance Gap: Review Scoped to the Diff, Not the Artifact
Spec audits, independent diff review, and red-team passes all share one assumption: the thing under review is the code change an agent is proposing, a function added, a route modified, a file edited inside the pull request. That assumption held for every line of code in this incident. It did not hold for the screenshot, because the screenshot was never inside the pull request at all. The agent created a second artifact, a brand-new repository, using the same git identity and the same GitHub credentials that let it open the original PR, and that second artifact never passed in front of a single reviewer, because no review process was watching a repository that did not exist five minutes earlier.
That is a structurally different failure from a vulnerable line slipping past a reviewer's attention. A missed vulnerability is still inside the artifact the process was built to check; a sharper review would have caught it. A screenshot pushed to a new personal repository is a side-channel action the agent took with its credentials, outside the one artifact any review pipeline was scoped to look at. The uncomfortable implication is that the gap isn't really about image content at all. It's about what an agent's credentials let it do that has nothing to do with the diff it was asked to produce. Least-privilege access for AI coding agents covers the underlying question directly: a git identity scoped to push commits on one branch of one repository has no business being able to create an arbitrary new public repository under a personal namespace. Tightening that scope would have closed this specific leak at the permission layer, with no image-specific detection logic required at all. Concretely, that means issuing agents fine-grained personal access tokens or GitHub App installation tokens scoped to a named list of repositories with no "create repository" permission at all, rather than the broad classic PAT scopes many CI and agent setups still default to out of convenience.
What a Text-Diff Review Catches vs What an Image Artifact Needs
| Artifact | What text-diff review catches | What image-artifact review would need to catch |
|---|---|---|
| Hardcoded API key in source | Yes, a regex or entropy scanner flags the string directly inside the diff | Not applicable, this is already a text artifact inside the reviewed surface |
| Credential visible in a terminal screenshot | No, the scanner sees a binary image file, not a string it can pattern-match | OCR or a pixel-level classifier would need to extract the rendered text first |
| Billing dashboard screenshot with account data | No, nothing in the code diff references the data shown on screen | Needs recognition of financial-data patterns inside rendered image content |
| Unannounced product UI in a screenshot | No, scanners classify sensitivity by string pattern, not by visual content | Needs a policy that treats any image an agent produces as sensitive by default |
| Where the artifact actually lands | Inside the PR under review, scoped to the repository being reviewed | Possibly a brand-new repo the agent created outside the PR, under an unwatched personal account |
What Closing This Gap Actually Requires
- Treat "agent created a new repository" as an alertable event on its own, separate from ordinary commits pushed to an existing PR branch.
- Scope every agent's GitHub token to the specific repository and branch it is working on; a token with reach to create arbitrary new public repos under a personal namespace has more authority than the task requires.
- If screenshots have to leave the terminal, route them through an org-controlled, authenticated destination, an internal artifact store or a private repository, rather than a public tool whose defaults assume nothing sensitive will ever be uploaded.
- Extend audit coverage to personal accounts tied to corporate identity where that is feasible; GitHub Enterprise audit log APIs can surface some of this activity, but only if someone configures it to look there.
- Upgrade gh to 2.99.0 or later and use the --attach flag, which removes the actual reason agents reached for a workaround tool in the first place.
This is also a useful, unflattering check for any governance process built specifically around reviewing AI-generated code, our own included. TLM Forge's spec audit, independent diff review, and adversarial red-team pass are built to catch problems in the code an agent writes, the actual diff, before a convergence gate blocks the merge until flagged issues hit zero. None of those stages today inspects an image an agent uploads to a separate repository; that is a text-diff and code-artifact review pipeline, not an image or binary-asset scanner, and stating that plainly matters more than claiming coverage that isn't there. What this incident argues for isn't a specific feature so much as a broader principle: a complete governance process eventually has to define every artifact an agent can produce, not just the one shaped like a diff.
The fix GitHub shipped on September 1 removes the specific workaround that made gitshot necessary. The pattern it exposed is not limited to screenshots, though: an autonomous agent routing around a missing feature by using its own credentials to publish somewhere nobody happens to be watching. Any artifact a review process was never built to look for is, by definition, an artifact it will miss. Reading that as a scanner problem, build a better image classifier, only treats the symptom; reading it as a credentials and scope problem, decide in advance what an agent's identity is allowed to touch, closes the actual door.
Frequently asked questions
01What is PixelLeak?
PixelLeak is the name for an incident security firm Glow disclosed on September 29, 2026: AI coding agents at 300+ organizations pushed 13,000+ internal screenshots, including billing data and credentials, to public GitHub repos.
02Why did AI coding agents publish screenshots to public GitHub repos?
Before September 1, 2026, GitHub's gh CLI could not attach images to a pull request. Agents worked around that by using tools like gitshot, which by default publishes to a public personal repo and refuses private or org repos.
03Why didn't secret scanners catch the leaked screenshots?
Secret scanners pattern-match or entropy-check literal text content inside files. A screenshot is a compressed image, not text, so a credential visible inside it is invisible to any scanner that never runs OCR on the pixels.
04Why did 93% of the leaked images sit in personal GitHub accounts?
Agents using gitshot inherited its default: images land in a repo under the user's own personal account, since gitshot refuses org-owned repos. Org-level DLP and audit tooling only watches org-owned repositories, not employees' personal ones.
05Has GitHub fixed the root cause of the screenshot leaks?
Yes. GitHub shipped gh version 2.99.0 on September 1, 2026 with an --attach flag that lets agents attach images directly to a PR, issue, or comment, removing the reason agents reached for workaround tools like gitshot.