psamvault-mcp@0.5.5
CAUTION· install onlyPublisher claims: "MCP server for psamvault — lets AI agents use stored credentials without seeing them." Observed in sandbox: no network, touches nothing outside the project, writes no memory.
Coverage
Nothing executable in the bundle ran; the trace covers the install step only.- Tested
- 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
- no credential variables read in the code
- Where it talks to
- no vendor host named in the codeAlso render.com, onrender.com, openrouter.ai, tavily.com — not the publisher's domain; check what for before connecting.
- What the honeypot saw
- no credential files read · no network
- What we could not test
- use of the skill by an agent
Connect it under the guard. Nothing executable in the bundle ran; the trace covers the install step only. The code names no credential variable; the guard pins the network to what the honeypot saw and logs every call.
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 (1 scenario; nothing executable in the bundle ran; the trace covers the install step only) on 2026-11-15 and scored it 70/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: URL to the cloud instance metadata address; Access to sensitive file paths; Access to sensitive file paths. Summary: no network, touches nothing outside the project, writes no memory.
Behavior trace
Honeypot run · 0 s · 1 scenarios · 0 deviationsStatic findings
# curl http://169.254.169.254/$KEYFix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.Scan a project directory for `.env` files containing exposed API keys,Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.description: "Use psamvault MCP server: credential vault, browser login, API key injection, .env secret protection. MCP tools keep secrets out of the agent's context window."Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.| `scan_and_protect` | Scan .env files for exposed secrets | **First** when working in a project with .env files |Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.if pattern.startswith(".env"):Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.# Only hosts whose .env location is VERIFIED appear here: writing a secret into a guessed path isFix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.(stored as ``project_name/.env/KEY_NAME``) are returned.Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.env_scanner — .env file scanning and API key/secret detection module.Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose."Export a vault API key into an agent host's .env file as an environment variable "Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose."- scan_and_protect → scan project .env files for exposed secrets and protect them\n"Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.| `how-to-scan-and-protect` | Guide for scanning and protecting `.env` secrets |Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.`export_key_to_env_file(key_name="tavily", env_var_name="TAVILY_API_KEY")` → writes `HERMES_HOME/.env`,Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose."""Resolve the ``.env`` file an agent host reads its tool variables from.Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.``atlas054probe/.env/MY_CUSTOM_KEY`` while the entry is stored asFix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.key, run a CLI command with a token, inject a secret into a process, protect a project's `.env`, or listFix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.When working in a project directory that has `.env` files, callFix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose."""Scan a project directory for exposed secrets in .env files and protect them.Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.- Relative paths: ``services/auth/.env``Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.# Check if this key belongs to a project (format: project/.env/KEY)Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.| `export_key_to_env_file` | Export a vault API key into an agent's `.env` as an env var (default `HERMES_HOME/.env`) — updates in place, backs up, auto-verifies |Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.Detects exposed secrets in .env files by analysing key names andFix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.| `scan_and_protect` | `project_dir, patterns, project_name` | Scan & encrypt .env secrets | ❗ Encrypts into vault |Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.unscoped ``env/.env/KEY`` (the shape ``scan_and_protect`` writes).Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.- User wants to secure their project's `.env` files (`scan_and_protect`)Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.# That first run found a real bug rather than a slow machine: the timeout kill in cmd_runner signalled theFix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.…he 13 tools and their names are unchanged. `scan_and_protect` no longer stores `.env` backup copies (`.env.bak-*`, `.env.old`, `.env.save`, dated `.env.<digits>`) a…Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose."(default: HERMES_HOME/.env for agent='hermes'; unknown hosts need env_path). "Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.…path, dry_run, verify_url, skip_verify` | Export a vault API key into an agent `.env` as an environment variable (default `HERMES_HOME/.env`) — updates in place, ba…Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.3. Replacements are `psamvault:KEY_NAME` placeholders in the `.env`Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose."- export_key_to_env_file → export a vault key into an agent .env as an env var (never returns the key)\n"Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.…he credential value. - **`scan_and_protect`** — Scans a project directory for `.env` files, detects secrets using pattern matching, encrypts them into the psamvaul…Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose."Scan a project directory for exposed secrets in .env files and protect them. "Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.``atlas054probe/.env/my_custom_key``.Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.parts = name.split("/.env/")Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.- Pattern parts: ``.env`` in a path componentFix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.# ── Agent-host .env targets ───────────────────────────────────────────────────Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.add `.env` to their `.gitignore`.Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.``project/.env/KEY`` — pass the project name hereFix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.* a **full stored name** — what ``list_api_keys`` returns, e.g. ``project/.env/KEY`` or theFix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.return Path(home) / ".env"Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.| `scan_and_protect` | Encrypt project `.env` secrets into psamvault |Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.return base / "hermes" / ".env"Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.### 5. Protecting `.env` filesFix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.one moments after you kill it. Killing processes without quitting the app looks like it "did nothing".Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.| `scan_and_protect(project_dir, patterns, project_name)` | Scan a project for `.env` secrets, encrypt them into psamvault |Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose."""A genuine timeout must kill the process (tree) and hand back what was captured — notFix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.return subprocess.Popen(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.return subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.return subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.proc = subprocess.Popen(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.proc = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.# command, or a test runner), so killpg here would kill the caller instead of theFix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.subprocess.run(["git", "init", "-q", str(root)], check=True, capture_output=True)Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.proc = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.proc = subprocess.run(["git", "-C", str(repo), *args], capture_output=True, text=True)Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.out = subprocess.run(["tasklist", "/FI", f"PID eq {pid}", "/NH"],Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.proc = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.and which respawns one the moment you kill it.Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.# timeout kill can target the command's tree without touching the caller's group. WithoutFix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.env_file = tmp_path / ".env"Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.proc = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout)Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.proc = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out."""Close the browser if it exists but don't kill the Playwright context.Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.proc = subprocess.run(["git", "-C", str(repo), "rev-parse", "--short", "HEAD"],Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.proc = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.proc = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.proc = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.proc = subprocess.run(["git", "-C", str(clone_path()), "rev-parse", "--abbrev-ref", "HEAD"],Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out."""Where does an agent host read its .env? Explicit path wins; known hosts have defaults."""Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.subprocess.run(["git", "-C", str(self.root), "add", "-A"], check=True, capture_output=True)Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.# ── The timeout kill must never signal the CALLER's process group ────────────────────────────────Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.proc = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.proc = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out."""Defence in depth: even sharing a group must not let the kill reach the caller."""Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.subprocess.run(["git", "-C", str(repo), "checkout", "-q", "-b", branch], check=True)Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.non-console signal to TerminateProcess, so a "probe" would kill the process it checks."""Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.assert path.name == ".env"Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.subprocess.run(["taskkill", "/F", "/T", "/PID", str(pid)],Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.result = subprocess.run(["pipx", "list", "--json"], capture_output=True, text=True, timeout=60)Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.return subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.proc = subprocess.run(cmd, capture_output=True, text=True, timeout=900)Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.proc = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.env_file = tmp_path / ".env"Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.env_file = tmp_path / ".env"Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.subprocess.run(["taskkill", "/F", "/T", "/PID", str(pid)],Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.f"({own_group}); the timeout kill would have signalled the caller"Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.return subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.child = subprocess.Popen([sys.executable, "-c", "import time; time.sleep(30)"])Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.subprocess.run(["git", "-C", str(root), "config", key, value], check=True, capture_output=True)Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.proc = subprocess.run(["pipx", "list", "--json"], capture_output=True, text=True, timeout=120)Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.proc = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout)Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.proc = subprocess.run(["git", "-C", str(repo), "status", "--porcelain", "--", "docs/skills"],Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.proc = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.proc = subprocess.run([python, "-c", code], capture_output=True, text=True, timeout=30, env=_child_env())Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.return subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.proc = subprocess.run(["git", *args], cwd=str(cwd), capture_output=True, text=True, env=GIT_ENV)Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.3. Consult the index **as advice only** (its JSON API lags an upload, so it must never refuse on its own) — a contract entry is created when a release is merged,Fix: Remove the text that addresses the agent rather than the reader; describe behavior, do not instruct.head = subprocess.run(["git", "-C", str(repo), "rev-parse", "--abbrev-ref", "HEAD"],Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.monkeypatch.setattr("mcp_server.version_check.httpx.get", boom)Fix: Namespace tool names and keep tool descriptions literal; no instructions to the agent inside them.{"name": "twitter-bot/.env/GROK_API_KEY", "service_hint": "xAI", "created_at": "2026-06-17T06:00:00Z"},Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.subprocess.run(["git", "-C", str(repo), "-c", "[email protected]", "-c", "user.name=t",Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.branches = subprocess.run(["git", "-C", str(repo), "branch", "--list", "sync/skill-docs-*"],Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.{"name": "twitter-bot/.env/GROK_API_KEY", "service_hint": "xAI", "notes": None,Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose."mcp_server.version_check.httpx.get",Fix: Namespace tool names and keep tool descriptions literal; no instructions to the agent inside them.``scan_and_protect`` stores ``project/.env/KEY``, so a leaf has to be resolved to the storedFix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.{"name": "twitter-bot/.env/GROK_API_KEY", "service_hint": "xAI", "created_at": "2026-06-17T06:00:00Z"},Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose."mcp_server.version_check.httpx.get",Fix: Namespace tool names and keep tool descriptions literal; no instructions to the agent inside them.subprocess.run(["git", "-C", str(repo), *args], check=True, capture_output=True)Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.app spawns a new one the moment you kill it."""Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.{"name": "twitter-bot/.env/TWITTER_TOKEN", "service_hint": "Twitter", "created_at": "2026-06-17T07:00:00Z"},Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.Cost to the agent
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 psamvault-mcp@0.5.5 as of 12 min ago. This is the package itself, not its dependencies.
What would make this Verified
10 points to 80 · weights: behavior 45%, static 25%, prompt 15%, publisher 15%- URL to the cloud instance metadata address≈ +9 on the totalStop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.
- Unclaimed publisher≈ +8 on the totalClaim psam-717: a verified publisher gets +50 on publisher trust. It is free and usually instant with GitHub sign-in.
- 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.
- Process kill command≈ +2 on the totalBuild commands from fixed arguments; do not interpolate untrusted strings into a shell.
- Python subprocess execution detected≈ +2 on the totalBuild commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.
- MCP server using network transport (SSE/HTTP)≈ +2 on the totalNamespace tool names and keep tool descriptions literal; no instructions to the agent inside them.