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_values and Esql.github_programmatic_access_type_values, and confirm whether the token belongs to known automation.
  • 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.
  • 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.
  • 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

to-top