GitHub OAuth Application Authorized

Detects when a user authorizes a GitHub OAuth application. Stolen OAuth grants persist after password changes until revoked and can clone or ZIP private repositories. This is not a GitHub App installation (integration_installation.create).

Elastic rule (View on GitHub)

  1[metadata]
  2creation_date = "2026/09/24"
  3integration = ["github"]
  4maturity = "production"
  5updated_date = "2026/09/24"
  6
  7[rule]
  8author = ["Elastic"]
  9description = """
 10Detects when a user authorizes a GitHub OAuth application. Stolen OAuth grants persist after password changes until
 11revoked and can clone or ZIP private repositories. This is not a GitHub App installation
 12(integration_installation.create).
 13"""
 14false_positives = [
 15    """
 16    Developers authorizing approved internal or vendor OAuth apps. Maintain an allowlist of expected application names
 17    and investigate first-time grants from unusual IPs or user agents.
 18    """,
 19]
 20from = "now-9m"
 21language = "esql"
 22license = "Elastic License v2"
 23name = "GitHub OAuth Application Authorized"
 24note = """## Triage and analysis
 25
 26### Investigating GitHub OAuth Application Authorized
 27
 28`oauth_authorization.create` is a user grant of an OAuth App. It is distinct from installing a GitHub App. After a grant, look for `git.clone` or `repo.download_zip` with `programmatic_access_type` of OAuth access token.
 29
 30### Possible investigation steps
 31
 32- Identify `user.name`, `github.oauth_application_name` / `github.oauth_application_id`, `github.actor_ip`, and `github.user_agent`.
 33- Confirm the app is approved by the organization. Review requested scopes.
 34- Pivot to clone, ZIP, and `api.request` activity from the same user shortly after the grant.
 35
 36### False positive analysis
 37
 38- First-time login to an approved CI, IDE, or SaaS integration.
 39
 40### Response and remediation
 41
 42- If unauthorized, revoke the OAuth grant and the application's tokens, then force a password reset and session invalidation.
 43- Review org third-party application restrictions.
 44"""
 45references = [
 46    "https://securitylabs.datadoghq.com/articles/mapping-out-your-unknown-threat-hunters-guide-to-github/",
 47    "https://github.blog/news-insights/company-news/security-alert-stolen-oauth-user-tokens/",
 48    "https://github.blog/news-insights/company-news/security-alert-new-phishing-campaign-targets-github-users/",
 49    "https://docs.github.com/en/apps/oauth-apps/using-oauth-apps/authorizing-oauth-apps",
 50]
 51risk_score = 21
 52rule_id = "3e8ae55e-5b66-40dc-b747-c314cf9fcef8"
 53severity = "low"
 54tags = [
 55    "Domain: Cloud",
 56    "Domain: SaaS",
 57    "Domain: Identity",
 58    "Platform: GitHub",
 59    "Profile: Beta",
 60    "Use Case: Threat Detection",
 61    "Tactic: Credential Access",
 62    "Tactic: Persistence",
 63    "Threat: OAuth App Consent",
 64    "Data Source: Github",
 65    "Data Source: GitHub Audit Logs",
 66    "Rule Type: ESQL",
 67    "Resources: Investigation Guide",
 68]
 69timestamp_override = "event.ingested"
 70type = "esql"
 71
 72query = '''
 73from logs-github.audit-* metadata _id, _index, _version
 74| where
 75  event.module == "github" and data_stream.dataset == "github.audit"
 76    and event.action == "oauth_authorization.create"
 77| keep
 78    _id,
 79    _index,
 80    _version,
 81    @timestamp,
 82    event.action,
 83    user.name,
 84    github.org,
 85    github.repo,
 86    github.actor_ip,
 87    github.hashed_token,
 88    github.oauth_application_name,
 89    github.oauth_application_id,
 90    github.programmatic_access_type,
 91    github.user_agent,
 92    github.name
 93'''
 94
 95
 96[[rule.threat]]
 97framework = "MITRE ATT&CK"
 98[[rule.threat.technique]]
 99id = "T1078"
100name = "Valid Accounts"
101reference = "https://attack.mitre.org/techniques/T1078/"
102[[rule.threat.technique.subtechnique]]
103id = "T1078.004"
104name = "Cloud Accounts"
105reference = "https://attack.mitre.org/techniques/T1078/004/"
106
107
108
109[rule.threat.tactic]
110id = "TA0003"
111name = "Persistence"
112reference = "https://attack.mitre.org/tactics/TA0003/"
113[[rule.threat]]
114framework = "MITRE ATT&CK"
115[[rule.threat.technique]]
116id = "T1528"
117name = "Steal Application Access Token"
118reference = "https://attack.mitre.org/techniques/T1528/"
119
120
121[rule.threat.tactic]
122id = "TA0006"
123name = "Credential Access"
124reference = "https://attack.mitre.org/tactics/TA0006/"
125
126[rule.investigation_fields]
127field_names = [
128    "@timestamp",
129    "event.action",
130    "user.name",
131    "github.org",
132    "github.repo",
133    "github.actor_ip",
134    "github.hashed_token",
135    "github.oauth_application_name",
136    "github.oauth_application_id",
137    "github.programmatic_access_type",
138    "github.user_agent",
139    "github.name",
140]

Triage and analysis

Investigating GitHub OAuth Application Authorized

oauth_authorization.create is a user grant of an OAuth App. It is distinct from installing a GitHub App. After a grant, look for git.clone or repo.download_zip with programmatic_access_type of OAuth access token.

Possible investigation steps

  • Identify user.name, github.oauth_application_name / github.oauth_application_id, github.actor_ip, and github.user_agent.
  • Confirm the app is approved by the organization. Review requested scopes.
  • Pivot to clone, ZIP, and api.request activity from the same user shortly after the grant.

False positive analysis

  • First-time login to an approved CI, IDE, or SaaS integration.

Response and remediation

  • If unauthorized, revoke the OAuth grant and the application's tokens, then force a password reset and session invalidation.
  • Review org third-party application restrictions.

References

Related rules

to-top