coding-agent-audit 0.5.0__tar.gz → 0.6.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {coding_agent_audit-0.5.0/src/coding_agent_audit.egg-info → coding_agent_audit-0.6.1}/PKG-INFO +11 -2
- {coding_agent_audit-0.5.0 → coding_agent_audit-0.6.1}/README.md +10 -1
- {coding_agent_audit-0.5.0 → coding_agent_audit-0.6.1}/pyproject.toml +1 -1
- {coding_agent_audit-0.5.0 → coding_agent_audit-0.6.1}/src/agentaudit/__init__.py +1 -1
- {coding_agent_audit-0.5.0 → coding_agent_audit-0.6.1}/src/agentaudit/checks.py +112 -0
- {coding_agent_audit-0.5.0 → coding_agent_audit-0.6.1}/src/agentaudit/iocs.py +26 -1
- {coding_agent_audit-0.5.0 → coding_agent_audit-0.6.1}/src/agentaudit/mcp_server.py +19 -3
- {coding_agent_audit-0.5.0 → coding_agent_audit-0.6.1/src/coding_agent_audit.egg-info}/PKG-INFO +11 -2
- {coding_agent_audit-0.5.0 → coding_agent_audit-0.6.1}/tests/test_checks.py +50 -0
- {coding_agent_audit-0.5.0 → coding_agent_audit-0.6.1}/LICENSE +0 -0
- {coding_agent_audit-0.5.0 → coding_agent_audit-0.6.1}/setup.cfg +0 -0
- {coding_agent_audit-0.5.0 → coding_agent_audit-0.6.1}/src/agentaudit/cli.py +0 -0
- {coding_agent_audit-0.5.0 → coding_agent_audit-0.6.1}/src/agentaudit/configscan.py +0 -0
- {coding_agent_audit-0.5.0 → coding_agent_audit-0.6.1}/src/agentaudit/findings.py +0 -0
- {coding_agent_audit-0.5.0 → coding_agent_audit-0.6.1}/src/agentaudit/phantomdeps.py +0 -0
- {coding_agent_audit-0.5.0 → coding_agent_audit-0.6.1}/src/coding_agent_audit.egg-info/SOURCES.txt +0 -0
- {coding_agent_audit-0.5.0 → coding_agent_audit-0.6.1}/src/coding_agent_audit.egg-info/dependency_links.txt +0 -0
- {coding_agent_audit-0.5.0 → coding_agent_audit-0.6.1}/src/coding_agent_audit.egg-info/entry_points.txt +0 -0
- {coding_agent_audit-0.5.0 → coding_agent_audit-0.6.1}/src/coding_agent_audit.egg-info/requires.txt +0 -0
- {coding_agent_audit-0.5.0 → coding_agent_audit-0.6.1}/src/coding_agent_audit.egg-info/top_level.txt +0 -0
- {coding_agent_audit-0.5.0 → coding_agent_audit-0.6.1}/tests/test_cli.py +0 -0
- {coding_agent_audit-0.5.0 → coding_agent_audit-0.6.1}/tests/test_configscan.py +0 -0
- {coding_agent_audit-0.5.0 → coding_agent_audit-0.6.1}/tests/test_mcp_server.py +0 -0
- {coding_agent_audit-0.5.0 → coding_agent_audit-0.6.1}/tests/test_phantomdeps.py +0 -0
{coding_agent_audit-0.5.0/src/coding_agent_audit.egg-info → coding_agent_audit-0.6.1}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: coding-agent-audit
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.1
|
|
4
4
|
Summary: Scan your machine for known AI-coding-assistant supply-chain backdoor indicators (Claude Code / Cursor / Windsurf extensions, MCP servers) plus risky hook/permission config patterns. Usable as a CLI or as an MCP server.
|
|
5
5
|
Author-email: StackScribe AI <survivalagent320@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -23,6 +23,8 @@ Dynamic: license-file
|
|
|
23
23
|
|
|
24
24
|
<!-- mcp-name: io.github.stackscribe-ai/coding-agent-audit -->
|
|
25
25
|
|
|
26
|
+
[](https://m8ven.ai/mcp/stackscribe-ai-coding-agent-audit-1xiuww?s=readme)
|
|
27
|
+
|
|
26
28
|
A small, open-source CLI that scans your machine for:
|
|
27
29
|
|
|
28
30
|
1. **Known indicators of compromise (IOCs)** from publicly documented
|
|
@@ -104,6 +106,12 @@ Cursor Marketplace Claude Code trojan:
|
|
|
104
106
|
persistence task name
|
|
105
107
|
- On Windows: the known SYSTEM scheduled task name, and the Startup-folder
|
|
106
108
|
script dropped as a fallback when that task can't be created
|
|
109
|
+
- A GitHub Copilot VS Code extension older than 1.1.29 (the version that
|
|
110
|
+
fixed the address-bar-spoofing half of **EMBRACE**, Forever Security's
|
|
111
|
+
Oct 2026 disclosure of embedded-browser flaws in Cursor, Copilot, Codex,
|
|
112
|
+
VS Code and Claude Desktop), plus a presence check that flags Codex/VS
|
|
113
|
+
Code (still unpatched at disclosure time) or Claude Desktop (patch status
|
|
114
|
+
unconfirmed) if installed, with mitigation guidance
|
|
107
115
|
|
|
108
116
|
**Config heuristics** (`configscan.py`) — pattern-based, always worth a
|
|
109
117
|
second look rather than proof of compromise:
|
|
@@ -221,7 +229,7 @@ scan for free; this just packages it for sharing.
|
|
|
221
229
|
|
|
222
230
|
If your agent runtime supports the open `SKILL.md` standard (Claude Code,
|
|
223
231
|
Cursor, and others), a packaged version of this scan is live on the
|
|
224
|
-
[Agensi skill marketplace](https://www.agensi.io/skills/coding-agent-security-audit)
|
|
232
|
+
[Agensi skill marketplace](https://www.agensi.io/r/STACKSCRIBEAI?to=/skills/coding-agent-security-audit)
|
|
225
233
|
as "coding agent security audit" (free) — source in
|
|
226
234
|
[`agensi-skill/`](agensi-skill/). It's a zero-dependency, single-file port of
|
|
227
235
|
the same checks below, meant to be loaded by an agent directly rather than
|
|
@@ -247,6 +255,7 @@ pytest
|
|
|
247
255
|
- doublepulsar.com: ["Anthropic hacked to deliver remote access trojan to Claude developer laptops worldwide"](https://doublepulsar.com/anthropic-hacked-to-deliver-remote-access-trojan-to-claude-developer-laptops-worldwide-1148a92baae2)
|
|
248
256
|
- dev.to/@slabb: ["A trojanized Claude Code extension plants an SSH backdoor: the 7-point audit for your machine"](https://dev.to/slabb/a-trojanized-claude-code-extension-plants-an-ssh-backdoor-the-7-point-audit-for-your-machine-23cj)
|
|
249
257
|
- Phorion: ["Official Claude Code Extension Compromise: Security Advisory"](https://phorion.io/blog/offical-claude-code-vsx-compromise/) — confirms the same backdoor reached the Cursor Marketplace and documents the Windows/Linux persistence mechanisms added in v0.2.0 of this tool.
|
|
258
|
+
- Help Net Security: ["Researchers broke the browsers built into VS Code, Cursor, Copilot, Codex and Claude Desktop"](https://www.helpnetsecurity.com/2026/10/29/research-ai-assistant-browser-vulnerabilities/) and The Register: ["Researchers find bugs in 5 AI developer tools, with OpenAI and Microsoft flaws still unpatched"](https://www.theregister.com/security/2026/10/29/researchers_find_bugs_in_5_ai_developer_tools_with_openai_and_microsoft_flaws_still_unpatched/5306508) — Forever Security's EMBRACE disclosure, added in v0.6.0 of this tool.
|
|
250
259
|
|
|
251
260
|
## Need this for your team?
|
|
252
261
|
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
<!-- mcp-name: io.github.stackscribe-ai/coding-agent-audit -->
|
|
4
4
|
|
|
5
|
+
[](https://m8ven.ai/mcp/stackscribe-ai-coding-agent-audit-1xiuww?s=readme)
|
|
6
|
+
|
|
5
7
|
A small, open-source CLI that scans your machine for:
|
|
6
8
|
|
|
7
9
|
1. **Known indicators of compromise (IOCs)** from publicly documented
|
|
@@ -83,6 +85,12 @@ Cursor Marketplace Claude Code trojan:
|
|
|
83
85
|
persistence task name
|
|
84
86
|
- On Windows: the known SYSTEM scheduled task name, and the Startup-folder
|
|
85
87
|
script dropped as a fallback when that task can't be created
|
|
88
|
+
- A GitHub Copilot VS Code extension older than 1.1.29 (the version that
|
|
89
|
+
fixed the address-bar-spoofing half of **EMBRACE**, Forever Security's
|
|
90
|
+
Oct 2026 disclosure of embedded-browser flaws in Cursor, Copilot, Codex,
|
|
91
|
+
VS Code and Claude Desktop), plus a presence check that flags Codex/VS
|
|
92
|
+
Code (still unpatched at disclosure time) or Claude Desktop (patch status
|
|
93
|
+
unconfirmed) if installed, with mitigation guidance
|
|
86
94
|
|
|
87
95
|
**Config heuristics** (`configscan.py`) — pattern-based, always worth a
|
|
88
96
|
second look rather than proof of compromise:
|
|
@@ -200,7 +208,7 @@ scan for free; this just packages it for sharing.
|
|
|
200
208
|
|
|
201
209
|
If your agent runtime supports the open `SKILL.md` standard (Claude Code,
|
|
202
210
|
Cursor, and others), a packaged version of this scan is live on the
|
|
203
|
-
[Agensi skill marketplace](https://www.agensi.io/skills/coding-agent-security-audit)
|
|
211
|
+
[Agensi skill marketplace](https://www.agensi.io/r/STACKSCRIBEAI?to=/skills/coding-agent-security-audit)
|
|
204
212
|
as "coding agent security audit" (free) — source in
|
|
205
213
|
[`agensi-skill/`](agensi-skill/). It's a zero-dependency, single-file port of
|
|
206
214
|
the same checks below, meant to be loaded by an agent directly rather than
|
|
@@ -226,6 +234,7 @@ pytest
|
|
|
226
234
|
- doublepulsar.com: ["Anthropic hacked to deliver remote access trojan to Claude developer laptops worldwide"](https://doublepulsar.com/anthropic-hacked-to-deliver-remote-access-trojan-to-claude-developer-laptops-worldwide-1148a92baae2)
|
|
227
235
|
- dev.to/@slabb: ["A trojanized Claude Code extension plants an SSH backdoor: the 7-point audit for your machine"](https://dev.to/slabb/a-trojanized-claude-code-extension-plants-an-ssh-backdoor-the-7-point-audit-for-your-machine-23cj)
|
|
228
236
|
- Phorion: ["Official Claude Code Extension Compromise: Security Advisory"](https://phorion.io/blog/offical-claude-code-vsx-compromise/) — confirms the same backdoor reached the Cursor Marketplace and documents the Windows/Linux persistence mechanisms added in v0.2.0 of this tool.
|
|
237
|
+
- Help Net Security: ["Researchers broke the browsers built into VS Code, Cursor, Copilot, Codex and Claude Desktop"](https://www.helpnetsecurity.com/2026/10/29/research-ai-assistant-browser-vulnerabilities/) and The Register: ["Researchers find bugs in 5 AI developer tools, with OpenAI and Microsoft flaws still unpatched"](https://www.theregister.com/security/2026/10/29/researchers_find_bugs_in_5_ai_developer_tools_with_openai_and_microsoft_flaws_still_unpatched/5306508) — Forever Security's EMBRACE disclosure, added in v0.6.0 of this tool.
|
|
229
238
|
|
|
230
239
|
## Need this for your team?
|
|
231
240
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "coding-agent-audit"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.6.1"
|
|
8
8
|
description = "Scan your machine for known AI-coding-assistant supply-chain backdoor indicators (Claude Code / Cursor / Windsurf extensions, MCP servers) plus risky hook/permission config patterns. Usable as a CLI or as an MCP server."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
@@ -9,6 +9,7 @@ from __future__ import annotations
|
|
|
9
9
|
import hashlib
|
|
10
10
|
import os
|
|
11
11
|
import platform
|
|
12
|
+
import re
|
|
12
13
|
import subprocess
|
|
13
14
|
from pathlib import Path
|
|
14
15
|
from typing import Iterable, Optional
|
|
@@ -17,6 +18,7 @@ from .findings import Finding
|
|
|
17
18
|
from .iocs import INCIDENTS
|
|
18
19
|
|
|
19
20
|
_IOC = INCIDENTS["openvsx-claude-code-2026-10"]
|
|
21
|
+
_EMBRACE = INCIDENTS["embrace-embedded-browser-2026-10"]
|
|
20
22
|
|
|
21
23
|
|
|
22
24
|
def check_ssh_authorized_keys(home: Path) -> list[Finding]:
|
|
@@ -290,6 +292,114 @@ def live_process_lines() -> list[str]:
|
|
|
290
292
|
return result.stdout.splitlines()
|
|
291
293
|
|
|
292
294
|
|
|
295
|
+
_EXTENSION_VERSION_RE = re.compile(r"^(.+)-(\d+(?:\.\d+)*)$")
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
def _parse_extension_version(dirname: str) -> Optional[tuple[int, ...]]:
|
|
299
|
+
match = _EXTENSION_VERSION_RE.match(dirname)
|
|
300
|
+
if not match:
|
|
301
|
+
return None
|
|
302
|
+
try:
|
|
303
|
+
return tuple(int(part) for part in match.group(2).split("."))
|
|
304
|
+
except ValueError:
|
|
305
|
+
return None
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
def check_embrace_copilot_version(scan_dirs: Iterable[Path]) -> list[Finding]:
|
|
309
|
+
"""Flag a GitHub Copilot VS Code extension older than the version that
|
|
310
|
+
fixed the EMBRACE address-bar-spoofing flaw in its embedded browser."""
|
|
311
|
+
patched = _EMBRACE["copilot_patched_version"]
|
|
312
|
+
findings: list[Finding] = []
|
|
313
|
+
for base in scan_dirs:
|
|
314
|
+
if not base.is_dir():
|
|
315
|
+
continue
|
|
316
|
+
for entry in sorted(base.iterdir()):
|
|
317
|
+
if not entry.is_dir():
|
|
318
|
+
continue
|
|
319
|
+
name = entry.name.lower()
|
|
320
|
+
# The base "GitHub Copilot" extension only; copilot-chat ships
|
|
321
|
+
# its own, differently-numbered releases not covered by the fix
|
|
322
|
+
# version above.
|
|
323
|
+
if not name.startswith("github.copilot-") or name.startswith(
|
|
324
|
+
"github.copilot-chat-"
|
|
325
|
+
):
|
|
326
|
+
continue
|
|
327
|
+
version = _parse_extension_version(entry.name)
|
|
328
|
+
if version is None or version >= patched:
|
|
329
|
+
continue
|
|
330
|
+
findings.append(
|
|
331
|
+
Finding(
|
|
332
|
+
check_id="embrace-copilot-version",
|
|
333
|
+
severity="warning",
|
|
334
|
+
title=(
|
|
335
|
+
"GitHub Copilot extension predates the EMBRACE "
|
|
336
|
+
"address-bar-spoofing fix"
|
|
337
|
+
),
|
|
338
|
+
detail=(
|
|
339
|
+
f"'{entry}' is version {'.'.join(map(str, version))}, "
|
|
340
|
+
f"older than {'.'.join(map(str, patched))} (released "
|
|
341
|
+
f"2026-10-13), which fixed an address-bar-spoofing "
|
|
342
|
+
f"flaw in Copilot's embedded browser (part of the "
|
|
343
|
+
f"EMBRACE disclosure). Update the extension."
|
|
344
|
+
),
|
|
345
|
+
path=str(entry),
|
|
346
|
+
references=_EMBRACE["references"],
|
|
347
|
+
)
|
|
348
|
+
)
|
|
349
|
+
return findings
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
def check_embrace_unpatched_tools(home: Path) -> list[Finding]:
|
|
353
|
+
"""Flag the presence of AI coding tools named in the EMBRACE embedded-
|
|
354
|
+
browser disclosure, calling out the ones reported unpatched at
|
|
355
|
+
disclosure time."""
|
|
356
|
+
detected: list[str] = []
|
|
357
|
+
if (home / ".vscode").is_dir() or (home / ".vscode-server").is_dir():
|
|
358
|
+
detected.append("VS Code")
|
|
359
|
+
if (home / ".codex").is_dir():
|
|
360
|
+
detected.append("OpenAI Codex")
|
|
361
|
+
claude_desktop_dirs = [
|
|
362
|
+
home / "Library" / "Application Support" / "Claude",
|
|
363
|
+
home / ".config" / "Claude",
|
|
364
|
+
home / "AppData" / "Roaming" / "Claude",
|
|
365
|
+
]
|
|
366
|
+
if any(p.is_dir() for p in claude_desktop_dirs):
|
|
367
|
+
detected.append("Claude Desktop")
|
|
368
|
+
if not detected:
|
|
369
|
+
return []
|
|
370
|
+
|
|
371
|
+
unpatched = [d for d in detected if d in _EMBRACE["unpatched_products"]]
|
|
372
|
+
unconfirmed = [d for d in detected if d not in _EMBRACE["unpatched_products"]]
|
|
373
|
+
|
|
374
|
+
parts = []
|
|
375
|
+
if unpatched:
|
|
376
|
+
parts.append(
|
|
377
|
+
f"{', '.join(unpatched)} detected on this machine and was still "
|
|
378
|
+
f"unpatched as of the EMBRACE disclosure referenced below."
|
|
379
|
+
)
|
|
380
|
+
if unconfirmed:
|
|
381
|
+
parts.append(
|
|
382
|
+
f"{', '.join(unconfirmed)} also detected; the researchers did "
|
|
383
|
+
f"not confirm a patch status for it at disclosure time."
|
|
384
|
+
)
|
|
385
|
+
parts.append(
|
|
386
|
+
"Until a fix ships: don't open links or HTML the assistant "
|
|
387
|
+
"generates from untrusted/external content inside the tool's "
|
|
388
|
+
"built-in browser or preview pane - a malicious page there can "
|
|
389
|
+
"read SSH keys, .env files and other local secrets, per the "
|
|
390
|
+
"EMBRACE write-up."
|
|
391
|
+
)
|
|
392
|
+
return [
|
|
393
|
+
Finding(
|
|
394
|
+
check_id="embrace-unpatched-tool-present",
|
|
395
|
+
severity="warning" if unpatched else "info",
|
|
396
|
+
title="AI coding tool named in the EMBRACE embedded-browser disclosure detected",
|
|
397
|
+
detail=" ".join(parts),
|
|
398
|
+
references=_EMBRACE["references"],
|
|
399
|
+
)
|
|
400
|
+
]
|
|
401
|
+
|
|
402
|
+
|
|
293
403
|
def run_all_ioc_checks(home: Optional[Path] = None) -> list[Finding]:
|
|
294
404
|
"""Run every IOC check against the real local machine."""
|
|
295
405
|
home = home or Path.home()
|
|
@@ -300,6 +410,8 @@ def run_all_ioc_checks(home: Optional[Path] = None) -> list[Finding]:
|
|
|
300
410
|
findings += check_marker_files(home)
|
|
301
411
|
findings += check_tmp_tunnel_keys(tmp_dir)
|
|
302
412
|
findings += check_extension_hashes(default_extension_scan_dirs(home))
|
|
413
|
+
findings += check_embrace_copilot_version(default_extension_scan_dirs(home))
|
|
414
|
+
findings += check_embrace_unpatched_tools(home)
|
|
303
415
|
findings += check_c2_network_indicators(live_process_lines())
|
|
304
416
|
findings += check_linux_cron_persistence(live_crontab_text())
|
|
305
417
|
if platform.system() == "Darwin":
|
|
@@ -50,5 +50,30 @@ INCIDENTS = {
|
|
|
50
50
|
"windows_startup_relpath": (
|
|
51
51
|
"Microsoft/Windows/Start Menu/Programs/Startup/sysmon.cmd"
|
|
52
52
|
),
|
|
53
|
-
}
|
|
53
|
+
},
|
|
54
|
+
"embrace-embedded-browser-2026-10": {
|
|
55
|
+
"name": "EMBRACE embedded-browser flaws in AI coding assistants (Forever Security, Oct 2026)",
|
|
56
|
+
"description": (
|
|
57
|
+
"Forever Security's EMBRACE research (published 2026-10-29) found "
|
|
58
|
+
"that five AI coding tools grant their embedded preview/agent "
|
|
59
|
+
"browser the same filesystem trust as the IDE itself: code "
|
|
60
|
+
"execution in Cursor, address-bar spoofing in GitHub Copilot, "
|
|
61
|
+
"and arbitrary local-file read (SSH keys, .env files, npm "
|
|
62
|
+
"tokens) in OpenAI Codex, VS Code and Claude Desktop, triggered "
|
|
63
|
+
"by a single HTML page opened in the tool's internal browser. "
|
|
64
|
+
"Cursor was fixed 2026-10-01 and GitHub Copilot in extension "
|
|
65
|
+
"version 1.1.29 (2026-10-13); Codex and VS Code were still "
|
|
66
|
+
"unpatched as of 2026-11-02, and Claude Desktop's status was "
|
|
67
|
+
"not confirmed by the researchers."
|
|
68
|
+
),
|
|
69
|
+
"references": [
|
|
70
|
+
"https://www.helpnetsecurity.com/2026/10/29/research-ai-assistant-browser-vulnerabilities/",
|
|
71
|
+
"https://www.theregister.com/security/2026/10/29/researchers_find_bugs_in_5_ai_developer_tools_with_openai_and_microsoft_flaws_still_unpatched/5306508",
|
|
72
|
+
"https://hackread.com/embrace-flaws-ai-coding-tools-code-execution-theft/",
|
|
73
|
+
],
|
|
74
|
+
# GitHub Copilot extension version that ships the address-bar-spoofing fix.
|
|
75
|
+
"copilot_patched_version": (1, 1, 29),
|
|
76
|
+
# As of the references above; re-check before treating as current.
|
|
77
|
+
"unpatched_products": ["OpenAI Codex", "VS Code"],
|
|
78
|
+
},
|
|
54
79
|
}
|
|
@@ -14,6 +14,7 @@ from pathlib import Path
|
|
|
14
14
|
from typing import Optional
|
|
15
15
|
|
|
16
16
|
from mcp.server.mcpserver import MCPServer
|
|
17
|
+
from mcp.types import ToolAnnotations
|
|
17
18
|
|
|
18
19
|
from . import __version__
|
|
19
20
|
from .checks import run_all_ioc_checks
|
|
@@ -53,7 +54,22 @@ def _render(findings: list[Finding]) -> str:
|
|
|
53
54
|
return "\n".join(lines)
|
|
54
55
|
|
|
55
56
|
|
|
56
|
-
|
|
57
|
+
_LOCAL_READ_ONLY = ToolAnnotations(
|
|
58
|
+
readOnlyHint=True,
|
|
59
|
+
destructiveHint=False,
|
|
60
|
+
idempotentHint=True,
|
|
61
|
+
openWorldHint=False,
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
_NETWORK_READ_ONLY = ToolAnnotations(
|
|
65
|
+
readOnlyHint=True,
|
|
66
|
+
destructiveHint=False,
|
|
67
|
+
idempotentHint=True,
|
|
68
|
+
openWorldHint=True,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
@server.tool(annotations=_LOCAL_READ_ONLY)
|
|
57
73
|
def scan_for_known_backdoors() -> str:
|
|
58
74
|
"""Scan this machine for known, publicly-documented indicators of
|
|
59
75
|
compromise from AI-coding-assistant supply-chain attacks (SSH backdoor
|
|
@@ -62,7 +78,7 @@ def scan_for_known_backdoors() -> str:
|
|
|
62
78
|
return _render(run_all_ioc_checks())
|
|
63
79
|
|
|
64
80
|
|
|
65
|
-
@server.tool()
|
|
81
|
+
@server.tool(annotations=_LOCAL_READ_ONLY)
|
|
66
82
|
def scan_mcp_config(project_dir: Optional[str] = None) -> str:
|
|
67
83
|
"""Scan this machine's Claude Code / Claude Desktop / MCP config files
|
|
68
84
|
for risky patterns: hooks that pipe a remote download into a shell,
|
|
@@ -80,7 +96,7 @@ def scan_mcp_config(project_dir: Optional[str] = None) -> str:
|
|
|
80
96
|
return _render(scan_paths(paths))
|
|
81
97
|
|
|
82
98
|
|
|
83
|
-
@server.tool()
|
|
99
|
+
@server.tool(annotations=_NETWORK_READ_ONLY)
|
|
84
100
|
def scan_phantom_dependencies(project_dir: str) -> str:
|
|
85
101
|
"""Check a project's package.json / requirements.txt / pyproject.toml
|
|
86
102
|
dependencies against the npm/PyPI registries and flag any package name
|
{coding_agent_audit-0.5.0 → coding_agent_audit-0.6.1/src/coding_agent_audit.egg-info}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: coding-agent-audit
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.1
|
|
4
4
|
Summary: Scan your machine for known AI-coding-assistant supply-chain backdoor indicators (Claude Code / Cursor / Windsurf extensions, MCP servers) plus risky hook/permission config patterns. Usable as a CLI or as an MCP server.
|
|
5
5
|
Author-email: StackScribe AI <survivalagent320@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -23,6 +23,8 @@ Dynamic: license-file
|
|
|
23
23
|
|
|
24
24
|
<!-- mcp-name: io.github.stackscribe-ai/coding-agent-audit -->
|
|
25
25
|
|
|
26
|
+
[](https://m8ven.ai/mcp/stackscribe-ai-coding-agent-audit-1xiuww?s=readme)
|
|
27
|
+
|
|
26
28
|
A small, open-source CLI that scans your machine for:
|
|
27
29
|
|
|
28
30
|
1. **Known indicators of compromise (IOCs)** from publicly documented
|
|
@@ -104,6 +106,12 @@ Cursor Marketplace Claude Code trojan:
|
|
|
104
106
|
persistence task name
|
|
105
107
|
- On Windows: the known SYSTEM scheduled task name, and the Startup-folder
|
|
106
108
|
script dropped as a fallback when that task can't be created
|
|
109
|
+
- A GitHub Copilot VS Code extension older than 1.1.29 (the version that
|
|
110
|
+
fixed the address-bar-spoofing half of **EMBRACE**, Forever Security's
|
|
111
|
+
Oct 2026 disclosure of embedded-browser flaws in Cursor, Copilot, Codex,
|
|
112
|
+
VS Code and Claude Desktop), plus a presence check that flags Codex/VS
|
|
113
|
+
Code (still unpatched at disclosure time) or Claude Desktop (patch status
|
|
114
|
+
unconfirmed) if installed, with mitigation guidance
|
|
107
115
|
|
|
108
116
|
**Config heuristics** (`configscan.py`) — pattern-based, always worth a
|
|
109
117
|
second look rather than proof of compromise:
|
|
@@ -221,7 +229,7 @@ scan for free; this just packages it for sharing.
|
|
|
221
229
|
|
|
222
230
|
If your agent runtime supports the open `SKILL.md` standard (Claude Code,
|
|
223
231
|
Cursor, and others), a packaged version of this scan is live on the
|
|
224
|
-
[Agensi skill marketplace](https://www.agensi.io/skills/coding-agent-security-audit)
|
|
232
|
+
[Agensi skill marketplace](https://www.agensi.io/r/STACKSCRIBEAI?to=/skills/coding-agent-security-audit)
|
|
225
233
|
as "coding agent security audit" (free) — source in
|
|
226
234
|
[`agensi-skill/`](agensi-skill/). It's a zero-dependency, single-file port of
|
|
227
235
|
the same checks below, meant to be loaded by an agent directly rather than
|
|
@@ -247,6 +255,7 @@ pytest
|
|
|
247
255
|
- doublepulsar.com: ["Anthropic hacked to deliver remote access trojan to Claude developer laptops worldwide"](https://doublepulsar.com/anthropic-hacked-to-deliver-remote-access-trojan-to-claude-developer-laptops-worldwide-1148a92baae2)
|
|
248
256
|
- dev.to/@slabb: ["A trojanized Claude Code extension plants an SSH backdoor: the 7-point audit for your machine"](https://dev.to/slabb/a-trojanized-claude-code-extension-plants-an-ssh-backdoor-the-7-point-audit-for-your-machine-23cj)
|
|
249
257
|
- Phorion: ["Official Claude Code Extension Compromise: Security Advisory"](https://phorion.io/blog/offical-claude-code-vsx-compromise/) — confirms the same backdoor reached the Cursor Marketplace and documents the Windows/Linux persistence mechanisms added in v0.2.0 of this tool.
|
|
258
|
+
- Help Net Security: ["Researchers broke the browsers built into VS Code, Cursor, Copilot, Codex and Claude Desktop"](https://www.helpnetsecurity.com/2026/10/29/research-ai-assistant-browser-vulnerabilities/) and The Register: ["Researchers find bugs in 5 AI developer tools, with OpenAI and Microsoft flaws still unpatched"](https://www.theregister.com/security/2026/10/29/researchers_find_bugs_in_5_ai_developer_tools_with_openai_and_microsoft_flaws_still_unpatched/5306508) — Forever Security's EMBRACE disclosure, added in v0.6.0 of this tool.
|
|
250
259
|
|
|
251
260
|
## Need this for your team?
|
|
252
261
|
|
|
@@ -3,6 +3,8 @@ from pathlib import Path
|
|
|
3
3
|
|
|
4
4
|
from agentaudit.checks import (
|
|
5
5
|
check_c2_network_indicators,
|
|
6
|
+
check_embrace_copilot_version,
|
|
7
|
+
check_embrace_unpatched_tools,
|
|
6
8
|
check_extension_hashes,
|
|
7
9
|
check_linux_cron_persistence,
|
|
8
10
|
check_macos_launch_agent,
|
|
@@ -16,6 +18,7 @@ from agentaudit.checks import (
|
|
|
16
18
|
from agentaudit.iocs import INCIDENTS
|
|
17
19
|
|
|
18
20
|
_IOC = INCIDENTS["openvsx-claude-code-2026-10"]
|
|
21
|
+
_EMBRACE = INCIDENTS["embrace-embedded-browser-2026-10"]
|
|
19
22
|
|
|
20
23
|
|
|
21
24
|
def test_ssh_authorized_keys_clean(tmp_path: Path):
|
|
@@ -195,3 +198,50 @@ def test_marker_files_includes_windows_variant(tmp_path: Path):
|
|
|
195
198
|
(config_dir / "smtk").write_text("x")
|
|
196
199
|
findings = check_marker_files(tmp_path)
|
|
197
200
|
assert len(findings) == 1
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
def test_embrace_copilot_version_clean_when_patched(tmp_path: Path):
|
|
204
|
+
ext_dir = tmp_path / ".vscode" / "extensions" / "github.copilot-1.1.29"
|
|
205
|
+
ext_dir.mkdir(parents=True)
|
|
206
|
+
findings = check_embrace_copilot_version([tmp_path / ".vscode" / "extensions"])
|
|
207
|
+
assert findings == []
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def test_embrace_copilot_version_flags_old_version(tmp_path: Path):
|
|
211
|
+
ext_dir = tmp_path / ".vscode" / "extensions" / "github.copilot-1.1.27"
|
|
212
|
+
ext_dir.mkdir(parents=True)
|
|
213
|
+
findings = check_embrace_copilot_version([tmp_path / ".vscode" / "extensions"])
|
|
214
|
+
assert len(findings) == 1
|
|
215
|
+
assert findings[0].severity == "warning"
|
|
216
|
+
assert findings[0].check_id == "embrace-copilot-version"
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def test_embrace_copilot_version_ignores_copilot_chat(tmp_path: Path):
|
|
220
|
+
ext_dir = tmp_path / ".vscode" / "extensions" / "github.copilot-chat-0.9.0"
|
|
221
|
+
ext_dir.mkdir(parents=True)
|
|
222
|
+
findings = check_embrace_copilot_version([tmp_path / ".vscode" / "extensions"])
|
|
223
|
+
assert findings == []
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
def test_embrace_copilot_version_nonexistent_dir(tmp_path: Path):
|
|
227
|
+
assert check_embrace_copilot_version([tmp_path / "nope"]) == []
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
def test_embrace_unpatched_tools_none_detected(tmp_path: Path):
|
|
231
|
+
assert check_embrace_unpatched_tools(tmp_path) == []
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
def test_embrace_unpatched_tools_vscode_is_warning(tmp_path: Path):
|
|
235
|
+
(tmp_path / ".vscode").mkdir()
|
|
236
|
+
findings = check_embrace_unpatched_tools(tmp_path)
|
|
237
|
+
assert len(findings) == 1
|
|
238
|
+
assert findings[0].severity == "warning"
|
|
239
|
+
assert "VS Code" in findings[0].detail
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
def test_embrace_unpatched_tools_claude_desktop_only_is_info(tmp_path: Path):
|
|
243
|
+
(tmp_path / ".config" / "Claude").mkdir(parents=True)
|
|
244
|
+
findings = check_embrace_unpatched_tools(tmp_path)
|
|
245
|
+
assert len(findings) == 1
|
|
246
|
+
assert findings[0].severity == "info"
|
|
247
|
+
assert "Claude Desktop" in findings[0].detail
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{coding_agent_audit-0.5.0 → coding_agent_audit-0.6.1}/src/coding_agent_audit.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{coding_agent_audit-0.5.0 → coding_agent_audit-0.6.1}/src/coding_agent_audit.egg-info/requires.txt
RENAMED
|
File without changes
|
{coding_agent_audit-0.5.0 → coding_agent_audit-0.6.1}/src/coding_agent_audit.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|