quotable-mcp@0.2.0
VERIFIED· not startedPublisher claims: "Local-first MCP server and CLI that turns recordings, podcast feeds and media URLs into cite-ready transcripts" Observed in sandbox: no network, touches nothing outside the project, writes no memory.
Coverage
Not started: dependency install failed; the server itself was not observed.- Tested
- the dependency install step · every file read, file written and host contacted by what ran
- Not tested
- server startup · the tool list · tool behavior
What this means for the label: Verified 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
HF_TOKENOPENAI_API_KEYQUOTABLE_HF_TOKENConfiguration, not credentials: QUOTABLE_DAEMON, QUOTABLE_MODEL_TTL- Where it talks to
- no vendor host named in the codeAlso deno.com, youtu.be, huggingface.co — 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
- server startup · the tool list · tool behavior
Connect it with a scoped credential, under the guard, and read the third-party hosts first. The code names deno.com, youtu.be, huggingface.co as well as its own vendor. The guard injects HF_TOKEN, OPENAI_API_KEY, QUOTABLE_HF_TOKEN only into requests to the host you bind (and its subdomains) and refuses the rest.
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; not started: dependency install failed; the server itself was not observed) on 2026-11-15 and scored it 81/100 (Verified). In what ran, nothing we could detect went wrong: no undeclared network egress, no credential reads, no persistent instruction writes. What it does with a real credential was not observed; the static findings and the publisher carry the rest of the score. Summary: no network, touches nothing outside the project, writes no memory.
Behavior trace
Honeypot run · 0 s · 2 scenarios · 0 deviationsStatic findings
version = subprocess.run(Fix: Put hosts, commands and strings in plain source. Decoding at runtime looks identical to malware and costs points on its own.done = subprocess.run(cmd, stdin=subprocess.DEVNULL, capture_output=True, text=True)Fix: Put hosts, commands and strings in plain source. Decoding at runtime looks identical to malware and costs points on its own.out = subprocess.run(Fix: Put hosts, commands and strings in plain source. Decoding at runtime looks identical to malware and costs points on its own.subprocess.run(["sh", "-c", "echo leak"], timeout=5)Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.state = subprocess.run(["ps", "-o", "stat=", "-p", str(pid)], capture_output=True, text=True)Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.return subprocess.Popen(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.args = subprocess.run(["ps", "-o", "args=", "-p", str(pid)], capture_output=True, text=True)Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.proc = subprocess.Popen(Fix: Put hosts, commands and strings in plain source. Decoding at runtime looks identical to malware and costs points on its own.subprocess.run(["uv", "build"], cwd=ROOT, check=True, stdin=subprocess.DEVNULL)Fix: Put hosts, commands and strings in plain source. Decoding at runtime looks identical to malware and costs points on its own.proc = subprocess.Popen(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.@pytest.mark.parametrize("url", ["file:///etc/passwd", "ftp://media.example/a.srt", "data:,x"])Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.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.cat = subprocess.run(["cat"], capture_output=True, timeout=5)Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.ΔstartFix: Put hosts, commands and strings in plain source. Decoding at runtime looks identical to malware and costs points on its own.assert not audio.is_url("file:///etc/passwd")Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.info = {"subtitles": {"en": [{"ext": "vtt", "url": "file:///etc/passwd"}]}}Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.done = subprocess.run(Fix: Put hosts, commands and strings in plain source. Decoding at runtime looks identical to malware and costs points on its own.stdio isolation is the SDK's: ``run()`` calls ``MCPServer.run("stdio")`` and never passesFix: Namespace tool names and keep tool descriptions literal; no instructions to the agent inside them.for block in re.split(r"(?:\r?\n){2,}", body.replace("", "").strip()):Fix: Keep SKILL.md to visible, descriptive text. Remove comments and encoded text that address the agent.out = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out."subprocess.run(['sh', '-c', 'echo from-child; cat; pwd']); "Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.out = subprocess.run(Fix: Put hosts, commands and strings in plain source. Decoding at runtime looks identical to malware and costs points on its own.out = subprocess.run(Fix: Put hosts, commands and strings in plain source. Decoding at runtime looks identical to malware and costs points on its own.state = subprocess.run(["ps", "-o", "stat=", "-p", str(pid)], capture_output=True, text=True)Fix: Put hosts, commands and strings in plain source. Decoding at runtime looks identical to malware and costs points on its own.proc = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.out = subprocess.run(Fix: Put hosts, commands and strings in plain source. Decoding at runtime looks identical to malware and costs points on its own.fix=f"chmod 700 {path}",Fix: Request the narrowest permission that works; replace wildcards with the exact paths or hosts.ΔstartFix: Put hosts, commands and strings in plain source. Decoding at runtime looks identical to malware and costs points on its own."location", ["file:///etc/passwd", "ftp://127.0.0.1/a.srt", "data:text/plain,hi"]Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.@pytest.mark.parametrize("source", ["/no/such/file.mp3", "ftp://host/a.mp3", "file:///etc/passwd"])Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose."/etc/passwd",Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.out = subprocess.run([sys.executable, "-c", probe], capture_output=True, text=True, check=True)Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.{url: b"1\n00:00:00,000 --> 00:00:01,000\nx\n"}, {url: "file:///etc/passwd"}Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.assert "chmod 700" in err.value.fixFix: Request the narrowest permission that works; replace wildcards with the exact paths or hosts.@pytest.mark.parametrize("url", ["javascript:alert(1)", "file:///etc/passwd", "/relative.mp3"])Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.out = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.Cost to the agent
Tokens estimated at four characters each. The tool list is re-read by the agent on every turn, so it is the number to compare between servers that do the same job: ranked across the index.
Known vulnerabilities
Not checked against OSV yet; the weekly check has not reached this version.