GitHub API Sensitive Resource Enumeration
Detects a burst of GitHub api.request events from a single non-bot actor and source IP against sensitive routes such
as Actions/Dependabot/environment secrets, public keys, git trees and contents, zipball archives, organization
repository and member lists, webhooks, installations, and personal access tokens. Grouping by actor and source IP and
requiring a high request count spread across several distinct sensitive routes separates broad enumeration from a
single high-volume endpoint. This pattern is commonly used for credential discovery and source collection after token
theft. Requires GitHub Enterprise audit log streaming with API Request Events enabled.
Elastic rule (View on GitHub)
1[metadata]
2creation_date = "2026/09/22"
3integration = ["github"]
4maturity = "production"
5updated_date = "2026/11/03"
6
7[rule]
8author = ["Elastic"]
9description = """
10Detects a burst of GitHub `api.request` events from a single non-bot actor and source IP against sensitive routes such
11as Actions/Dependabot/environment secrets, public keys, git trees and contents, zipball archives, organization
12repository and member lists, webhooks, installations, and personal access tokens. Grouping by actor and source IP and
13requiring a high request count spread across several distinct sensitive routes separates broad enumeration from a
14single high-volume endpoint. This pattern is commonly used for credential discovery and source collection after token
15theft. Requires GitHub Enterprise audit log streaming with API Request Events enabled.
16"""
17false_positives = [
18 """
19 Org-wide backup, secret-rotation, or inventory scripts that list secrets, hooks, and repositories. Allowlist known
20 automation tokens and user agents.
21 """,
22]
23from = "now-11m"
24interval = "10m"
25language = "esql"
26license = "Elastic License v2"
27name = "GitHub API Sensitive Resource Enumeration"
28note = """## Triage and analysis
29
30> **Disclaimer**:
31> This investigation guide was created using generative AI technology and has been reviewed to improve its accuracy and relevance. While every effort has been made to ensure its quality, we recommend validating the content and adapting it to suit your specific environment and operational needs.
32
33### Investigating GitHub API Sensitive Resource Enumeration
34
35`api.request` is a streaming-only audit action (available with GitHub Enterprise audit log streaming and API Request Events enabled). Sensitive routes include Actions/Dependabot/environment secrets, public keys, git trees, contents, zipball archives, organization repository lists, members, webhooks, installations, and personal access tokens. The rule groups requests by `user.name` and `github.actor_ip` in a 10-minute window and fires on >= 15 requests spanning >= 3 distinct sensitive routes, which distinguishes broad enumeration from a single high-volume route. Automated actors (`github.actor_is_bot: true`) and requests without an actor IP are excluded. An adversary who has stolen a token commonly enumerates these routes to locate secrets and source code before pulling them, so this activity frequently precedes successful credential access or source collection.
36
37### Possible investigation steps
38
39- Review the distinct routes probed (`Esql.github_route_values`, `Esql.github_route_unique_count`) and the breadth across repositories and organizations (`Esql.github_repo_unique_count`, `Esql.github_org_values`) to gauge how targeted or broad the enumeration is.
40- Identify the token and access method from `Esql.github_token_id_values` and `Esql.github_programmatic_access_type_values`, and confirm whether the token belongs to known automation.
41- Review `Esql.github_user_agent_values` for the client; treat user agents containing tooling signatures such as `trufflehog` or `nord-stream` as credential-stealer tooling.
42- Pivot on `github.actor_ip` and `user.name` and correlate with `git.clone`, `repo.download_zip`, and secret-scanning alerts from the same actor or token, which indicate the enumeration led to collection.
43- Check for a later run of successful (2xx) requests on secrets, trees, or contents from the same actor or token, which indicates successful enumeration rather than failed probing.
44
45### False positive analysis
46
47- Internal inventory, backup, or secret-rotation automation and GitHub App servers that enumerate installations, repositories, and secrets. These typically use a known token and user agent; confirm and scope exceptions by actor, token, or user agent when expected.
48- Security tooling that legitimately scans repositories for exposed secrets from a known source.
49
50### Response and remediation
51
52- Revoke the token if the actor is not a known automation identity, and rotate any secrets exposed on the enumerated routes.
53- Review PAT and OAuth grants for the actor, and tighten organization PAT access and approval policies.
54- Block or monitor the source IP if the activity is clearly reconnaissance, and review whether any probed route later returned a success for the same actor.
55- Escalate to incident response if the enumeration is followed by secret access, repository cloning, or ZIP downloads from the same actor or token.
56"""
57references = [
58 "https://securitylabs.datadoghq.com/articles/mapping-out-your-unknown-threat-hunters-guide-to-github/",
59 "https://docs.github.com/en/enterprise-cloud@latest/admin/monitoring-activity-in-your-enterprise/reviewing-audit-logs-for-your-enterprise/streaming-the-audit-log-for-your-enterprise#enabling-api-request-events",
60]
61risk_score = 47
62rule_id = "ad112f18-b658-4cd8-ae1e-cb3c18a938ca"
63setup = """## Setup
64
65Requires the Elastic GitHub integration (`logs-github.audit-*`), GitHub Enterprise audit log streaming, and **Enable API Request Events** on the enterprise. `api.request` is not available via the REST audit-log API.
66"""
67severity = "medium"
68tags = [
69 "Domain: Cloud",
70 "Domain: SaaS",
71 "Platform: GitHub",
72 "Use Case: Threat Detection",
73 "Tactic: Discovery",
74 "Tactic: Credential Access",
75 "Tactic: Collection",
76 "Data Source: Github",
77 "Data Source: GitHub Audit Logs",
78 "Rule Type: ES|QL",
79 "Resources: Investigation Guide",
80]
81timestamp_override = "event.ingested"
82type = "esql"
83
84query = '''
85from logs-github.audit-* metadata _id, _index, _version
86| where
87 data_stream.dataset == "github.audit" and event.action == "api.request" and
88 github.actor_ip is not null and (github.actor_is_bot is not null and github.actor_is_bot == false) and
89 (
90 github.route like "*secrets*" or
91 github.route like "*public-key*" or
92 github.route like "*git/trees*" or
93 github.route like "*contents*" or
94 github.route like "*zipball*" or
95 github.route like "*hooks*" or
96 github.route like "*installations*" or
97 github.route like "*members*" or
98 github.route like "*outside_collaborators*" or
99 github.route like "*personal-access-token*" or
100 github.route == "/organizations/:organization_id/repos"
101 )
102| stats
103 Esql.event_count = COUNT(*),
104 Esql.github_route_unique_count = COUNT_DISTINCT(github.route),
105 Esql.github_repo_unique_count = COUNT_DISTINCT(github.repo),
106 Esql.github_route_values = VALUES(github.route),
107 Esql.github_org_values = VALUES(github.org),
108 Esql.github_programmatic_access_type_values = VALUES(github.programmatic_access_type),
109 Esql.github_user_agent_values = VALUES(github.user_agent),
110 Esql.agent_id_values = VALUES(agent.id),
111 Esql.data_stream_dataset_values = VALUES(data_stream.dataset),
112 Esql.data_stream_namespace_values = VALUES(data_stream.namespace),
113 Esql.github_token_id_values = VALUES(github.token_id)
114 by user.name, github.actor_ip, Esql.time_window = DATE_TRUNC(10 minutes, @timestamp)
115| keep user.name, github.actor_ip, Esql.*
116| where Esql.event_count >= 15 and Esql.github_route_unique_count >= 3
117'''
118
119
120[[rule.threat]]
121framework = "MITRE ATT&CK"
122[[rule.threat.technique]]
123id = "T1526"
124name = "Cloud Service Discovery"
125reference = "https://attack.mitre.org/techniques/T1526/"
126
127
128[rule.threat.tactic]
129id = "TA0007"
130name = "Discovery"
131reference = "https://attack.mitre.org/tactics/TA0007/"
132[[rule.threat]]
133framework = "MITRE ATT&CK"
134[[rule.threat.technique]]
135id = "T1552"
136name = "Unsecured Credentials"
137reference = "https://attack.mitre.org/techniques/T1552/"
138
139
140[rule.threat.tactic]
141id = "TA0006"
142name = "Credential Access"
143reference = "https://attack.mitre.org/tactics/TA0006/"
144[[rule.threat]]
145framework = "MITRE ATT&CK"
146[[rule.threat.technique]]
147id = "T1213"
148name = "Data from Information Repositories"
149reference = "https://attack.mitre.org/techniques/T1213/"
150[[rule.threat.technique.subtechnique]]
151id = "T1213.003"
152name = "Code Repositories"
153reference = "https://attack.mitre.org/techniques/T1213/003/"
154
155
156[rule.threat.tactic]
157id = "TA0009"
158name = "Collection"
159reference = "https://attack.mitre.org/tactics/TA0009/"
160
161[rule.investigation_fields]
162field_names = [
163 "user.name",
164 "github.actor_ip",
165 "Esql.time_window",
166 "Esql.event_count",
167 "Esql.github_route_unique_count",
168 "Esql.github_repo_unique_count",
169 "Esql.github_route_values",
170 "Esql.github_org_values",
171 "Esql.github_programmatic_access_type_values",
172 "Esql.github_user_agent_values",
173 "Esql.github_token_id_values",
174]
Triage and analysis
Disclaimer: This investigation guide was created using generative AI technology and has been reviewed to improve its accuracy and relevance. While every effort has been made to ensure its quality, we recommend validating the content and adapting it to suit your specific environment and operational needs.
Investigating GitHub API Sensitive Resource Enumeration
api.request is a streaming-only audit action (available with GitHub Enterprise audit log streaming and API Request Events enabled). Sensitive routes include Actions/Dependabot/environment secrets, public keys, git trees, contents, zipball archives, organization repository lists, members, webhooks, installations, and personal access tokens. The rule groups requests by user.name and github.actor_ip in a 10-minute window and fires on >= 15 requests spanning >= 3 distinct sensitive routes, which distinguishes broad enumeration from a single high-volume route. Automated actors (github.actor_is_bot: true) and requests without an actor IP are excluded. An adversary who has stolen a token commonly enumerates these routes to locate secrets and source code before pulling them, so this activity frequently precedes successful credential access or source collection.
Possible investigation steps
- Review the distinct routes probed (
Esql.github_route_values,Esql.github_route_unique_count) and the breadth across repositories and organizations (Esql.github_repo_unique_count,Esql.github_org_values) to gauge how targeted or broad the enumeration is. - Identify the token and access method from
Esql.github_token_id_valuesandEsql.github_programmatic_access_type_values, and confirm whether the token belongs to known automation. - Review
Esql.github_user_agent_valuesfor the client; treat user agents containing tooling signatures such astrufflehogornord-streamas credential-stealer tooling. - Pivot on
github.actor_ipanduser.nameand correlate withgit.clone,repo.download_zip, and secret-scanning alerts from the same actor or token, which indicate the enumeration led to collection. - Check for a later run of successful (2xx) requests on secrets, trees, or contents from the same actor or token, which indicates successful enumeration rather than failed probing.
False positive analysis
- Internal inventory, backup, or secret-rotation automation and GitHub App servers that enumerate installations, repositories, and secrets. These typically use a known token and user agent; confirm and scope exceptions by actor, token, or user agent when expected.
- Security tooling that legitimately scans repositories for exposed secrets from a known source.
Response and remediation
- Revoke the token if the actor is not a known automation identity, and rotate any secrets exposed on the enumerated routes.
- Review PAT and OAuth grants for the actor, and tighten organization PAT access and approval policies.
- Block or monitor the source IP if the activity is clearly reconnaissance, and review whether any probed route later returned a success for the same actor.
- Escalate to incident response if the enumeration is followed by secret access, repository cloning, or ZIP downloads from the same actor or token.
References
Related rules
- GitHub Webhook Created or Configuration Changed
- GitHub API Failed Access Burst
- GitHub SAML SSO Disabled
- GitHub OAuth Application Authorized
- GitHub OAuth App Access Restrictions Disabled