MCP, MCP server
com.failecho/failecho
Check what other agents hit the same tool failure — and what recovery worked.
Compatibility: Not stated.
Grade C
One Medium finding. Read the findings before installing.
Not a guarantee. A hygiene check of the source at the commit shown, not a security audit.
Rescanned at commit 8276e26dac84, unchanged since the check below.
NETWORK_HOST_FROM_INPUT
Why this grade
- NETWORK_HOST_FROM_INPUT Medium
A file takes a URL or endpoint as input and has no fixed host list.
app/main.py, line 378
curl -sX POST {base_url}/v1/query -H 'Content-Type: application/json' \
Any High, or two or more Medium findings, give D. One Medium gives C. Low findings or a security Note give B. Each code names a finding behind the letter.
If you think this grade is wrong, email [email protected] with the entry link and your evidence. We aim to acknowledge within two working days and decide within seven. If we confirm an error, we aim to correct it within 24 hours of confirming it. These are aims, not guarantees.
Grades are a hygiene check of the source at the commit shown, on the date checked, not a security audit or a guarantee. The free directory grades are automated. Before release, a PlugVet engineer reviews every paid report and any grade we hold back, including all F grades, against the source code and the evidence we quote.
What was checked
Plain notes from the hygiene checks.
Permissions
Concern
can delete files.
PERMISSION_DELETE_FILES
failecho_mcp/proxy.py, line 321
self.proc: subprocess.Popen | None = None
failecho_mcp/proxy.py, line 478
self.proc = subprocess.Popen(self.argv, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
failecho_sandbox/__init__.py, line 115
self.proc: subprocess.Popen | None = None
Show more
failecho_sandbox/__init__.py, line 144
subprocess.run(["mkfs.ext4", "-q", "-F", "-O", "^has_journal", scratch],
failecho_sandbox/__init__.py, line 160
self.proc = subprocess.Popen(
failecho_sandbox/__init__.py, line 195
shutil.rmtree(self.dir, ignore_errors=True)
failecho_sandbox/__init__.py, line 299
shutil.rmtree(path, ignore_errors=True)
failecho_sandbox/canary.py, line 68
p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
failecho_sandbox/guest_init.py, line 57
subprocess.call(list(argv), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
failecho_sandbox/guest_init.py, line 142
p = subprocess.Popen(argv, cwd=WORK, env=env, **who,
Install and update
Concern
dependencies are not pinned.
INSTALL_UNPINNED
requirements.txt, line 2
fastapi>=0.111
Network
Serious
accepts a host from input, with no fixed list in this file.
NETWORK_HOST_FROM_INPUT
app/main.py, line 378
curl -sX POST {base_url}/v1/query -H 'Content-Type: application/json' \
app/main.py, line 481
curl -fsSL -o .opencode/plugin/failecho.js \\
app/main.py, line 508
curl -sX POST {base_url}/v1/query -H 'Content-Type: application/json' \
Show more
app/mcp_server.py, line 6
fingerprinting or intelligence logic, so an MCP client and a curl user cannot
app/web/static/app.js, line 63
return fetch(path, { headers: { accept: "application/json" } }).then(function (r) {
app/web/static/app.js, line 415
fetch(base + "/fleet.json", { cache: "no-store" })
app/web/static/fleet.js, line 154
fetch("/fleet.json", { cache: "no-store" }).then(function (r) { return r.ok ? r.json() : null; })
client/failure_network.py, line 98
with urllib.request.urlopen(request, timeout=self.timeout) as response:
client/failecho/__init__.py, line 151
with urllib.request.urlopen(request, timeout=self.timeout) as response:
deploy/cloudflare-ips.sh, line 14
V4=$(curl -fsS --max-time 20 https://www.cloudflare.com/ips-v4)
deploy/deploy.sh, line 80
if [ "$(curl -s -o /dev/null -w '%{http_code}' --max-time 2 http://127.0.0.1:8000/health)" = "200" ]; then
failecho_fleet/onboard.py, line 228
r = self.vm.run(["sh", "-c", f"curl -sS -L --max-time 20 -- {_q(url)} | head -c 30000"], timeout=30)
failecho_fleet/onboard.py, line 321
with urllib.request.urlopen(req, timeout=90) as r:
failecho_sandbox/__main__.py, line 44
"d=json.load(urllib.request.urlopen('https://pypi.org/pypi/requests/json', timeout=20)); print('version', d['info']['version'])",
Secrets
Concern
reads a credential or environment file.
SECRETS_ENV_READ SECRETS_PATH_DOTENV
client/failecho/__init__.py, line 128
self.operator_token = operator_token or os.environ.get("FAILECHO_OPERATOR_TOKEN") or None
failecho_agent/__init__.py, line 58
OPERATOR_TOKEN = os.environ.get("FIN_FIRST_PARTY_TOKEN") or os.environ.get("FAILECHO_OPERATOR_TOKEN")
failecho_agent/__init__.py, line 68
"key": os.environ.get("GROQ_API_KEY"), "models": ["openai/gpt-oss-20b"]},
Show more
failecho_agent/__init__.py, line 71
"key": os.environ.get("GEMINI_API_KEY"), "models": ["gemini-flash-latest", "gemini-3.7-flash"]},
failecho_autoreport/__init__.py, line 285
self.operator_token = operator_token or os.environ.get("FAILECHO_OPERATOR_TOKEN") or None
failecho_autoreport/identity.py, line 57
override = os.environ.get("FAILECHO_IDENTITY_KEY")
failecho_fleet/__init__.py, line 89
"key": os.environ.get("GROQ_API_KEY"), "models": ["openai/gpt-oss-20b"], "daily_cap": 3000,
failecho_fleet/__init__.py, line 96
"key": os.environ.get("GEMINI_API_KEY"), "models": ["gemini-flash-latest"], "daily_cap": 40,
.env.example, line 1
# FailEcho configuration. Copy to .env or export these in your service unit.
.gitignore, line 4
venv/
README.md, line 1217
LICENSE SECURITY.md CONTRIBUTING.md .env.example
docs/record-the-demo.md, line 116
any `.env` or token in scrollback, browser tabs if the terminal is not
Agent instructions
Pass
No instruction to ignore earlier instructions or to hide a step.
Obfuscation
Pass
No encoded or minified payload found.
Licence
Pass
A licence file is present (LICENSE).
Maintainer activity
Pass
The latest commit is within the last 365 days.
Note
Hygiene check of commit 8276e26dac84. can delete files. dependencies are not pinned. accepts a host from input, with no fixed list in this file. reads a credential or environment file.
Date and source
Date checked:
github.com
Commit graded: 8276e26dac845d485bb98d39878b45e644c4595a
This link goes to the original host. PlugVet does not host or check what you download from there, and installing it is your own decision and risk.