Key points
- Datadog Security Research is tracking several overlapping campaigns that systematically enumerate corporate GitHub organizations, repositories, and user accounts through the GitHub API.
- Operators rely on automated scraping tooling with custom or legitimate-sounding user agents, leveraging GitHub "ghost" accounts that are often years old, or compromised OAuth tokens and personal access tokens (PATs) from legitimate users.
- Most requests target public data, making it look like ordinary API traffic. In some cases, the activity escalated past public information enumeration, appearing to successfully clone private repositories.
- The behaviors can be hunted on and detected if you are watching the right fields, such as user agent, token type, source ASN (when available), and attempted actions.
Overview
Over the past several months, Datadog Security Research has observed a sustained pattern of GitHub API abuse aimed at mapping organizations and their members. The activity is not a single actor. Rather, it’s a blend of custom automated scanner tools, opportunistic abuse of leaked credentials, and coordinated networks of burner (ghost) accounts.
Individually, most of these requests are unremarkable. They hit public endpoints, authenticate cleanly or not at all, and return successful responses. The concern lies in the aggregate: a group of accounts moving in sync across companies’ GitHub organizations with versioned custom tooling iterating over weeks, and in the worst case, actors that stopped enumerating and started cloning.
This post covers what we have seen, from broad public-data scraping up to confirmed private-repository access. It closes with indicators and the detection queries defenders can use to separate this activity from legitimate traffic.
Enumeration is noisy
A large share of GitHub's API surface is reachable without authentication. Listing an organization's public repositories, walking a user's followers and following lists, enumerating gists, starred repos, and org memberships, and running GraphQL queries against public objects all return data. Because these paths are public by design, requests against them produce HTTP 200 responses and generate no failed-auth signal.
An operator can build a detailed map of an organization, such as its public repositories, its members, who those members follow, and which projects they touch, entirely from public data. This traffic blends into normal API usage. GitHub also does not populate geolocation data for events on external resources, which limits geolocation and VPN/proxy-based attribution. The logs do capture the GitHub actor making the request and the type of access token used.
Broad enumeration through ghost accounts
The widest band of activity comes from networks of "ghost" accounts: profiles created two to five years ago, left dormant, then activated to send API traffic across multiple organizations. An account with a multi-year history reads as more legitimate than one registered the same week it starts scraping.
We have confirmed more than 50 ghost accounts across multiple user agents participated in this enumeration since we began monitoring in October 2025. Naming conventions often cluster into recognizable families, including an amazon-data-* prefix pattern and several short, repetitive handles. Examples include kobalt*, BirdWithDreams, BirdWithPlan, the *-orb family (kuku-orb, lolo-orb, lulu-orb, ruru-orb, zouzou-orb, meme-orb), user432023, user412023, and so on.
These accounts are often used for a burst of 1–3 weeks across many organizations before usage ends.
These accounts use a mix of data exfiltration sounding user agents such as GitHub-Company-Scraper and GitHub-Scraper-Tool/1.0. Another common naming trend runs the same playbook with legitimate-sounding analytics or dashboard-related user agents designed to blend into normal data analysis traffic, such as GitHubAnalytics/1.5. One exception uses the bare user agent request, which stands out from the versioned naming typical of other campaigns.
The heaviest concentration of requests target /graphql, which is well suited to bulk queries across organization, user, and repositories. Beyond GraphQL, the targeted REST routes are exactly what you would expect from an org-mapping exercise. On its own, this enumeration rarely produces meaningful access inside an organization, rather it’s accomplishing reconnaissance.
Token compromise
Beyond ghost accounts, some campaigns use tokens from legitimate GitHub users who posted their PATs unintentionally, had their endpoint compromised, or exposed their token in another way.
Between late December 2025 and early January 2026, we tracked one campaign using stolen tokens across a versioned progression of user agents:
GitHub-Commit-Fetcher/1.3(late December 2025)GitHub-Commit-Fetcher/1.4(late December 2025)GitHub-Event-Fetcher/2.2(January 2026)
The version bumps occurred over a tight window. The campaign's infrastructure ran on 3xK Tech, a hosting provider with repeated abuse reports.
The activity shows repeated usage of the same compromised OAuth access tokens and compromised PATs. Dozens of distinct legitimate GitHub user accounts made API requests to a single organization within a window of only a few minutes. Their requests targeted private repository commit paths, and in this campaign the attempts failed.
The functional focus of this campaign was narrow and consistent: listing organization repositories, fetching commits, and probing private repository paths.
Successful exfiltration
Most of this activity focused on reconnaissance and exfiltration attempts. In rare cases, the scanning crossed into confirmed data access.
In one example, the user agent repo-dumper successfully took actions inside a private repository belonging to a single organization. The audit log captured the exfiltration through a mix of git.clone and api.request events to private paths. Both GitHub accounts behind this access were already known to us from earlier failed activity.
Detecting malicious behavior
Since most activity targets public data and returns successful responses, focus detection on successful exfiltration of private resources.
Suspicious user agents often use fake version strings like /1.0 or /1.1 alongside names that sound like legitimate tools.
We recommend reviewing anomalous user agent (http.useragent) behavior across your GitHub audit logs, especially for actions reaching private repositories. When an actor reaches a private resource, GitHub captures the IP address, actor name, and programmatic access type. Use the queries below as a start to hunt for this activity.
source:github
evt.action:api.request
status_code:2*
public_repo:false
programmatic_access_type:(*OAuth* OR "Personal access token (classic)" OR "Fine-grained personal access token")
source:github
evt.action:git.clone
repository_public:false
programmatic_access_type:(*OAuth* OR "Personal access token (classic)" OR "Fine-grained personal access token")
source:github
evt.action:repo.download_zip
public_repo:false
programmatic_access_type:(*OAuth* OR "Personal access token (classic)" OR "Fine-grained personal access token")
If you are a Datadog customer, your GitHub source will fall under github.audit.streaming or github-telemetry.
Conclusion
User agents, event activity, and actor names are vital clues to unauthorized activity in your environment. Datadog’s Security Research team has seen an increase in vibe-coded or custom tooling legitimately used within an organization that may have some similarities in user agent naming to the ones we’ve identified. It’s important to know what normal looks like in your environment. We suggest enabling GitHub audit log streaming, baselining your user agents, proactively threat hunting, and developing detections unique to your GitHub organization.
Appendix
Indicators of compromise
| Type | Value |
|---|---|
| User agent | gha-injection-scanner/1.0 |
| User agent | GitHub-Repo-Crawler/1.0 |
| User agent | gh-repo-lister/1.0 |
| User agent | GitHub-Commit-Fetcher/1.3 |
| User agent | GitHub-Commit-Fetcher/1.4 |
| User agent | GitHub-Event-Fetcher/2.2 |
| User agent | repo-dumper |
| User agent | GitHub-Company-Scraper |
| User agent | GitHub-Scraper-Tool/1.0 |
| User agent | OrgSearchAndInspect/1.1 |
| User agent | request |
| User agent | GitHub-Insights/3.2 |
| User agent | GitHub-Inspector/2.9 |
| User agent | RepoAnalyzer/1.7 |
| User agent | GitHub-Monitor/2.5 |
| User agent | GitHubVisualizer/2.7 |
| User agent | GitHubAnalytics/1.5 |
| User agent | GitHubDashboard/1.8 |
| User agent | RepoExplorer/2.1 |
| User agent | GitHubMetrics/1.9 |
| User agent | GitHub-Display/1.0 |
| User agent | GitHub-Scanner/1.6 |
| User agent | GitHubReporter/2.0 |
| User agent | GitHub-Tracker/3.1 |
| User agent | githarvester/1.0 |
| Tooling | GitHarvester |
| Hosting Provider | cherryservers[.]com |
| Hosting Provider | 3xktech[.]cloud |
Common routes
| Route | Purpose |
|---|---|
/graphql |
Primary focus—bulk org/user/repo queries |
/organizations/:organization_id |
Get organization |
/organizations/:organization_id/repos |
List org repositories |
/user/:user_id/followers |
List a user's followers |
/user/:user_id/following |
List accounts a user follows |
/user/:user_id/gists |
List a user's gists |
/user/:user_id/orgs |
List a user's org memberships |
/user/:user_id/repos |
List a user's repositories |
/user/:user_id/starred |
List starred repositories |