GitHub SSH or Deploy Key Added
Identifies the addition of an SSH public key to a GitHub user account or a deploy key to a repository. These keys grant
Git access over SSH, so an adversary can add one to maintain persistent repository access after the original password,
session, or token is revoked. Note that a user-level public_key.create action may not appear in a non-EMU enterprise
audit stream, where it is retained only in the per-user security log.
Elastic rule (View on GitHub)
1[metadata]
2creation_date = "2026/09/22"
3integration = ["github"]
4maturity = "production"
5updated_date = "2026/09/22"
6
7[rule]
8author = ["Elastic"]
9description = """
10Identifies the addition of an SSH public key to a GitHub user account or a deploy key to a repository. These keys grant
11Git access over SSH, so an adversary can add one to maintain persistent repository access after the original password,
12session, or token is revoked. Note that a user-level `public_key.create` action may not appear in a non-EMU enterprise
13audit stream, where it is retained only in the per-user security log.
14"""
15false_positives = [
16 """
17 Developers adding a key for a new workstation, or administrators adding an approved deploy key for CI/CD or
18 repository automation. Confirm the key, source IP, affected account or repository, and expected access level.
19 """,
20]
21from = "now-9m"
22language = "esql"
23license = "Elastic License v2"
24name = "GitHub SSH or Deploy Key Added"
25note = """## Triage and analysis
26
27> **Disclaimer**:
28> This investigation guide was created using generative AI technology and has been reviewed to improve its accuracy and relevance. While every effort has been made to ensure its quality, we recommend validating the content and adapting it to suit your specific environment and operational needs.
29
30### Investigating GitHub SSH or Deploy Key Added
31
32This rule fires on GitHub's `public_key.create` audit action, which records the addition of an SSH public key to a user account or a deploy key to a repository. Both provide durable Git access independent of the account password, making an unauthorized key a useful persistence mechanism after account or token compromise. Review the actor and source (`user.name`, `github.actor_ip`), repository context (`github.repo`), client and token (`github.user_agent`, `github.hashed_token`, `github.programmatic_access_type`), and the key's configured access in GitHub. Note that user-level `public_key.create` events may not reach `logs-github.audit-*` on non-EMU enterprises, where they are retained only in the per-user security log.
33
34### Possible investigation steps
35
36- Determine whether the event added a user SSH key or a repository deploy key. Confirm the change with the user or repository owner and verify whether `github.actor_ip` and `github.user_agent` are expected.
37- For deploy keys, verify the repository, purpose, owner, and whether write access is required. Unexpected write-enabled deploy keys should receive higher priority.
38- Geolocate `github.actor_ip` and review its ASN to check whether the source is consistent with the user's normal GitHub activity.
39- Review `github.hashed_token` and `github.programmatic_access_type` to determine whether the key was added interactively or with a PAT or OAuth token, the latter being a stronger compromise signal.
40- Correlate the same `user.name` and `github.actor_ip` with related account changes, such as unrecognized-device sign-ins, new personal access tokens, or OAuth grants, that indicate account takeover.
41- Pivot to subsequent Git activity such as clones, pushes, or archive downloads that may have used the new key.
42
43### False positive analysis
44
45- A developer adding an SSH key for a new or replacement workstation. Confirm the key, source IP, and that the user expected it before dismissing.
46- Automation or onboarding workflows that register SSH keys for a service account. Validate against deployment records and scope exceptions to the specific user where appropriate.
47- Approved deploy keys used by CI/CD systems or repository automation. Confirm the repository, key owner, documented purpose, and whether the configured read or write access is expected.
48
49### Response and remediation
50
51- If the key was not authorized by the user or repository owner, delete it immediately.
52- Reset the user's credentials and revoke active sessions if account takeover is suspected, and rotate any credentials used by affected automation.
53- Review all SSH keys, personal access tokens, and OAuth authorizations on the account and remove any others that are unexpected.
54- Hunt for Git activity that used the new key, such as clones, pushes, or archive downloads, to assess what was accessed.
55- Consider requiring SSH certificates or hardware-backed keys where policy allows, and engage incident response per your organization's playbooks if compromise is confirmed.
56"""
57references = [
58 "https://github.blog/news-insights/company-news/security-alert-new-phishing-campaign-targets-github-users/",
59 "https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account",
60 "https://docs.github.com/en/authentication/connecting-to-github-with-ssh/managing-deploy-keys",
61]
62risk_score = 21
63rule_id = "8205043a-5fd1-4dd8-be6f-55677ffe067b"
64severity = "low"
65tags = [
66 "Domain: Cloud",
67 "Domain: SaaS",
68 "Platform: GitHub",
69 "Use Case: Threat Detection",
70 "Tactic: Persistence",
71 "Data Source: Github",
72 "Data Source: GitHub Audit Logs",
73 "Rule Type: ES|QL",
74 "Resources: Investigation Guide",
75]
76timestamp_override = "event.ingested"
77type = "esql"
78
79query = '''
80from logs-github.audit-* metadata _id, _index, _version
81| where
82 event.module == "github" and data_stream.dataset == "github.audit"
83 and event.action == "public_key.create"
84| keep
85 _id,
86 _index,
87 _version,
88 @timestamp,
89 event.action,
90 user.name,
91 github.org,
92 github.repo,
93 github.actor_ip,
94 github.hashed_token,
95 github.programmatic_access_type,
96 github.user_agent
97'''
98
99
100[[rule.threat]]
101framework = "MITRE ATT&CK"
102[[rule.threat.technique]]
103id = "T1098"
104name = "Account Manipulation"
105reference = "https://attack.mitre.org/techniques/T1098/"
106[[rule.threat.technique.subtechnique]]
107id = "T1098.001"
108name = "Additional Cloud Credentials"
109reference = "https://attack.mitre.org/techniques/T1098/001/"
110
111
112
113[rule.threat.tactic]
114id = "TA0003"
115name = "Persistence"
116reference = "https://attack.mitre.org/tactics/TA0003/"
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]
Triage and analysis
Disclaimer: This investigation guide was created using generative AI technology and has been reviewed to improve its accuracy and relevance. While every effort has been made to ensure its quality, we recommend validating the content and adapting it to suit your specific environment and operational needs.
Investigating GitHub SSH or Deploy Key Added
This rule fires on GitHub's public_key.create audit action, which records the addition of an SSH public key to a user account or a deploy key to a repository. Both provide durable Git access independent of the account password, making an unauthorized key a useful persistence mechanism after account or token compromise. Review the actor and source (user.name, github.actor_ip), repository context (github.repo), client and token (github.user_agent, github.hashed_token, github.programmatic_access_type), and the key's configured access in GitHub. Note that user-level public_key.create events may not reach logs-github.audit-* on non-EMU enterprises, where they are retained only in the per-user security log.
Possible investigation steps
- Determine whether the event added a user SSH key or a repository deploy key. Confirm the change with the user or repository owner and verify whether
github.actor_ipandgithub.user_agentare expected. - For deploy keys, verify the repository, purpose, owner, and whether write access is required. Unexpected write-enabled deploy keys should receive higher priority.
- Geolocate
github.actor_ipand review its ASN to check whether the source is consistent with the user's normal GitHub activity. - Review
github.hashed_tokenandgithub.programmatic_access_typeto determine whether the key was added interactively or with a PAT or OAuth token, the latter being a stronger compromise signal. - Correlate the same
user.nameandgithub.actor_ipwith related account changes, such as unrecognized-device sign-ins, new personal access tokens, or OAuth grants, that indicate account takeover. - Pivot to subsequent Git activity such as clones, pushes, or archive downloads that may have used the new key.
False positive analysis
- A developer adding an SSH key for a new or replacement workstation. Confirm the key, source IP, and that the user expected it before dismissing.
- Automation or onboarding workflows that register SSH keys for a service account. Validate against deployment records and scope exceptions to the specific user where appropriate.
- Approved deploy keys used by CI/CD systems or repository automation. Confirm the repository, key owner, documented purpose, and whether the configured read or write access is expected.
Response and remediation
- If the key was not authorized by the user or repository owner, delete it immediately.
- Reset the user's credentials and revoke active sessions if account takeover is suspected, and rotate any credentials used by affected automation.
- Review all SSH keys, personal access tokens, and OAuth authorizations on the account and remove any others that are unexpected.
- Hunt for Git activity that used the new key, such as clones, pushes, or archive downloads, to assess what was accessed.
- Consider requiring SSH certificates or hardware-backed keys where policy allows, and engage incident response per your organization's playbooks if compromise is confirmed.
References
Related rules
- GitHub SAML SSO Disabled
- GitHub Activity on a Private Repository from an Unusual ASN
- GitHub OAuth Application Authorized
- GitHub Actions Workflow Modification Blocked
- GitHub Repository Transferred Out of Organization