GitHub Secret Scanning Alert for a Publicly Leaked Secret


Description

Detects GitHub secret scanning creating an alert for a secret that it has determined is publicly leaked ("github.publicly_leaked == true"). Unlike a generic secret-scanning finding, a publicly leaked secret means GitHub observed the credential exposed outside the repository's access boundary (for example in a public repository, gist, or other public location), so it should be treated as a confirmed credential compromise requiring immediate rotation rather than a low-signal scanner event. Gating on the public-leak flag also removes most of the noise from dummy strings and test fixtures, which are typically confined to private repositories and are not flagged as publicly leaked.

Query · esql

from logs-github.audit-* metadata _id, _index, _version
| where
  event.module == "github" and data_stream.dataset == "github.audit"
    and event.action == "secret_scanning_alert.create"
    and github.publicly_leaked == true
| keep
    _id,
    _index,
    _version,
    @timestamp,
    event.action,
    user.name,
    github.org,
    github.repo,
    github.actor_ip,
    github.hashed_token,
    github.programmatic_access_type,
    github.user_agent,
    github.secret_type,
    github.secret_type_display_name,
    github.publicly_leaked,
    github.multi_repo

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.secret_type
  • github.secret_type_display_name
  • github.publicly_leaked
  • github.multi_repo

Known false positives

  • Example or dummy tokens that are themselves committed to a public repository can still be flagged as publicly leaked. Tune by repository, pattern name (`github.secret_type`), or known test org when such keys are expected.

Analyst notes

Investigating GitHub Secret Scanning Alert for a Publicly Leaked Secret

secret_scanning_alert.create with github.publicly_leaked == true means GitHub determined the matched secret is exposed in a public location, not just committed to the repository. Treat the credential as compromised and rotate it immediately.

Possible investigation steps

  • Identify the exposed credential type from github.secret_type / github.secret_type_display_name and the affected github.repo and github.org.
  • Review github.multi_repo; if true, the same secret was detected across multiple repositories, widening the blast radius.
  • Identify the committer via user.name (vs the github service actor) and corroborate with github.actor_ip and github.user_agent.
  • Determine the source and scope of the public exposure and whether the secret grants access to production systems.

False positive analysis

  • Example or dummy keys intentionally published to a public repository can be flagged as publicly leaked. Scope these by repository or github.secret_type.

Response and remediation

  • Revoke and rotate the exposed credential immediately, then invalidate any sessions or tokens derived from it.
  • Remove the secret from git history if required by policy and audit for any use of the credential prior to rotation.
Raw source GitHub Secret Scanning Alert for a Publicly Leaked Secret · 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 GitHub secret scanning creating an alert for a secret that it has determined is publicly leaked
("github.publicly_leaked == true"). Unlike a generic secret-scanning finding, a publicly leaked secret means GitHub
observed the credential exposed outside the repository's access boundary (for example in a public repository, gist, or
other public location), so it should be treated as a confirmed credential compromise requiring immediate rotation
rather than a low-signal scanner event. Gating on the public-leak flag also removes most of the noise from dummy
strings and test fixtures, which are typically confined to private repositories and are not flagged as publicly
leaked.
"""
false_positives = [
    """
    Example or dummy tokens that are themselves committed to a public repository can still be flagged as publicly
    leaked. Tune by repository, pattern name (`github.secret_type`), or known test org when such keys are expected.
    """,
]
from = "now-9m"
language = "esql"
license = "Elastic License v2"
name = "GitHub Secret Scanning Alert for a Publicly Leaked Secret"
note = """## Triage and analysis

### Investigating GitHub Secret Scanning Alert for a Publicly Leaked Secret

`secret_scanning_alert.create` with `github.publicly_leaked == true` means GitHub determined the matched secret is exposed in a public location, not just committed to the repository. Treat the credential as compromised and rotate it immediately.

### Possible investigation steps

- Identify the exposed credential type from `github.secret_type` / `github.secret_type_display_name` and the affected `github.repo` and `github.org`.
- Review `github.multi_repo`; if true, the same secret was detected across multiple repositories, widening the blast radius.
- Identify the committer via `user.name` (vs the `github` service actor) and corroborate with `github.actor_ip` and `github.user_agent`.
- Determine the source and scope of the public exposure and whether the secret grants access to production systems.

### False positive analysis

- Example or dummy keys intentionally published to a public repository can be flagged as publicly leaked. Scope these by repository or `github.secret_type`.

### Response and remediation

- Revoke and rotate the exposed credential immediately, then invalidate any sessions or tokens derived from it.
- Remove the secret from git history if required by policy and audit for any use of the credential prior to rotation.
"""
references = ["https://docs.github.com/en/code-security/secret-scanning/introduction/about-secret-scanning"]
risk_score = 73
rule_id = "305f8b49-ac0a-4f08-82fe-560cd30d66fd"
severity = "high"
tags = [
    "Domain: Cloud",
    "Domain: SaaS",
    "Platform: GitHub",
    "Use Case: Threat Detection",
    "Tactic: Credential Access",
    "Data Source: GitHub Audit Logs",
    "Service: GitHub Code Scanning",
    "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 == "secret_scanning_alert.create"
    and github.publicly_leaked == true
| keep
    _id,
    _index,
    _version,
    @timestamp,
    event.action,
    user.name,
    github.org,
    github.repo,
    github.actor_ip,
    github.hashed_token,
    github.programmatic_access_type,
    github.user_agent,
    github.secret_type,
    github.secret_type_display_name,
    github.publicly_leaked,
    github.multi_repo
'''


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



[rule.threat.tactic]
id = "TA0006"
name = "Credential Access"
reference = "https://attack.mitre.org/tactics/TA0006/"

[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.secret_type",
    "github.secret_type_display_name",
    "github.publicly_leaked",
    "github.multi_repo",
]

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.