GitHub SSO Recovery Codes Activity


Description

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

Query · esql

from logs-github.audit-* metadata _id, _index, _version
| where
  event.module == "github" and data_stream.dataset == "github.audit"
    and event.action in (
      "business.recovery_codes_downloaded",
      "business.recovery_codes_generated",
      "business.recovery_codes_printed",
      "business.recovery_codes_viewed",
      "business.recovery_code_used",
      "business.recovery_code_failed",
      "org.recovery_codes_downloaded",
      "org.recovery_codes_generated",
      "org.recovery_codes_printed",
      "org.recovery_codes_viewed",
      "org.recovery_code_used",
      "org.recovery_code_failed"
    )
| keep
    _id,
    _index,
    _version,
    @timestamp,
    event.action,
    user.name,
    github.org,
    github.actor_is_bot,
    github.repo,
    github.actor_ip,
    github.hashed_token,
    github.programmatic_access_type,
    github.user_agent,
    github.business

Investigation fields

Pivot points the source recommends for triage.

  • @timestamp
  • event.action
  • user.name
  • github.org
  • github.repo
  • github.actor_ip
  • github.hashed_token
  • github.programmatic_access_type
  • github.user_agent
  • github.business

Known false positives

  • Documented disaster-recovery tests. Dual-control these events and store codes offline.

Analyst notes

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.
Raw source GitHub SSO Recovery Codes Activity · Elastic TOML
Esc
Published by elastic/detection-rules ↗, licensed under Elastic License 2.0 ↗. Reproduced here unmodified.
[metadata]
creation_date = "2026/11/02"
integration = ["github"]
maturity = "production"
updated_date = "2026/11/02"

[rule]
author = ["Elastic"]
description = """
Detects viewing, downloading, printing, generating, or using GitHub enterprise or organization SSO recovery codes. These
codes bypass the IdP and are break-glass credentials.
"""
false_positives = ["Documented disaster-recovery tests. Dual-control these events and store codes offline."]
from = "now-9m"
language = "esql"
license = "Elastic License v2"
name = "GitHub SSO Recovery Codes Activity"
note = """## 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 = [
    "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",
]
risk_score = 73
rule_id = "76c4cafe-0da8-41ab-a9f5-ca95eb2e644e"
severity = "high"
tags = [
    "Domain: Cloud",
    "Domain: SaaS",
    "Platform: GitHub",
    "Use Case: Threat Detection",
    "Tactic: Credential Access",
    "Tactic: Persistence",
    "Data Source: GitHub Audit Logs",
    "Rule Type: ESQL",
    "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "esql"

query = '''
from logs-github.audit-* metadata _id, _index, _version
| where
  event.module == "github" and data_stream.dataset == "github.audit"
    and event.action in (
      "business.recovery_codes_downloaded",
      "business.recovery_codes_generated",
      "business.recovery_codes_printed",
      "business.recovery_codes_viewed",
      "business.recovery_code_used",
      "business.recovery_code_failed",
      "org.recovery_codes_downloaded",
      "org.recovery_codes_generated",
      "org.recovery_codes_printed",
      "org.recovery_codes_viewed",
      "org.recovery_code_used",
      "org.recovery_code_failed"
    )
| keep
    _id,
    _index,
    _version,
    @timestamp,
    event.action,
    user.name,
    github.org,
    github.actor_is_bot,
    github.repo,
    github.actor_ip,
    github.hashed_token,
    github.programmatic_access_type,
    github.user_agent,
    github.business
'''


[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1552"
name = "Unsecured Credentials"
reference = "https://attack.mitre.org/techniques/T1552/"


[rule.threat.tactic]
id = "TA0006"
name = "Credential Access"
reference = "https://attack.mitre.org/tactics/TA0006/"
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1078"
name = "Valid Accounts"
reference = "https://attack.mitre.org/techniques/T1078/"
[[rule.threat.technique.subtechnique]]
id = "T1078.004"
name = "Cloud Accounts"
reference = "https://attack.mitre.org/techniques/T1078/004/"



[rule.threat.tactic]
id = "TA0003"
name = "Persistence"
reference = "https://attack.mitre.org/tactics/TA0003/"

[rule.investigation_fields]
field_names = [
    "@timestamp",
    "event.action",
    "user.name",
    "github.org",
    "github.repo",
    "github.actor_ip",
    "github.hashed_token",
    "github.programmatic_access_type",
    "github.user_agent",
    "github.business",
]

Detection rules belong to the projects that publish them and remain under their own licenses. This site indexes and links to them; it claims no rights in them.