GitHub SSO Recovery Codes Activity

Detects viewing, downloading, printing, generating, or using GitHub enterprise or organization SSO recovery codes. These codes bypass the IdP and are break-glass credentials.

Elastic rule (View on GitHub)

  1[metadata]
  2creation_date = "2026/11/02"
  3integration = ["github"]
  4maturity = "production"
  5updated_date = "2026/11/02"
  6
  7[rule]
  8author = ["Elastic"]
  9description = """
 10Detects viewing, downloading, printing, generating, or using GitHub enterprise or organization SSO recovery codes. These
 11codes bypass the IdP and are break-glass credentials.
 12"""
 13false_positives = ["Documented disaster-recovery tests. Dual-control these events and store codes offline."]
 14from = "now-9m"
 15language = "esql"
 16license = "Elastic License v2"
 17name = "GitHub SSO Recovery Codes Activity"
 18note = """## Triage and analysis
 19
 20### Investigating GitHub SSO Recovery Codes Activity
 21
 22Recovery-code events are rare. Download/view/print/generate often precede an SSO bypass. Use/fail events indicate an actual sign-in attempt with a recovery code.
 23
 24### Possible investigation steps
 25
 26- Identify `user.name`, `event.action`, and `github.actor_ip`.
 27- Correlate with `business.disable_saml` / MFA disable and new owner invites.
 28
 29### False positive analysis
 30
 31- Scheduled recovery-code rotation with two-person integrity.
 32
 33### Response and remediation
 34
 35- Rotate recovery codes, review SSO configuration, and force re-authentication of enterprise owners.
 36"""
 37references = [
 38    "https://docs.github.com/en/enterprise-cloud@latest/admin/identity-and-access-management/managing-recovery-codes-for-your-enterprise/downloading-your-enterprise-accounts-single-sign-on-recovery-codes",
 39]
 40risk_score = 73
 41rule_id = "76c4cafe-0da8-41ab-a9f5-ca95eb2e644e"
 42severity = "high"
 43tags = [
 44    "Domain: Cloud",
 45    "Domain: SaaS",
 46    "Platform: GitHub",
 47    "Use Case: Threat Detection",
 48    "Tactic: Credential Access",
 49    "Tactic: Persistence",
 50    "Data Source: GitHub Audit Logs",
 51    "Rule Type: ESQL",
 52    "Resources: Investigation Guide",
 53]
 54timestamp_override = "event.ingested"
 55type = "esql"
 56
 57query = '''
 58from logs-github.audit-* metadata _id, _index, _version
 59| where
 60  event.module == "github" and data_stream.dataset == "github.audit"
 61    and event.action in (
 62      "business.recovery_codes_downloaded",
 63      "business.recovery_codes_generated",
 64      "business.recovery_codes_printed",
 65      "business.recovery_codes_viewed",
 66      "business.recovery_code_used",
 67      "business.recovery_code_failed",
 68      "org.recovery_codes_downloaded",
 69      "org.recovery_codes_generated",
 70      "org.recovery_codes_printed",
 71      "org.recovery_codes_viewed",
 72      "org.recovery_code_used",
 73      "org.recovery_code_failed"
 74    )
 75| keep
 76    _id,
 77    _index,
 78    _version,
 79    @timestamp,
 80    event.action,
 81    user.name,
 82    github.org,
 83    github.actor_is_bot,
 84    github.repo,
 85    github.actor_ip,
 86    github.hashed_token,
 87    github.programmatic_access_type,
 88    github.user_agent,
 89    github.business
 90'''
 91
 92
 93[[rule.threat]]
 94framework = "MITRE ATT&CK"
 95[[rule.threat.technique]]
 96id = "T1552"
 97name = "Unsecured Credentials"
 98reference = "https://attack.mitre.org/techniques/T1552/"
 99
100
101[rule.threat.tactic]
102id = "TA0006"
103name = "Credential Access"
104reference = "https://attack.mitre.org/tactics/TA0006/"
105[[rule.threat]]
106framework = "MITRE ATT&CK"
107[[rule.threat.technique]]
108id = "T1078"
109name = "Valid Accounts"
110reference = "https://attack.mitre.org/techniques/T1078/"
111[[rule.threat.technique.subtechnique]]
112id = "T1078.004"
113name = "Cloud Accounts"
114reference = "https://attack.mitre.org/techniques/T1078/004/"
115
116
117
118[rule.threat.tactic]
119id = "TA0003"
120name = "Persistence"
121reference = "https://attack.mitre.org/tactics/TA0003/"
122
123[rule.investigation_fields]
124field_names = [
125    "@timestamp",
126    "event.action",
127    "user.name",
128    "github.org",
129    "github.repo",
130    "github.actor_ip",
131    "github.hashed_token",
132    "github.programmatic_access_type",
133    "github.user_agent",
134    "github.business",
135]

Triage and analysis

Investigating GitHub SSO Recovery Codes Activity

Recovery-code events are rare. Download/view/print/generate often precede an SSO bypass. Use/fail events indicate an actual sign-in attempt with a recovery code.

Possible investigation steps

  • Identify user.name, event.action, and github.actor_ip.
  • Correlate with business.disable_saml / MFA disable and new owner invites.

False positive analysis

  • Scheduled recovery-code rotation with two-person integrity.

Response and remediation

  • Rotate recovery codes, review SSO configuration, and force re-authentication of enterprise owners.

References

Related rules

to-top