High Number of Protected Branch Force Pushes by User
Detects a high number of force push actions to protected branches by a single user within a short time frame. Adversaries may perform force pushes to overwrite commit history on protected branches, potentially leading to data loss or disruption of development workflows.
Elastic rule (View on GitHub)
1[metadata]
2creation_date = "2025/12/16"
3integration = ["github"]
4maturity = "production"
5updated_date = "2026/01/12"
6
7[rule]
8author = ["Elastic"]
9description = """
10Detects a high number of force push actions to protected branches by a single user within a short
11time frame. Adversaries may perform force pushes to overwrite commit history on protected branches,
12potentially leading to data loss or disruption of development workflows.
13"""
14from = "now-9m"
15interval = "8m"
16language = "esql"
17license = "Elastic License v2"
18name = "High Number of Protected Branch Force Pushes by User"
19note = """ ## Triage and analysis
20
21> **Disclaimer**:
22> 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.
23
24### Investigating High Number of Protected Branch Force Pushes by User
25
26This rule flags a single user performing many force pushes to protected branches in a short window, signaling aggressive history rewrites on critical repositories. Such activity can erase commits, hide unauthorized changes, and disrupt builds or releases, indicating potential data destruction or sabotage. Example: a compromised maintainer acquires elevated access and repeatedly force-pushes rewritten history to the main branch to purge prior commits, remove security fixes, and introduce a backdoor while bypassing merge protections.
27
28### Possible investigation steps
29
30- Verify the user's current and recent org/repo roles and bypass permissions, along with any recent elevation, SSO changes, or new PAT/GitHub App installations linked to the account.
31- Enumerate impacted repositories and protected branches, then reconstruct the overwritten history by comparing before/after SHAs from audit logs or local mirrors to determine what commits were removed or rewritten.
32- Assess intent and legitimacy by contacting repo owners and checking change tickets or maintenance windows for planned history rewrites, and suspend override permissions if unplanned while preserving forensic evidence.
33- Analyze sign-in and authentication telemetry around the events (IP, geo, MFA status, device, OAuth/PAT/App identifiers, off-hours) to spot account compromise indicators and pivot to other activity by the same token.
34- Review diffs of the resulting branch heads and CI/CD artifacts to detect malicious changes (e.g., removed security fixes, inserted secrets/backdoors), and check for anomalous releases or workflows triggered by the rewritten commits.
35
36### False positive analysis
37
38- An authorized maintainer conducts a planned history rewrite (rebases/resets to remove problematic commits) across protected branches in multiple repositories, legitimately invoking policy overrides and issuing many force pushes in quick succession.
39- A release owner executes an emergency rollback by resetting protected branches to a known-good commit across several repositories, causing repeated, intentional force pushes and protected-branch overrides.
40
41### Response and remediation
42
43- Immediately contain by removing the user from repo admin/maintain teams, revoking all active PATs/OAuth/App tokens linked to the account, and updating branch protection on affected branches to disallow force pushes and restrict pushes to a small trusted group.
44- Freeze each impacted protected branch by creating an annotated tag at the last known-good commit SHA prior to the force pushes and temporarily pausing CI/CD workflows that build from those branch heads.
45- Recover by restoring each branch head to the last known-good commit or signed tag from a trusted mirror/backup, verifying the target SHA, and re-enabling protections and required status checks after integrity confirmation.
46- Eradicate unauthorized changes by diffing the pre-override and post-override branch heads, reverting malicious edits, rotating repository secrets referenced in code/workflows, and removing suspicious GitHub Apps installed by the user.
47- Escalate to incident response and legal if any overwritten history includes production release branches or signed tags, if the user denies authorization, or if pushes originated from a new token/App unknown to repo owners.
48- Harden by enforcing rulesets that block force pushes and require linear history on main and release/* branches, enabling CODEOWNERS-required reviews and signed commits, limiting bypass permissions to a small admin group, and using deploy keys or CI bots with short-lived tokens for pushes.
49"""
50references = [
51 "https://www.wiz.io/blog/shai-hulud-2-0-ongoing-supply-chain-attack",
52 "https://trigger.dev/blog/shai-hulud-postmortem",
53 "https://posthog.com/blog/nov-24-shai-hulud-attack-post-mortem",
54]
55risk_score = 47
56rule_id = "0428c618-27f5-4d94-99e6-b254585aba69"
57severity = "medium"
58tags = [
59 "Domain: Cloud",
60 "Use Case: Threat Detection",
61 "Tactic: Impact",
62 "Tactic: Exfiltration",
63 "Data Source: Github",
64 "Resources: Investigation Guide",
65]
66timestamp_override = "event.ingested"
67type = "esql"
68query = '''
69from logs-github.audit-* metadata _id, _index, _version
70| where
71 data_stream.dataset == "github.audit" and
72 event.type == "change" and
73 event.action == "protected_branch.policy_override" and
74 github.category == "protected_branch" and
75 mv_contains(github.reasons.code, "force_push")
76| stats
77 Esql.event_count = COUNT(*),
78 Esql.github_org_values = values(github.org),
79 Esql.github_repo_values = values(github.repo),
80 Esql.github_overridden_codes_values = values(github.overridden_codes),
81 Esql.github_reasons_code_values = values(github.reasons.code),
82 Esql.github_reasons_message_values = values(github.reasons.message),
83 Esql.user_name_values = values(user.name),
84 Esql.agent_id_values = values(agent.id),
85 Esql.event_dataset_values = values(event.dataset),
86 Esql.data_stream_namespace_values = values(data_stream.namespace)
87
88 by user.name
89
90| keep Esql.*
91
92| where
93 Esql.event_count >= 10
94'''
95
96[[rule.threat]]
97framework = "MITRE ATT&CK"
98
99[[rule.threat.technique]]
100id = "T1485"
101name = "Data Destruction"
102reference = "https://attack.mitre.org/techniques/T1485/"
103
104[rule.threat.tactic]
105id = "TA0040"
106name = "Impact"
107reference = "https://attack.mitre.org/tactics/TA0040/"
108
109[[rule.threat]]
110framework = "MITRE ATT&CK"
111
112[[rule.threat.technique]]
113id = "T1020"
114name = "Automated Exfiltration"
115reference = "https://attack.mitre.org/techniques/T1020/"
116
117[[rule.threat.technique]]
118id = "T1567"
119name = "Exfiltration Over Web Service"
120reference = "https://attack.mitre.org/techniques/T1567/"
121
122[[rule.threat.technique.subtechnique]]
123id = "T1567.001"
124name = "Exfiltration to Code Repository"
125reference = "https://attack.mitre.org/techniques/T1567/001/"
126
127[rule.threat.tactic]
128id = "TA0010"
129name = "Exfiltration"
130reference = "https://attack.mitre.org/tactics/TA0010/"
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 High Number of Protected Branch Force Pushes by User
This rule flags a single user performing many force pushes to protected branches in a short window, signaling aggressive history rewrites on critical repositories. Such activity can erase commits, hide unauthorized changes, and disrupt builds or releases, indicating potential data destruction or sabotage. Example: a compromised maintainer acquires elevated access and repeatedly force-pushes rewritten history to the main branch to purge prior commits, remove security fixes, and introduce a backdoor while bypassing merge protections.
Possible investigation steps
- Verify the user's current and recent org/repo roles and bypass permissions, along with any recent elevation, SSO changes, or new PAT/GitHub App installations linked to the account.
- Enumerate impacted repositories and protected branches, then reconstruct the overwritten history by comparing before/after SHAs from audit logs or local mirrors to determine what commits were removed or rewritten.
- Assess intent and legitimacy by contacting repo owners and checking change tickets or maintenance windows for planned history rewrites, and suspend override permissions if unplanned while preserving forensic evidence.
- Analyze sign-in and authentication telemetry around the events (IP, geo, MFA status, device, OAuth/PAT/App identifiers, off-hours) to spot account compromise indicators and pivot to other activity by the same token.
- Review diffs of the resulting branch heads and CI/CD artifacts to detect malicious changes (e.g., removed security fixes, inserted secrets/backdoors), and check for anomalous releases or workflows triggered by the rewritten commits.
False positive analysis
- An authorized maintainer conducts a planned history rewrite (rebases/resets to remove problematic commits) across protected branches in multiple repositories, legitimately invoking policy overrides and issuing many force pushes in quick succession.
- A release owner executes an emergency rollback by resetting protected branches to a known-good commit across several repositories, causing repeated, intentional force pushes and protected-branch overrides.
Response and remediation
- Immediately contain by removing the user from repo admin/maintain teams, revoking all active PATs/OAuth/App tokens linked to the account, and updating branch protection on affected branches to disallow force pushes and restrict pushes to a small trusted group.
- Freeze each impacted protected branch by creating an annotated tag at the last known-good commit SHA prior to the force pushes and temporarily pausing CI/CD workflows that build from those branch heads.
- Recover by restoring each branch head to the last known-good commit or signed tag from a trusted mirror/backup, verifying the target SHA, and re-enabling protections and required status checks after integrity confirmation.
- Eradicate unauthorized changes by diffing the pre-override and post-override branch heads, reverting malicious edits, rotating repository secrets referenced in code/workflows, and removing suspicious GitHub Apps installed by the user.
- Escalate to incident response and legal if any overwritten history includes production release branches or signed tags, if the user denies authorization, or if pushes originated from a new token/App unknown to repo owners.
- Harden by enforcing rulesets that block force pushes and require linear history on main and release/* branches, enabling CODEOWNERS-required reviews and signed commits, limiting bypass permissions to a small admin group, and using deploy keys or CI bots with short-lived tokens for pushes.
References
Related rules
- GitHub Private Repository Turned Public
- High Number of Closed Pull Requests by User
- Several Failed Protected Branch Force Pushes by User
- GitHub Exfiltration via High Number of Repository Clones by User
- Github Activity on a Private Repository from an Unusual IP