LoFP LoFP / org-wide backup, secret-rotation, or inventory scripts that list secrets, hooks, and repositories. allowlist known automation tokens and user agents.

Techniques

Sample rules

GitHub API Sensitive Resource Enumeration

Description

Detects a burst of GitHub api.request events from a single non-bot actor and source IP against sensitive routes such as Actions/Dependabot/environment secrets, public keys, git trees and contents, zipball archives, organization repository and member lists, webhooks, installations, and personal access tokens. Grouping by actor and source IP and requiring a high request count spread across several distinct sensitive routes separates broad enumeration from a single high-volume endpoint. This pattern is commonly used for credential discovery and source collection after token theft. Requires GitHub Enterprise audit log streaming with API Request Events enabled.

Detection logic

from logs-github.audit-* metadata _id, _index, _version
| where
  data_stream.dataset == "github.audit" and event.action == "api.request" and
  github.actor_ip is not null and (github.actor_is_bot is not null and github.actor_is_bot == false) and
  (
    github.route like "*secrets*" or
    github.route like "*public-key*" or
    github.route like "*git/trees*" or
    github.route like "*contents*" or
    github.route like "*zipball*" or
    github.route like "*hooks*" or
    github.route like "*installations*" or
    github.route like "*members*" or
    github.route like "*outside_collaborators*" or
    github.route like "*personal-access-token*" or
    github.route == "/organizations/:organization_id/repos"
  )
| stats
  Esql.event_count = COUNT(*),
  Esql.github_route_unique_count = COUNT_DISTINCT(github.route),
  Esql.github_repo_unique_count = COUNT_DISTINCT(github.repo),
  Esql.github_route_values = VALUES(github.route),
  Esql.github_org_values = VALUES(github.org),
  Esql.github_programmatic_access_type_values = VALUES(github.programmatic_access_type),
  Esql.github_user_agent_values = VALUES(github.user_agent),
  Esql.agent_id_values = VALUES(agent.id),
  Esql.data_stream_dataset_values = VALUES(data_stream.dataset),
  Esql.data_stream_namespace_values = VALUES(data_stream.namespace),
  Esql.github_token_id_values = VALUES(github.token_id)
  by user.name, github.actor_ip, Esql.time_window = DATE_TRUNC(10 minutes, @timestamp)
| keep user.name, github.actor_ip, Esql.*
| where Esql.event_count >= 15 and Esql.github_route_unique_count >= 3