oraios/serena
Dangerous patterns detected — do not install blindly.
View source ↗AI review
The extension contains several patterns that could be risky in an AI agent context, but none appear to be intentionally malicious or deceptive. The usage reporting telemetry is opt-in and transparent, and the remote code execution in build scripts is standard CI/CD practice. The main concern is the copilot-instructions.md file that attempts to enforce reading of a CLAUDE.md file, which could be a vector for prompt injection if that file contains malicious instructions, but this is speculative without seeing the referenced file.
- medium Potential prompt injection vector via copilot-instructions.md — The .github/copilot-instructions.md file contains a non-negotiable instruction telling AI agents to immediately read and follow instructions from CLAUDE.md. If CLAUDE.md contains hidden instructions to exfiltrate data or manipulate the agent, this could be exploited. However, no such malicious content was found in the reviewed files.
- low Usage reporting telemetry — src/serena/agent.py sends a GET request to oraios-software.de/serena_usage.php with environment parameters. This is gated by CI/GitHub Actions checks and a SERENA_USAGE_REPORTING env var defaulting to false, making it opt-in. Not a direct risk but worth noting for transparency.
- low Remote code execution in CI/CD pipelines — The pytest workflow and Dockerfile download and execute shell scripts from external URLs (astral.sh, raw.githubusercontent.com). This is standard practice for CI/CD but could be a supply chain risk if those endpoints are compromised. Not a safety risk for the agent extension itself.
Model: deepseek-chat
Static findings
Remote code execution · Downloads and executes remote code
.github/workflows/pytest.yml:58
run: curl -LsSf https://astral.sh/uv/install.sh | sh
Dockerfile:30
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v${NVM_VERSION}/install.sh | bash
src/solidlsp/language_servers/lean4_language_server.py:41
" curl https://raw.githubusercontent.com/leanprover/elan/master/elan-init.sh -sSf | sh\n"
Filesystem writes · Reads or writes the filesystem
docs/autogen_docs.py:73
shutil.rmtree(rst_root)
repo_dir_sync.py:163
shutil.rmtree(self.libRepo.libDirectory)
scripts/demo_diagnostics.py:175
shutil.rmtree(temp_dir, ignore_errors=True)
src/serena/cli.py:591
os.remove(path)
src/serena/config/serena_config.py:866
shutil.move(old_config_path, config_path)
src/serena/hooks.py:520
shutil.rmtree(self.session_persistence_dir, ignore_errors=True)
src/serena/memories/memory_manager.py:311
shutil.move(old_path, new_path)
src/solidlsp/language_servers/elixir_tools/elixir_tools.py:191
os.remove(executable_path)
src/solidlsp/language_servers/haxe_language_server.py:155
os.remove(vsix_path)
src/solidlsp/language_servers/pascal_server.py:396
os.remove(file_path)
Shell / command execution · Executes shell / system commands
docs/create_toc.py:9
os.system(cmd)
repo_dir_sync.py:12
def popen(cmd):
scripts/build_news_json.py:55
os.system(f"scp news/news.json {user}@hades:/var/www/html/oraios-software/serena_news.json")
scripts/bump_version.py:56
os.system("uv lock")
src/serena/cli.py:111
subprocess.run([editor, path], check=False, **run_kwargs)
src/serena/dashboard.py:816
p = subprocess.Popen(
src/serena/util/dotnet.py:30
result = subprocess.run([self._system_dotnet, "--list-runtimes"], capture_output=True, text=True, check=True)
src/serena/util/shell.py:28
process = subprocess.Popen(
src/solidlsp/language_servers/bsl_language_server.py:55
result = subprocess.run(
src/solidlsp/language_servers/clojure_lsp.py:62
return subprocess.run(
src/solidlsp/language_servers/common.py:113
completed_process = subprocess.run(
src/solidlsp/language_servers/elixir_tools/elixir_tools.py:68
result = subprocess.run(["elixir", "--version"], capture_output=True, text=True, check=False)
+ 17 more
Environment variables (config / keys) · Reads environment variables (config / API keys)
scripts/build_news_json.py:53
user = os.getenv("HADES_USER")
src/serena/agent.py:721
if os.getenv("CI") == "true" or os.getenv("GITHUB_ACTIONS") == "true" or os.getenv("SERENA_USAGE_REPORTING") == "false":
src/serena/cli.py:107
editor = os.environ.get("EDITOR")
src/serena/config/serena_config.py:61
home_dir = os.getenv("SERENA_HOME")
src/serena/hooks.py:18
serena_home_dir = os.getenv("SERENA_HOME", "").strip() or str(Path.home() / ".serena")
src/serena/util/exception.py:22
if not os.environ.get("DISPLAY"): # type: ignore
src/serena/util/gui.py:16
display = os.environ.get("DISPLAY", "")
src/serena/util/shell.py:49
args, stdin=subprocess.DEVNULL, stderr=subprocess.PIPE, timeout=timeout, env=os.environ.copy(), cwd=cwd, **subprocess_kwargs()
src/solidlsp/language_servers/al_language_server.py:236
env_path = os.environ.get("AL_EXTENSION_PATH")
src/solidlsp/language_servers/bash_language_server.py:195
"PATH": managed_bin_dir + os.pathsep + os.environ.get("PATH", ""),
src/solidlsp/language_servers/common.py:178
uvx_path = os.environ.get("UVX") or shutil.which("uvx")
src/solidlsp/language_servers/eclipse_jdtls.py:682
elif env_home := os.environ.get("JAVA_HOME"):
+ 12 more
Outbound network · Makes outbound network requests
src/serena/agent.py:731
requests.get("https://oraios-software.de/serena_usage.php", params=params, timeout=1)
src/serena/dashboard.py:10
import urllib.request
src/serena/util/dotnet.py:103
urllib.request.urlretrieve(script_url, script_path)
src/solidlsp/language_servers/haxe_language_server.py:11
import urllib.request
src/solidlsp/language_servers/pascal_server.py:60
import urllib.request
Scanning every extension your team installs?
Pro & Team add monitoring, private scans, and a CI gate for unsafe extensions.
MCPVet is a heuristic aid, not a security guarantee. A clean grade does not prove an extension is safe; always review code and instructions you don't trust.