odoo-mcp-tools@1.6.1
CAUTION· not startedPublisher claims: "Clean-room MCP server for Odoo (Community, Enterprise, online) across versions 10-19." 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
- no credential variables read in the code
- Where it talks to
- no vendor host named in the codeAlso odoo.com, wa.me, transgenia.org — 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 under the guard. Not started: dependency install failed; the server itself was not observed. 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 (2 scenarios; not started: dependency install failed; the server itself was not observed) on 2026-11-08 and scored it 73/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 with embedded credentials; URL with embedded credentials; URL with embedded credentials. Summary: no network, touches nothing outside the project, writes no memory.
Behavior trace
Honeypot run · 0 s · 2 scenarios · 0 deviationsStatic findings
probe = subprocess.run(["docker", "compose", "version"], capture_output=True, check=False)Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.ok = subprocess.run([sys.executable, str(script), f"v{version}"],Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.done = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.secret = "https://admin:[email protected]"Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.done = subprocess.run([sys.executable, str(run_stdio), "--verify-audit", str(path)],Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.``https://user:pass@host`` is valid in ODOO_URL (HTTP basic auth in front ofFix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.# With an "@" the split itself is unsafe: in https://admin:4242#pw@host the hostFix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.monkeypatch, tmp_path, f"http://{CANARY['user']}:{CANARY['url_password']}@{host}")Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose."""``https://user:pass@host`` -> ``https://host`` for logs; never raises."""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.bad = subprocess.run([sys.executable, str(script), "9.9.9"],Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.and ``ODOO_LIVE_SBX18_DIR`` (key file optional; the admin password from ``.env`` is usedFix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.return Settings(url=f"https://gateway:{CANARY_PASSWORD}@{CANARY_HOST}", db="auditdb",Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.self.creds = SimpleNamespace(url="https://gateway:[email protected]", db="db",Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.result = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.# "replace": a lone surrogate echoed back from the input must not killFix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.usage = subprocess.run([sys.executable, str(script), "1.3"],Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.url = fake.url.replace("http://", "http://gw:secret@")Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.url = f"https://admin:4242#{SECRET}@erp.example.com"Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose."server/src/odoo_mcp/.env": CANARY.encode(),Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.f"https://admin:{SECRET}@erp.example.com",Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.url = fake.url.replace("http://", "http://gw:PW-NOT-LEAKED@")Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.report = check_options(_options(odoo_url=f"https://bot:{SECRET}@my-company.odoo.com"))Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.out = subprocess.run(["git", "ls-files", "-z"], cwd=ROOT, 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.done = subprocess.run([sys.executable, str(RUN_STDIO), "--check-copies"],Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.assert validate.index("differs from the uploaded one") < validate.index("npx -y")Fix: Pin versions and sources; vendor anything fetched at install time.probe = subprocess.run(["git", "rev-parse", "--is-inside-work-tree"], cwd=ROOT,Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.for line in (Path(directory).expanduser() / ".env").read_text().splitlines():Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.for line in (Path(directory).expanduser() / ".env").read_text().splitlines():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.proc = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.Since 1.6.0 each keeps an admin API key in its ``.env``, which the tests use; aFix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.The credentials are read from the sandbox's owner-only ``.env`` and the keyFix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.subprocess.run(["git", "init", "-q"], cwd=repo, check=True)Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.assert 'npx -y "$MCPB" validate' in text and 'npx -y "$MCPB" unpack' in textFix: Pin versions and sources; vendor anything fetched at install time.return subprocess.run(["git", *args], cwd=ROOT, capture_output=True, text=True, check=False)Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.assert re.search(r"sudo unshare --net -- .*scripts/build_mcpb\.py \\\n\s*--smoke \S+ --offline",Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.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
No advisories in OSV for odoo-mcp-tools@1.6.1 as of 5d ago. This is the package itself, not its dependencies.
What would make this Verified
7 points to 80 · weights: behavior 45%, static 25%, prompt 15%, publisher 15%- Unclaimed publisher≈ +8 on the totalClaim transgenia: 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.
- 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.
- URL with embedded credentials≈ +2 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.