GitHub Secret Scanning Push Protection Bypassed or Disabled

Detects bypass of GitHub secret scanning push protection, approval of a bypass request, or disabling push protection at enterprise, organization, or repository scope. This is separate from turning secret scanning off. Bypass means a detected secret was allowed into the repository — the pattern used after tj-actions and similar CI secret-dump attacks.

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 bypass of GitHub secret scanning push protection, approval of a bypass request, or disabling push protection at
 11enterprise, organization, or repository scope. This is separate from turning secret scanning off. Bypass means a
 12detected secret was allowed into the repository — the pattern used after tj-actions and similar CI secret-dump attacks.
 13"""
 14false_positives = [
 15    """
 16    Documented test of push protection using a dummy token, or a temporary disable while fixing a noisy pattern.
 17    Re-enable afterward and confirm no live secret was pushed.
 18    """,
 19]
 20from = "now-9m"
 21language = "esql"
 22license = "Elastic License v2"
 23name = "GitHub Secret Scanning Push Protection Bypassed or Disabled"
 24note = """## Triage and analysis
 25
 26### Investigating GitHub Secret Scanning Push Protection Bypassed or Disabled
 27
 28`secret_scanning_push_protection.bypass` fires when a user pushes a detected secret anyway. `secret_scanning_push_protection_request.approve` is a reviewer allowing that push. `business_secret_scanning_push_protection.disable`, `org.secret_scanning_push_protection_disable`, and `repository_secret_scanning_push_protection.disable` turn the control off at enterprise, organization, and repository scope respectively (the `*_new_repos_disable` actions turn it off for newly created repositories). This is separate from disabling secret scanning itself, which is covered by the `GitHub Secret Scanning Disabled` rule.
 29
 30### Possible investigation steps
 31
 32- Identify `user.name`, `github.repo`, `event.action`, and `github.secret_type`, and confirm whether the actor is expected to bypass or administer this control.
 33- Review `github.actor_ip` and `github.user_agent` to validate the source of the change, and pivot on `github.hashed_token` / `github.programmatic_access_type` to determine whether it was performed via the UI or a token.
 34- For a bypass or approved bypass: inspect the commit that landed, rotate the secret type reported in `github.secret_type`, and check workflow logs for printed credentials.
 35- For a disable: re-enable push protection and review commits pushed during the window it was off.
 36- Correlate with other control changes in the same window (secret scanning disabled, bypass-list additions, new owners, PAT grants) that may indicate broader tampering.
 37
 38### False positive analysis
 39
 40- Security team testing push protection with a known dummy value during an approved exercise.
 41- A noisy custom pattern that maintainers temporarily disable. Confirm no live secret was pushed and that the control is re-enabled afterward.
 42
 43### Response and remediation
 44
 45- Re-enable push protection at the affected scope. Rotate any secret that was bypassed.
 46- Restrict who can bypass or disable the control, and review the push-protection bypass list.
 47- Review Actions secrets and PATs created in the same window, and confirm the acting account is not compromised.
 48"""
 49references = [
 50    "https://github.com/SigmaHQ/sigma/blob/master/rules/application/github/audit/github_push_protection_bypass_detected.yml",
 51    "https://docs.github.com/en/code-security/secret-scanning/working-with-secret-scanning-and-push-protection/working-with-push-protection-from-the-command-line",
 52]
 53risk_score = 47
 54rule_id = "0b026848-9d06-44ba-8a56-6af27790452d"
 55severity = "medium"
 56tags = [
 57    "Domain: Cloud",
 58    "Domain: SaaS",
 59    "Platform: GitHub",
 60    "Use Case: Threat Detection",
 61    "Tactic: Defense Evasion",
 62    "Data Source: Github",
 63    "Data Source: GitHub Audit Logs",
 64    "Rule Type: ESQL",
 65    "Resources: Investigation Guide",
 66]
 67timestamp_override = "event.ingested"
 68type = "esql"
 69
 70query = '''
 71from logs-github.audit-* metadata _id, _index, _version
 72| where
 73  data_stream.dataset == "github.audit"
 74    and event.action in (
 75      "secret_scanning_push_protection.bypass",
 76      "secret_scanning_push_protection_request.approve",
 77      "business_secret_scanning_push_protection.disable",
 78      "business_secret_scanning_push_protection.disabled_for_new_repos",
 79      "org.secret_scanning_push_protection_disable",
 80      "org.secret_scanning_push_protection_new_repos_disable",
 81      "repository_secret_scanning_push_protection.disable"
 82    )
 83| keep
 84    _id,
 85    _index,
 86    _version,
 87    @timestamp,
 88    event.action,
 89    user.name,
 90    github.org,
 91    github.repo,
 92    github.actor_ip,
 93    github.hashed_token,
 94    github.programmatic_access_type,
 95    github.user_agent,
 96    github.secret_type
 97'''
 98
 99
100[[rule.threat]]
101framework = "MITRE ATT&CK"
102[[rule.threat.technique]]
103id = "T1562"
104name = "Impair Defenses"
105reference = "https://attack.mitre.org/techniques/T1562/"
106[[rule.threat.technique.subtechnique]]
107id = "T1562.001"
108name = "Disable or Modify Tools"
109reference = "https://attack.mitre.org/techniques/T1562/001/"
110
111
112
113[rule.threat.tactic]
114id = "TA0005"
115name = "Defense Evasion"
116reference = "https://attack.mitre.org/tactics/TA0005/"
117
118[rule.investigation_fields]
119field_names = [
120    "@timestamp",
121    "event.action",
122    "user.name",
123    "github.org",
124    "github.repo",
125    "github.actor_ip",
126    "github.hashed_token",
127    "github.programmatic_access_type",
128    "github.user_agent",
129    "github.secret_type",
130]

Triage and analysis

Investigating GitHub Secret Scanning Push Protection Bypassed or Disabled

secret_scanning_push_protection.bypass fires when a user pushes a detected secret anyway. secret_scanning_push_protection_request.approve is a reviewer allowing that push. business_secret_scanning_push_protection.disable, org.secret_scanning_push_protection_disable, and repository_secret_scanning_push_protection.disable turn the control off at enterprise, organization, and repository scope respectively (the *_new_repos_disable actions turn it off for newly created repositories). This is separate from disabling secret scanning itself, which is covered by the GitHub Secret Scanning Disabled rule.

Possible investigation steps

  • Identify user.name, github.repo, event.action, and github.secret_type, and confirm whether the actor is expected to bypass or administer this control.
  • Review github.actor_ip and github.user_agent to validate the source of the change, and pivot on github.hashed_token / github.programmatic_access_type to determine whether it was performed via the UI or a token.
  • For a bypass or approved bypass: inspect the commit that landed, rotate the secret type reported in github.secret_type, and check workflow logs for printed credentials.
  • For a disable: re-enable push protection and review commits pushed during the window it was off.
  • Correlate with other control changes in the same window (secret scanning disabled, bypass-list additions, new owners, PAT grants) that may indicate broader tampering.

False positive analysis

  • Security team testing push protection with a known dummy value during an approved exercise.
  • A noisy custom pattern that maintainers temporarily disable. Confirm no live secret was pushed and that the control is re-enabled afterward.

Response and remediation

  • Re-enable push protection at the affected scope. Rotate any secret that was bypassed.
  • Restrict who can bypass or disable the control, and review the push-protection bypass list.
  • Review Actions secrets and PATs created in the same window, and confirm the acting account is not compromised.

References

Related rules

to-top