Skills/PyPI/ninja-mcp

ninja-mcp@1.9.2

CAUTION· install only

Publisher claims: "Multi-module MCP server: Coder, Researcher, Secretary" Observed in sandbox: calls astral.sh only, touches nothing outside the project, writes no memory.

Registry PyPI (MCP server)Publisher ninja-mcp-contributors · publishing for 62 daysInstalls 1,828Last detonated 31 h ago

Coverage

Install scripts ran; no agent task scenario for this bundle.
Tested
install scripts, with decoy credentials in place · second launch with the clock 45 days ahead · every file read, file written and host contacted by what ran
Not tested
use of the skill by an agent

What this means for the label: Caution here covers what ran. The server's tools were not exercised with a real credential, so nothing about their behavior is asserted; the credential summary below says what to do with that.

Before you give it your token

It will ask for
API_KEYNINJA_CREDENTIAL_PASSWORDNINJA_CREDENTIALS_DBOPENAI_API_KEYOPENROUTER_API_KEYPY_PI_TOKENTWINE_PASSWORDUV_PUBLISH_TOKEN or --openai-api-key / --max-chat-history-tokensConfiguration, not credentials: CLEANED_KEY, CURRENT_KEY, E2E_SCOPE, NINJA_ABSOLUTE_TIMEOUT_SEC, NINJA_AIDER_TIMEOUT, NINJA_CODE_BIN, NINJA_CODER_MODEL, NINJA_DEDUP_TTL, NINJA_ENABLED_MODULES, NINJA_HTTP_URL, NINJA_INACTIVITY_COUNT_STDERR, NINJA_INACTIVITY_TIMEOUT, NINJA_INACTIVITY_TIMEOUT_AGENT_MODELS, NINJA_INACTIVITY_TIMEOUT_CODING_PLAN, NINJA_MAX_RETRIES, NINJA_MODEL, NINJA_OPENCODE_SERVE_MODE, NINJA_OPENROUTER_PROVIDERS, NINJA_RETRY_DELAY_SEC, NINJA_SAFETY_MODE, NINJA_SEARCH_PROVIDER, NINJA_TASKS_DB, NINJA_TIMEOUT_SEC, OPENAI_BASE_URL, OPENAI_MODEL, OPENROUTER_MODEL, REPO_PATH, TEST_PATH
Where it talks to
no vendor host named in the codeAlso openrouter.ai, opencode.dev, claude.ai, ex.com, astral.sh, yourrepo.com, opencode.ai, arxiv.org — not the publisher's domain; check what for before connecting.
What the honeypot saw
no credential files read · reached only astral.sh
What we could not test
use of the skill by an agent

Connect it with a scoped credential, under the guard, and read the third-party hosts first. The code names openrouter.ai, opencode.dev, claude.ai, ex.com, astral.sh, yourrepo.com, opencode.ai, arxiv.org as well as its own vendor. The guard injects API_KEY, NINJA_CREDENTIAL_PASSWORD, NINJA_CREDENTIALS_DB, OPENAI_API_KEY, OPENROUTER_API_KEY, PY_PI_TOKEN, TWINE_PASSWORD, UV_PUBLISH_TOKEN only into requests to the host you bind (and its subdomains) and refuses the rest.

$vet-skills run --net declared -- uvx ninja-mcp

Never paste a credential into a chat, a ticket or a report, including ours. How the guard holds it.

Is [email protected] safe to install?

KillerSkills ran it in the KillerSkills honeypot sandbox (2 scenarios; install scripts ran; no agent task scenario for this bundle) on 2026-11-13 and scored it 68/100 (Caution). It is not known to be malicious, but it has behaviour or code a security policy should decide on before install. Notable findings: Privileged sudo command; Access to sensitive file paths; Privileged sudo command. Summary: calls astral.sh only, touches nothing outside the project, writes no memory.

Behavior trace

Honeypot run · 0 s · 2 scenarios
t+CategoryObserved action
0.0sprocessinstall script run in the sandbox
0.2snetworkCONNECT tcp://astral.sh:443 · not in the allow-list, refused
0.2sprocessexec /usr/bin/dirname
0.2sprocessexec /usr/bin/cut
0.2sprocessexec /usr/bin/curl
0.2sprocessexited 22: curl: (22) The requested URL returned error: 403
0.2sprocessscript backend runs setup only
0.2sprocessscript backend runs setup only
0.2sprocesssecond launch, clock +45 days, CI unset
0.4snetworkCONNECT tcp://astral.sh:443 · not in the allow-list, refused
0.4sprocessexec /usr/bin/dirname
0.4sprocessexec /usr/bin/cut
0.4sprocessexec /usr/bin/curl
0.4sprocessexited 22: curl: (22) The requested URL returned error: 403

Static findings

HIGH
Privileged sudo commandscripts/packaging/build-deb.sh:176 · Privileged sudo command — agent may execute with elevated privilegesecho " sudo apt-get install -f # Install dependencies if needed"Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.
AST05
HIGH
Access to sensitive file pathsscripts/release.sh:21 · Access to sensitive file paths — SSH keys, AWS credentials, env files, or system files# 2. PY_PI_TOKEN in .env at the repository rootFix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.
AST05
HIGH
Privileged sudo commandscripts/packaging/build-deb.sh:175 · Privileged sudo command — agent may execute with elevated privilegesecho " sudo dpkg -i packaging/debian/ninja-mcp_${VERSION}_all.deb"Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.
AST05
HIGH
Privileged sudo commandscripts/packaging/build-deb.sh:185 · Privileged sudo command — agent may execute with elevated privilegesecho " 3. Users add: echo 'deb [trusted=yes] http://yourrepo.com/ ./' | sudo tee /etc/apt/sources.list.d/ninja-mcp.list"Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.
AST05
CRITICAL
Pipe-to-shell patternscripts/install.sh:69 · Pipe-to-shell pattern — downloads and immediately executes remote codecurl -LsSf https://astral.sh/uv/install.sh | shFix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.
AST06
CRITICAL
Destructive command against a filesystem root or devicesrc/ninja_agent/runner.py:83 · Destructive command against a filesystem root or devicere.compile(r"\brm\s+[^|;&]*-f\s+r?\s*/(\s|$|;)"), # rm -fr /Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.
AST05
HIGH
Destructive file system command detectedscripts/packaging/build-deb.sh:98 · Destructive file system command detectedrm -rf /opt/ninja-mcpFix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.
AST05
HIGH
Access to sensitive file pathsscripts/release.sh:241 · Access to sensitive file paths — SSH keys, AWS credentials, env files, or system filesif [ -z "$TOKEN" ] && [ -f .env ]; thenFix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.
AST05
CRITICAL
Destructive command against a filesystem root or devicesrc/ninja_agent/runner.py:82 · Destructive command against a filesystem root or devicere.compile(r"\brm\s+[^|;&]*-r\s*f?\s*/(\s|$|;)"), # rm -rf /Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.
AST05
HIGH
Destructive file system command detectedsrc/ninja_agent/runner.py:82 · Destructive file system command detectedre.compile(r"\brm\s+[^|;&]*-r\s*f?\s*/(\s|$|;)"), # rm -rf /Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.
AST05
MEDIUM
Python subprocess execution detectedsrc/ninja_coder/safety.py:150 · Python subprocess execution detectedresult = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.
AST05
MEDIUM
File permission modification commandscripts/install.sh:112 · File permission modification command — agent changes file ownership/permissionschmod +x "$SCRIPT_DIR"/*.shFix: Request the narrowest permission that works; replace wildcards with the exact paths or hosts.
AST05
MEDIUM
Python subprocess execution detectedsrc/ninja_coder/safety.py:201 · Python subprocess execution detectedresult = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.
AST05
MEDIUM
Python subprocess execution detectedscripts/e2e_live.py:36 · Python subprocess execution detectedsubprocess.run(["git", "init"], cwd=REPO, check=True, capture_output=True)Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.
AST05
HIGH
Access to sensitive file pathssrc/ninja_config/modern_tui.py:1140 · Access to sensitive file paths — SSH keys, AWS credentials, env files, or system files# Resolve the effective value (SecretStore -> env -> .env) so the rowFix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.
AST05
MEDIUM
Python subprocess execution detectedsrc/ninja_coder/driver.py:2818 · Python subprocess execution detectedsubprocess.run(["git", "add", "-A"], cwd=path, check=False, capture_output=True)Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.
AST05
MEDIUM
Python subprocess execution detectedsrc/ninja_coder/safety.py:55 · Python subprocess execution detectedname = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.
AST05
MEDIUM
Python subprocess execution detectedscripts/e2e_live.py:40 · Python subprocess execution detectedsubprocess.run(["git", "config", "user.name", "E2E"], cwd=REPO, check=True, capture_output=True)Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.
AST05
MEDIUM
Process kill commandsrc/ninja_coder/driver.py:1440 · Process kill command — agent can terminate processesf"[watchdog] Could not kill child {child.pid}: {ke}"Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.
AST05
MEDIUM
Remote installer piped to shellscripts/install.sh:69 · Remote installer piped to shellcurl -LsSf https://astral.sh/uv/install.sh | shFix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.
AST07
MEDIUM
Python subprocess execution detectedsrc/ninja_coder/daemon.py:179 · Python subprocess execution detectedprocess = subprocess.Popen(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.
AST05
MEDIUM
Process kill commandscripts/restart_mcp.sh:40 · Process kill command — agent can terminate processeserror "Failed to kill all processes"Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.
AST05
MEDIUM
Python subprocess execution detectedsrc/ninja_coder/driver.py:2816 · Python subprocess execution detectedsubprocess.run(["git", "init", "-q"], cwd=path, check=False, capture_output=True)Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.
AST05
MEDIUM
Python subprocess execution detectedscripts/benchmark_prompts.py:24 · Python subprocess execution detectedr = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.
AST05
MEDIUM
Python subprocess execution detectedsrc/ninja_agent/runner.py:950 · Python subprocess execution detectedlambda *a, **k: subprocess.run(*a, check=False, **k)Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.
AST05
MEDIUM
Process kill commandscripts/restart_mcp.sh:97 · Process kill command — agent can terminate processeskill $TEST_PID 2>/dev/null || trueFix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.
AST05
HIGH
Access to sensitive file pathsscripts/release.sh:244 · Access to sensitive file paths — SSH keys, AWS credentials, env files, or system files[ -n "$TOKEN" ] || die "No PyPI token found. Set UV_PUBLISH_TOKEN or add PY_PI_TOKEN to .env"Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.
AST05
MEDIUM
Python subprocess execution detectedsrc/ninja_coder/safety.py:127 · Python subprocess execution detectedresult = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.
AST05
HIGH
Auto-update or dynamic fetch configurationsrc/ninja_common/config_cli.py:596 · Auto-update or dynamic fetch configuration — agent may load new code at runtimeprint_colored("❌ Auto-updater not available in this installation", "red")Fix: Pin versions and sources; vendor anything fetched at install time.
AST06
HIGH
Access to sensitive file pathsscripts/release.sh:242 · Access to sensitive file paths — SSH keys, AWS credentials, env files, or system filesTOKEN="$(grep -E '^(PY_PI_TOKEN|UV_PUBLISH_TOKEN)=' .env | head -1 | cut -d= -f2- | tr -d "\"'" || true)"Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.
AST05
HIGH
Access to sensitive file pathsscripts/smoke_test.sh:99 · Access to sensitive file paths — SSH keys, AWS credentials, env files, or system filesassert not is_path_within('/etc/passwd', d), 'Should not be within'Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.
AST05
MEDIUM
File permission modification commandscripts/fix_config.sh:130 · File permission modification command — agent changes file ownership/permissionschmod 600 "$CONFIG_FILE"Fix: Request the narrowest permission that works; replace wildcards with the exact paths or hosts.
AST05
HIGH
Access to sensitive file pathsscripts/run_server_stdio.sh:10 · Access to sensitive file paths — SSH keys, AWS credentials, env files, or system files# Load environment variables if .env file existsFix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.
AST05
MEDIUM
Python subprocess execution detectedscripts/e2e_live.py:37 · Python subprocess execution detectedsubprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.
AST05
MEDIUM
Python subprocess execution detectedsrc/ninja_coder/worktree.py:636 · Python subprocess execution detecteddiff_result = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.
AST05
MEDIUM
File permission modification commandscripts/packaging/build-deb.sh:87 · File permission modification command — agent changes file ownership/permissionschmod 755 "$PKG_DIR/DEBIAN/postinst"Fix: Request the narrowest permission that works; replace wildcards with the exact paths or hosts.
AST05
MEDIUM
Process kill commandsrc/ninja_coder/driver.py:2108 · Process kill command — agent can terminate processestask_logger.error(f"Failed to force-kill process group: {kill_error}")Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.
AST05
MEDIUM
Python subprocess execution detectedscripts/e2e_live.py:41 · Python subprocess execution detectedsubprocess.run(["git", "add", "."], cwd=REPO, check=True, capture_output=True)Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.
AST05
MEDIUM
Python subprocess execution detectedsrc/ninja_coder/worktree.py:281 · Python subprocess execution detectedresult = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.
AST05
MEDIUM
File permission modification commandscripts/packaging/build-deb.sh:103 · File permission modification command — agent changes file ownership/permissionschmod 755 "$PKG_DIR/DEBIAN/prerm"Fix: Request the narrowest permission that works; replace wildcards with the exact paths or hosts.
AST05
MEDIUM
Python subprocess execution detectedscripts/e2e_live.py:42 · Python subprocess execution detectedsubprocess.run(["git", "commit", "-m", "init"], cwd=REPO, check=True, capture_output=True)Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.
AST05
MEDIUM
Python subprocess execution detectedsrc/ninja_coder/driver.py:2819 · Python subprocess execution detectedsubprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.
AST05
MEDIUM
Python subprocess execution detectedsrc/ninja_coder/safety.py:63 · Python subprocess execution detectedemail = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.
AST05
MEDIUM
Python subprocess execution detectedsrc/ninja_coder/driver.py:1257 · Python subprocess execution detectedprocess = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.
AST05
HIGH
Destructive file system command detectedsrc/ninja_agent/runner.py:83 · Destructive file system command detectedre.compile(r"\brm\s+[^|;&]*-f\s+r?\s*/(\s|$|;)"), # rm -fr /Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.
AST05
MEDIUM
Python subprocess execution detectedsrc/ninja_common/daemon.py:389 · Python subprocess execution detectedresult = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.
AST05
MEDIUM
Python subprocess execution detectedsrc/ninja_common/daemon.py:491 · Python subprocess execution detectedresult = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.
AST05
MEDIUM
Python subprocess execution detectedsrc/ninja_common/hooks_base.py:156 · Python subprocess execution detectedresult = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.
AST05
MEDIUM
Process kill commandsrc/ninja_common/daemon.py:145 · Process kill command — agent can terminate processes# Wait for both tasks, but don't let stdin closure kill SSEFix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.
AST05
MEDIUM
Python subprocess execution detectedsrc/ninja_common/daemon.py:505 · Python subprocess execution detectedresult = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.
AST05
MEDIUM
Python subprocess execution detectedsrc/ninja_common/daemon.py:426 · Python subprocess execution detectedresult = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.
AST05
MEDIUM
Python subprocess execution detectedsrc/ninja_config/modern_tui.py:1449 · Python subprocess execution detectedresult = subprocess.run(cmd, capture_output=True, text=True, check=False)Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.
AST05
MEDIUM
Process kill commandsrc/ninja_common/daemon.py:545 · Process kill command — agent can terminate processeslogger.warning(f"Could not kill process {pid}: {e}")Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.
AST05
MEDIUM
Python subprocess execution detectedsrc/ninja_common/config_cli.py:659 · Python subprocess execution detectedresult = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.
AST05
MEDIUM
Python subprocess execution detectedsrc/ninja_config/credentials.py:227 · Python subprocess execution detectedresult = subprocess.run(Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.
AST05
MEDIUM
Python subprocess execution detectedsrc/ninja_config/ui/settings.py:248 · Python subprocess execution detectedsubprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.
AST05
MEDIUM
Python subprocess execution detectedsrc/ninja_coder/worktree.py:660 · Python subprocess execution detectedstatus_result = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.
AST05
MEDIUM
Python subprocess execution detectedsrc/ninja_common/daemon.py:446 · Python subprocess execution detectedresult = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.
AST05
MEDIUM
Process kill commandsrc/ninja_common/daemon.py:717 · Process kill command — agent can terminate processes# Force killFix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.
AST05
MEDIUM
Python subprocess execution detectedsrc/ninja_common/hooks_base.py:82 · Python subprocess execution detectedresult = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.
AST05
MEDIUM
Python subprocess execution detectedsrc/ninja_config/modern_tui.py:1357 · Python subprocess execution detectedresult = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.
AST05
MEDIUM
Python subprocess execution detectedsrc/ninja_coder/worktree.py:755 · Python subprocess execution detectedreturn subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.
AST05
MEDIUM
Python subprocess execution detectedsrc/ninja_coder/worktree.py:644 · Python subprocess execution detectedapply_result = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.
AST05
MEDIUM
Python subprocess execution detectedsrc/ninja_common/config_cli.py:652 · Python subprocess execution detectedsubprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.
AST05
MEDIUM
Python subprocess execution detectedsrc/ninja_common/config_cli.py:332 · Python subprocess execution detectedresult = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.
AST05
MEDIUM
Python subprocess execution detectedsrc/ninja_common/hooks_base.py:133 · Python subprocess execution detectedresult = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.
AST05
MEDIUM
Python subprocess execution detectedsrc/ninja_config/ui/settings.py:255 · Python subprocess execution detectedresult = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.
AST05
MEDIUM
Python subprocess execution detectedsrc/ninja_config/ui/base.py:101 · Python subprocess execution detectedresult = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.
AST05

Cost to the agent

Instructions loaded
≈48 tok
1 file · 81 in bundle

Tokens estimated at four characters each. Skills load their instruction text when triggered; the figure is what that costs.

Known vulnerabilities

No advisories in OSV for ninja-mcp@1.9.2 as of 31 h ago. This is the package itself, not its dependencies.

What would make this Verified

12 points to 80 · weights: behavior 45%, static 25%, prompt 15%, publisher 15%
  1. Pipe-to-shell pattern≈ +9 on the totalBuild commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.
  2. Destructive command against a filesystem root or device≈ +9 on the totalBuild commands from fixed arguments; do not interpolate untrusted strings into a shell.
  3. Unclaimed publisher≈ +8 on the totalClaim ninja-mcp-contributors: a verified publisher gets +50 on publisher trust. It is free and usually instant with GitHub sign-in.
  4. Privileged sudo command≈ +4 on the totalBuild commands from fixed arguments; do not interpolate untrusted strings into a shell.
  5. Access to sensitive file paths≈ +4 on the totalStop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.
  6. Destructive file system command detected≈ +4 on the totalBuild commands from fixed arguments; do not interpolate untrusted strings into a shell.
Publish a new version to PyPI, then queue it here. Not your skill? Claim the handle to get verdict changes by email.Claim ninja-mcp-contributorsPropose a patch to the maintainer