# [HIGH] kubernetes-el Compromised: How a Pwn Request Exploited a Popular Emacs Package

**Source:** StepSecurity
**Published:** 2026-03-11
**Article:** https://www.stepsecurity.io/blog/kubernetes-el-compromised-how-a-pwn-request-exploited-a-popular-emacs-package

## Threat Profile

Back to Blog Threat Intel kubernetes-el Compromised: How a Pwn Request Exploited a Popular Emacs Package On March 5, 2026, a threat actor exploited a classic "Pwn Request" vulnerability in the CI workflow of kubernetes-el/kubernetes-el, a popular Emacs package for managing Kubernetes clusters. The attacker stole the repository's GITHUB_TOKEN (with full write permissions), exfiltrated CI/CD secrets, defaced the repository, and injected destructive code Varun Sharma View LinkedIn March 9, 2026
Sha…

## Indicators of Compromise (high-fidelity only)

- **Domain (defanged):** `webhook.site`
- **SHA1:** `929c6399c4fde4fe236bd6712b2c53f750d9ad3a`

## MITRE ATT&CK Techniques

- **T1071** — Application Layer Protocol
- **T1027** — Obfuscated Files or Information
- **T1204.002** — User Execution: Malicious File
- **T1567.002** — Exfiltration to Cloud Storage / Web Service
- **T1059.004** — Command and Scripting Interpreter: Unix Shell
- **T1552.001** — Unsecured Credentials: Credentials In Files
- **T1003** — OS Credential Dumping
- **T1195.002** — Compromise Software Supply Chain
- **T1059.006** — Command and Scripting Interpreter: Python
- **T1105** — Ingress Tool Transfer
- **T1485** — Data Destruction
- **T1195.001** — Compromise Software Supply Chain: Compromise Software Dependencies and Development Tools

## Kill chain phases observed

_(none detected from narrative keywords)_

## Recommended hunts

### Exfiltration to kubernetes-el attacker webhook.site UUIDs (Pwn Request payload)

`UC_475_3` · phase: **c2** · confidence: **High** · AI-generated for this article

**Splunk SPL (CIM):**
```spl
| tstats summariesonly=true count min(_time) as firstTime max(_time) as lastTime from datamodel=Web.Web where (Web.url="*webhook.site/18c6f9e6-1dce-4b6a-975a-4f0fe0114f65*" OR Web.url="*webhook.site/2a7334c9-64a7-48cf-8b22-409028d50d9d*" OR Web.dest="webhook.site") by Web.src Web.dest Web.url Web.user Web.http_method Web.http_user_agent | `drop_dm_object_name(Web)` | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)` | append [| tstats summariesonly=true count min(_time) as firstTime max(_time) as lastTime from datamodel=Endpoint.Processes where (Processes.process="*18c6f9e6-1dce-4b6a-975a-4f0fe0114f65*" OR Processes.process="*2a7334c9-64a7-48cf-8b22-409028d50d9d*" OR Processes.process="*webhook.site*" Processes.parent_process_name IN ("bash","sh","make","python3","curl","Runner.Worker")) by Processes.dest Processes.user Processes.process Processes.parent_process_name Processes.process_name | `drop_dm_object_name(Processes)`]
```

**Defender KQL:**
```kql
let _uuids = dynamic(["18c6f9e6-1dce-4b6a-975a-4f0fe0114f65","2a7334c9-64a7-48cf-8b22-409028d50d9d"]);
union isfuzzy=true
  (DeviceNetworkEvents
    | where Timestamp > ago(30d)
    | where RemoteUrl has_any (_uuids) or (RemoteUrl has "webhook.site" and InitiatingProcessFileName in~ ("curl","curl.exe","wget","wget.exe","python3","python","powershell.exe","pwsh.exe","node"))
    | project Timestamp, DeviceName, RemoteUrl, RemoteIP, InitiatingProcessFileName, InitiatingProcessCommandLine, InitiatingProcessAccountName, Source = "DeviceNetworkEvents"),
  (DeviceProcessEvents
    | where Timestamp > ago(30d)
    | where ProcessCommandLine has_any (_uuids)
       or (ProcessCommandLine has "webhook.site" and ProcessCommandLine has_any ("curl","wget","-d ","--upload-file","-X PUT"))
    | project Timestamp, DeviceName, AccountName, FileName, ProcessCommandLine, InitiatingProcessFileName, InitiatingProcessCommandLine, Source = "DeviceProcessEvents")
| order by Timestamp desc
```

### Cacheract memdump.py download/execution on CI runner or developer host

`UC_475_4` · phase: **install** · confidence: **High** · AI-generated for this article

**Splunk SPL (CIM):**
```spl
| tstats summariesonly=true count min(_time) as firstTime max(_time) as lastTime from datamodel=Endpoint.Processes where (Processes.process="*AdnaneKhan/Cacheract*" OR Processes.process="*Cacheract/refs/heads/main/assets/memdump.py*" OR Processes.process="*b0d8565fa1ac52c28899c0cfc880d59943bc04ea/assets/memdump.py*" OR Processes.process="*30e525b776c409e03c2d6f328f254965/raw/memdump.py*" OR (Processes.process="*memdump.py*" AND Processes.process="*sudo*" AND Processes.process="*python*")) by Processes.dest Processes.user Processes.process Processes.parent_process_name Processes.process_name Processes.process_hash | `drop_dm_object_name(Processes)` | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)`
```

**Defender KQL:**
```kql
let _markers = dynamic([
  "AdnaneKhan/Cacheract",
  "Cacheract/refs/heads/main/assets/memdump.py",
  "b0d8565fa1ac52c28899c0cfc880d59943bc04ea/assets/memdump.py",
  "30e525b776c409e03c2d6f328f254965/raw/memdump.py",
  "jump-kept-freckles@duck.com",
  "quicktrinny"
]);
union isfuzzy=true
  (DeviceProcessEvents
    | where Timestamp > ago(30d)
    | where ProcessCommandLine has_any (_markers)
       or (ProcessCommandLine has "memdump.py" and ProcessCommandLine has "sudo" and ProcessCommandLine has_any ("python3","python")
           and ProcessCommandLine has_any ("ghs_","isSecret","tr -d"))
    | project Timestamp, DeviceName, AccountName, FileName, FolderPath, ProcessCommandLine, InitiatingProcessFileName, InitiatingProcessCommandLine, InitiatingProcessParentFileName),
  (DeviceNetworkEvents
    | where Timestamp > ago(30d)
    | where RemoteUrl has_any ("AdnaneKhan/Cacheract","Cacheract/refs/heads/main/assets/memdump.py","b0d8565fa1ac52c28899c0cfc880d59943bc04ea","30e525b776c409e03c2d6f328f254965")
    | project Timestamp, DeviceName, RemoteUrl, RemoteIP, InitiatingProcessFileName, InitiatingProcessCommandLine),
  (DeviceFileEvents
    | where Timestamp > ago(30d)
    | where FileName =~ "memdump.py" or FolderPath has "Cacheract" or FileName =~ "funny.sh"
    | project Timestamp, DeviceName, FolderPath, FileName, SHA256, InitiatingProcessFileName, InitiatingProcessCommandLine, InitiatingProcessAccountName)
| order by Timestamp desc
```

### Compromised kubernetes.el destructive payload — Emacs spawning `rm -rf / --no-preserve-root`

`UC_475_5` · phase: **actions** · confidence: **High** · AI-generated for this article

**Splunk SPL (CIM):**
```spl
| tstats summariesonly=true count min(_time) as firstTime max(_time) as lastTime from datamodel=Endpoint.Processes where (Processes.parent_process_name IN ("emacs","emacs-gtk","emacs-nox","emacs.exe","runemacs.exe","emacsclient","emacsclient.exe") OR Processes.parent_process="*emacs*") AND Processes.process_name IN ("sh","bash","zsh","dash","sudo","rm","cmd.exe","powershell.exe") AND (Processes.process="*rm -rf /*" OR Processes.process="*--no-preserve-root*" OR Processes.process="*sudo rm -rf /*" OR Processes.process="*kubernetes.el*") by Processes.dest Processes.user Processes.process Processes.parent_process Processes.parent_process_name Processes.process_name | `drop_dm_object_name(Processes)` | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)` | append [| tstats summariesonly=true count min(_time) as firstTime max(_time) as lastTime from datamodel=Endpoint.Filesystem where (Endpoint.Filesystem.file_name="kubernetes.el" OR Endpoint.Filesystem.file_path="*kubernetes-el*kubernetes.el") by Endpoint.Filesystem.dest Endpoint.Filesystem.user Endpoint.Filesystem.file_path Endpoint.Filesystem.file_hash | `drop_dm_object_name(Filesystem)`]
```

**Defender KQL:**
```kql
union isfuzzy=true
  (DeviceProcessEvents
    | where Timestamp > ago(30d)
    | where InitiatingProcessFileName in~ ("emacs","emacs-gtk","emacs-nox","emacs.exe","runemacs.exe","emacsclient","emacsclient.exe")
         or InitiatingProcessParentFileName in~ ("emacs","emacs-gtk","emacs-nox","emacs.exe","runemacs.exe")
    | where FileName in~ ("sh","bash","zsh","dash","sudo","rm","cmd.exe","powershell.exe","pwsh.exe")
    | where ProcessCommandLine has "rm" and ProcessCommandLine has "-rf" and ProcessCommandLine has "/"
         and (ProcessCommandLine has "--no-preserve-root" or ProcessCommandLine has "|| rm -rf /" or ProcessCommandLine has "sudo rm -rf /")
    | project Timestamp, DeviceName, AccountName, FileName, ProcessCommandLine, InitiatingProcessFileName, InitiatingProcessCommandLine, InitiatingProcessParentFileName),
  (DeviceFileEvents
    | where Timestamp between (datetime(2026-03-05T04:32:00Z) .. ago(0h))
    | where FileName =~ "kubernetes.el"
    | where FolderPath has_any (@"/.emacs.d/",@"/elpa/",@"/melpa/",@"kubernetes-el",@"\.emacs.d\\",@"\elpa\\")
    | project Timestamp, DeviceName, FolderPath, FileName, SHA256, InitiatingProcessFileName, InitiatingProcessCommandLine, InitiatingProcessAccountName)
```

### Article-specific behavioural hunt — kubernetes-el Compromised: How a Pwn Request Exploited a Popular Emacs Package

`UC_475_2` · phase: **exploit** · confidence: **High**

**Splunk SPL (CIM):**
```spl
``` Article-specific bespoke detection — kubernetes-el Compromised: How a Pwn Request Exploited a Popular Emacs Package ```
| tstats `summariesonly` count earliest(_time) AS firstTime latest(_time) AS lastTime
    from datamodel=Endpoint.Processes
    where (Processes.process_name IN ("funny.sh","memdump.py"))
    by Processes.dest, Processes.user, Processes.process_name,
       Processes.process, Processes.parent_process_name, Processes.process_path
| `drop_dm_object_name(Processes)`
| `security_content_ctime(firstTime)`
| append [
| tstats `summariesonly` count
    from datamodel=Endpoint.Filesystem
    where Filesystem.action IN ("created","modified")
      AND (Filesystem.file_path="*/tmp/secrets*" OR Filesystem.file_name IN ("funny.sh","memdump.py"))
    by Filesystem.dest, Filesystem.user, Filesystem.process_name,
       Filesystem.file_path, Filesystem.file_name
| `drop_dm_object_name(Filesystem)`
]
```

**Defender KQL:**
```kql
// Article-specific bespoke detection — kubernetes-el Compromised: How a Pwn Request Exploited a Popular Emacs Package
// Hunts the actual binaries / paths / commandline fragments named
// in the article instead of a generic technique-class template.
DeviceProcessEvents
| where Timestamp > ago(30d)
| where (FileName in~ ("funny.sh", "memdump.py"))
| project Timestamp, DeviceName, AccountName, FileName,
          FolderPath, ProcessCommandLine,
          InitiatingProcessFileName, InitiatingProcessCommandLine
| order by Timestamp desc

// File-creation events for the named binaries / paths
DeviceFileEvents
| where Timestamp > ago(30d)
| where ActionType in ("FileCreated","FileModified")
| where (FolderPath has_any ("/tmp/secrets") or FileName in~ ("funny.sh", "memdump.py"))
| project Timestamp, DeviceName, AccountName, FolderPath,
          FileName, ActionType, InitiatingProcessFileName,
          InitiatingProcessCommandLine
| order by Timestamp desc
```

### IOC-driven hunts (use shared templates)

These are standard IOC-substitution hunts — the canonical SPL and KQL live once in [`_TEMPLATES.md`](../_TEMPLATES.md), so we don't repeat the same boilerplate on every CVE / hash / network-IOC briefing.

- **Network connections to article IPs / domains** ([template](../_TEMPLATES.md#network-ioc)) — phase: **c2**, confidence: **High**
  - IP / domain IOC(s): `webhook.site`

- **File hash IOCs — endpoint file/process match** ([template](../_TEMPLATES.md#hash-ioc)) — phase: **install**, confidence: **High**
  - file hash IOC(s): `929c6399c4fde4fe236bd6712b2c53f750d9ad3a`


## Why this matters

Severity classified as **HIGH** based on: IOCs present, 6 use case(s) fired, 12 technique(s) inferred. Read the full article for actor attribution, tooling details, and any defanged IOCs in the body that aren't visible in the RSS summary.
