Suspicious IDE Extension Installation from VSIX

Detects installation of an IDE extension from a local VSIX ("--install-extension" with a ".vsix" path) when that path is in a staging directory, or the parent is a script host or installer. VS Code and compatible editors (Cursor, VSCodium, Windsurf) use this CLI to sideload extensions outside the marketplace.

Elastic rule (View on GitHub)

  1[metadata]
  2creation_date = "2026/10/26"
  3integration = ["endpoint"]
  4maturity = "production"
  5min_stack_comments = "MV_CONTAINS was added to ES|QL in 9.2.0 and is not available on 8.19; 9.3.0 is the lowest supported 9.x release."
  6min_stack_version = "9.3.0"
  7updated_date = "2026/10/26"
  8
  9[rule]
 10author = ["Elastic"]
 11description = """
 12Detects installation of an IDE extension from a local VSIX ("--install-extension" with a ".vsix" path) when that path is
 13in a staging directory, or the parent is a script host or installer. VS Code and compatible editors (Cursor, VSCodium,
 14Windsurf) use this CLI to sideload extensions outside the marketplace.
 15"""
 16from = "now-9m"
 17language = "esql"
 18license = "Elastic License v2"
 19name = "Suspicious IDE Extension Installation from VSIX"
 20note = """## Triage and analysis
 21
 22### Investigating Suspicious IDE Extension Installation from VSIX
 23
 24An IDE CLI (`code`, `cursor`, `codium`, or a compatible editor) was invoked with `--install-extension` against a
 25`.vsix` file. The VSIX path is under a staging directory (`Users\\Public`, `AppData\\Local\\Temp`, `/tmp`,
 26`/var/tmp`, `/private/tmp`, `/dev/shm`), or the parent is a script host or installer rather than the editor itself.
 27Sideloading a VSIX is a known way to persist or gain execution through a malicious IDE extension.
 28
 29### Possible investigation steps
 30
 31- From `process.command_line`, extract the `.vsix` path and the editor binary (`code`, `code.exe`, `cursor`, `codium`).
 32- Review `process.parent.name` and `process.parent.command_line` to see whether a script host (`powershell`,
 33  `pwsh`, `mshta`, `wscript`, `cscript`, `msiexec`, `python*`, `py.exe`, `node`, `bun`, `osascript`) launched the install.
 34- Hash the VSIX and compare it with the extension the editor actually installed under `.vscode/extensions` or the
 35  equivalent Cursor or VSCodium extensions directory.
 36- On the same host and user, look for follow-on child processes from the extension host, new outbound connections,
 37  and files written by the extension.
 38
 39### False positive analysis
 40
 41- Extension development often installs a locally built VSIX from PowerShell, pwsh, Node, Bun, or Python, including
 42  from a temp directory. Confirm the VSIX path, publisher, and parent script with the developer before excluding.
 43- Scope exceptions to a known VSIX path, parent command line, host, or user. Do not broadly exclude
 44  `--install-extension` or the editor binary.
 45
 46### Response and remediation
 47
 48- If the VSIX is unapproved, uninstall the extension, remove the VSIX, and restart the editor.
 49- Quarantine the VSIX, collect its hash, and hunt that hash and command line on other hosts.
 50- If a script host launched the install, investigate that parent for a downloader or installer and remove it.
 51- Rotate tokens or credentials the extension could have read from the user profile or workspace.
 52"""
 53references = [
 54    "https://www.mdsec.co.uk/2021/01/macos-post-exploitation-shenanigans-with-vscode-extensions/",
 55    "https://code.visualstudio.com/docs/editor/extension-marketplace#_install-from-a-vsix",
 56]
 57risk_score = 47
 58rule_id = "7babe894-46e5-4cc8-a7ae-3b0e71e31d97"
 59setup = """## Setup
 60
 61This rule is designed for data generated by [Elastic Defend](https://www.elastic.co/security/endpoint-security), which provides native endpoint detection and response, along with event enrichments designed to work with our detection rules.
 62
 63Setup instructions: https://ela.st/install-elastic-defend
 64"""
 65severity = "medium"
 66tags = [
 67    "Domain: Endpoint",
 68    "OS: Linux",
 69    "OS: Windows",
 70    "OS: macOS",
 71    "Use Case: Threat Detection",
 72    "Tactic: Persistence",
 73    "Data Source: Elastic Defend",
 74    "Resources: Investigation Guide",
 75    "Rule Type: ES|QL",
 76    "Platform: Windows",
 77    "Platform: Linux",
 78    "Platform: macOS",
 79]
 80timestamp_override = "event.ingested"
 81type = "esql"
 82
 83query = '''
 84FROM logs-endpoint.events.process-* METADATA _id, _version, _index
 85| WHERE MV_CONTAINS(event.category, "process")
 86  AND MV_CONTAINS(event.type, "start")
 87  AND TO_LOWER(process.command_line) LIKE "*--install-extension*"
 88  AND TO_LOWER(process.command_line) LIKE "*.vsix*"
 89  AND (
 90    (
 91      host.os.type == "windows"
 92      AND (
 93        TO_LOWER(process.command_line) RLIKE
 94          """.*\\users\\public\\.*|.*\\appdata\\local\\temp\\.*|.*/users/public/.*|.*/appdata/local/temp/.*"""
 95        OR TO_LOWER(process.parent.name) IN (
 96          "mshta.exe",
 97          "wscript.exe",
 98          "cscript.exe",
 99          "powershell.exe",
100          "msiexec.exe",
101          "pwsh.exe",
102          "node.exe",
103          "bun.exe",
104          "py.exe"
105        )
106        OR TO_LOWER(process.parent.name) LIKE "python*"
107      )
108    )
109    OR
110    (
111      host.os.type IN ("macos", "linux")
112      AND (
113        TO_LOWER(process.command_line) LIKE (
114          "*/tmp/*",
115          "*/var/tmp/*",
116          "*/private/tmp/*",
117          "*/dev/shm/*",
118          "*/users/shared/*"
119        )
120        OR TO_LOWER(process.parent.name) IN (
121          "osascript", "node", "bun"
122        )
123        OR TO_LOWER(process.parent.name) LIKE "python*"
124      )
125    )
126  )
127| KEEP
128    _id,
129    _version,
130    _index,
131	data_stream.namespace,
132    @timestamp,
133    host.name,
134	host.id,
135	agent.id,
136    host.os.type,
137    user.name,
138	user.domain,
139    process.name,
140    process.parent.name,
141    process.command_line,
142    process.parent.command_line
143'''
144
145
146[[rule.threat]]
147framework = "MITRE ATT&CK"
148
149[[rule.threat.technique]]
150id = "T1176"
151name = "Software Extensions"
152reference = "https://attack.mitre.org/techniques/T1176/"
153
154[[rule.threat.technique.subtechnique]]
155id = "T1176.002"
156name = "IDE Extensions"
157reference = "https://attack.mitre.org/techniques/T1176/002/"
158
159[rule.threat.tactic]
160id = "TA0003"
161name = "Persistence"
162reference = "https://attack.mitre.org/tactics/TA0003/"
163
164[rule.investigation_fields]
165field_names = [
166    "host.name",
167    "host.os.type",
168    "user.name",
169    "process.name",
170    "process.parent.name",
171    "process.command_line",
172    "process.parent.command_line"
173]

Triage and analysis

Investigating Suspicious IDE Extension Installation from VSIX

An IDE CLI (code, cursor, codium, or a compatible editor) was invoked with --install-extension against a .vsix file. The VSIX path is under a staging directory (Users\Public, AppData\Local\Temp, /tmp, /var/tmp, /private/tmp, /dev/shm), or the parent is a script host or installer rather than the editor itself. Sideloading a VSIX is a known way to persist or gain execution through a malicious IDE extension.

Possible investigation steps

  • From process.command_line, extract the .vsix path and the editor binary (code, code.exe, cursor, codium).
  • Review process.parent.name and process.parent.command_line to see whether a script host (powershell, pwsh, mshta, wscript, cscript, msiexec, python*, py.exe, node, bun, osascript) launched the install.
  • Hash the VSIX and compare it with the extension the editor actually installed under .vscode/extensions or the equivalent Cursor or VSCodium extensions directory.
  • On the same host and user, look for follow-on child processes from the extension host, new outbound connections, and files written by the extension.

False positive analysis

  • Extension development often installs a locally built VSIX from PowerShell, pwsh, Node, Bun, or Python, including from a temp directory. Confirm the VSIX path, publisher, and parent script with the developer before excluding.
  • Scope exceptions to a known VSIX path, parent command line, host, or user. Do not broadly exclude --install-extension or the editor binary.

Response and remediation

  • If the VSIX is unapproved, uninstall the extension, remove the VSIX, and restart the editor.
  • Quarantine the VSIX, collect its hash, and hunt that hash and command line on other hosts.
  • If a script host launched the install, investigate that parent for a downloader or installer and remove it.
  • Rotate tokens or credentials the extension could have read from the user profile or workspace.

References

Related rules

to-top