knock@r1
CAUTION· not startedPublisher claims: "A local-first MCP server that gives AI coding agents a persistent code map and memory, so they can retrieve relevant code with exact file:line pointers and rationale instead of re-reading files. It also lets agents save findings for future sessions and flags notes as stale when referenced files change." 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: 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_KEYConfiguration, not credentials: KNOCK_HOME, KNOCK_LOG_LEVEL, VITE_URL- Where it talks to
- no vendor host named in the code
- 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. It asks for API_KEY and talks to its vendor. Give the credential to the guard, not the server: the value never enters the server's environment and only travels to the host you bind. What the tools do with a real credential was not observed.
Never paste a credential into a chat, a ticket or a report, including ours. How the guard holds it.
Is knock@r1 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-11 and scored it 66/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: Access to sensitive file paths; 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 · 2 scenarios · 0 deviationsStatic findings
".netrc",Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.".xml": "xml", ".gradle": "gradle", ".properties": "properties", ".conf": "conf", ".env.example": "dotenv"}Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.assert ".env" not in found and ".env" in skippedFix: 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, timeout=timeout, env=_env(), stdin=subprocess.DEVNULL)Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.AWS_KEY = "AKIAIOSFODNN7EXAMPLE"Fix: Never read or enumerate credential locations; accept a documented environment variable instead.""".git .hg .svn node_modules bower_components jspm_packages vendor third_party .venv venv env .envFix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.".env",Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.".env.*",Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.".env": f"STRIPE_SECRET_KEY={STRIPE_SECRET}\n",Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.@pytest.mark.parametrize("path", ["../../etc/passwd", "/etc/passwd", ".env", "build/bundle.js", "config/secrets.yaml", ".git/config", "missing.py"])Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.subprocess.run(["git", "-c", "core.hooksPath=/dev/null", "clone", "-q", "--depth", str(spec.get("history_depth", 200)),Fix: Put hosts, commands and strings in plain source. Decoding at runtime looks identical to malware and costs points on its own.if name.startswith(".env.") and name.endswith((".example", ".sample", ".template")):Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.<summary><b>Do I need an API key or a paid model?</b></summary> No. Indexing and search are fully deterministic and local. The only thing that uses an API is thFix: Remove the text that addresses the agent rather than the reader; describe behavior, do not instruct.out = subprocess.run(["git", "-C", str(root), "ls-files", "-z"], capture_output=True, check=True).stdout.decode()Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.({"category": "debugging", "content": "valid content here", "sources": [{"path": ".env"}]}, "not an indexed file"),Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.rec = svc.record_knowledge("debugging", 'Local login works with api_key = "sk_live_abcdefghijklmnop1234"', repository=name)Fix: Never read or enumerate credential locations; accept a documented environment variable instead.svc.open_code("../../etc/passwd:1-2", repository=name)Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.STRIPE_SECRET = "sk_live_51HxYzAbCdEfGhIjKlMnOp"Fix: Never read or enumerate credential locations; accept a documented environment variable instead."*.env",Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.<summary><b>🖥️ Optional: use knock yourself from the terminal</b></summary> <br> You never *need* these, but they're handy. | Command | When you'd use it | |--Fix: Remove the text that addresses the agent rather than the reader; describe behavior, do not instruct.bad_path = await c.call_tool("get_source", {"path": "../../etc/passwd"})Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.return subprocess.run(["git", "-C", str(root), *args], check=True, capture_output=True, text=True, env=env).stdoutFix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.out = subprocess.run(["git", "-C", str(root), "ls-files", "-z"], capture_output=True, check=True).stdout.decode()Fix: Put hosts, commands and strings in plain source. Decoding at runtime looks identical to malware and costs points on its own._SPACE = re.compile(r"[ \t\r\f\v
]+")Fix: Keep SKILL.md to visible, descriptive text. Remove comments and encoded text that address the agent.head = subprocess.run(["git", "-C", str(dest), "rev-parse", "HEAD"], capture_output=True, text=True, check=True).stdout.strip()Fix: Put hosts, commands and strings in plain source. Decoding at runtime looks identical to malware and costs points on its own.assert ".env" not in paths and "certs/server.pem" not in paths and "config/secrets.yaml" not in pathsFix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.@pytest.mark.parametrize("path", [".env.example", "src/secret_manager.py", "README.md", "src/keys.py"])Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose."aws = 'AKIAIOSFODNN7EXAMPLE'",Fix: Never read or enumerate credential locations; accept a documented environment variable instead.> Add this line to your project's `CLAUDE.md` so the agent uses knock when it pays off:Fix: Remove the text that addresses the agent rather than the reader; describe behavior, do not instruct.@pytest.mark.parametrize("bad", ["../etc/passwd", "/etc/passwd", "a/../../b", "C:\\Windows", "", ".git/config", "a\x00b"])Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.@pytest.mark.parametrize("path", [".env", "config/.env.production", "id_rsa", "certs/server.pem", "secrets.yaml",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. 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
Vulnerability advisories (OSV) cover npm and PyPI packages; this registry has no advisory database.
What would make this Verified
14 points to 80 · weights: behavior 45%, static 25%, prompt 15%, publisher 15%- Unclaimed publisher≈ +8 on the totalClaim hasangilani: a verified publisher gets +50 on publisher trust. It is free and usually instant with GitHub sign-in.
- Hidden instructions≈ +6 on the totalRemove HTML comments, zero-width characters and white-on-white text that carry instructions. Everything the agent is meant to read should be visible to the person reading the file.
- 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.
- Hidden zero-width characters detected≈ +4 on the totalKeep SKILL.md to visible, descriptive text. Remove comments and encoded text that address the agent.
- New publisher≈ +3 on the totalTime clears this on its own after 14 and 30 days. Claiming the handle (+50) is the fastest way past it.
- Python subprocess execution detected≈ +2 on the totalBuild commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.