MCP, MCP server
retinue
English · 简体中文 · English demo · 中文演示
Compatibility: Not stated.
Grade D
Two or more Medium findings, or a High finding. Only try it in a sandbox.
Not a guarantee. A hygiene check of the source at the commit shown, not a security audit.
Rescanned at commit 72aff265c4dd, unchanged since the check below.
SECRETS_PATH_CREDENTIAL OBFUSCATION_MINIFIED_PAYLOAD
Why this grade
- SECRETS_PATH_CREDENTIAL Medium
Mentions a credential store path (~/.ssh, id_rsa, .npmrc, .aws/credentials, credentials.json, .netrc).
node/quota_probe.py, line 75
'claude': home / '.claude/.credentials.json', - OBFUSCATION_MINIFIED_PAYLOAD Medium
Contains a very long line with almost no spaces in a script or style file.
core/panel.py, line 25
.card{display:block;color:inherit;text-decoration:none;background:#182238;border:1px solid #2b3855;border-radius:12px;padding:13px;margin-bottom:10px;box-shadow:0 8px 22px #0508125
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.
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
adapters/collectors/central.py, line 110
result = subprocess.run(ssh_argv(config), capture_output=True, timeout=25, check=False)
adapters/im/feishu.py, line 153
completed = subprocess.run(argv, check=True, capture_output=True, text=True)
adapters/im/feishu.py, line 476
with subprocess.Popen(argv, stdout=subprocess.PIPE, text=True) as process:
Show more
core/daemon.py, line 23
subprocess.run(argv, env=env, check=True)
core/panel_demo.py, line 296
subprocess.run([npm, "ci", "--no-audit", "--no-fund"], cwd=webui, check=True, env=env)
core/panel_demo.py, line 297
subprocess.run([npm, "run", "build"], cwd=webui, check=True, env=env)
core/panel_demo.py, line 311
shutil.rmtree(staging)
core/panel_demo.py, line 316
shutil.rmtree(seed_dir)
core/panel_demo.py, line 342
shutil.rmtree(site_root)
core/panel_demo.py, line 348
shutil.rmtree(api_snap)
core/panel_demo.py, line 364
shutil.rmtree(dest)
core/panel_demo.py, line 367
shutil.rmtree(seed_dir, ignore_errors=True)
core/static_demo.py, line 112
shutil.rmtree(destination)
node/control_relay.py, line 142
runner: Callable[..., subprocess.CompletedProcess[str]] = subprocess.run,
node/control_relay.py, line 256
runner: Callable[..., subprocess.CompletedProcess[str]] = subprocess.run,
scripts/export_community.py, line 216
shutil.rmtree(previous)
Install and update
Pass
No install-time script found, and dependencies are pinned or absent.
Network
Concern
can reach a host that is not written as a fixed address.
NETWORK_NO_FIXED_HOST
scripts/smoke_install.sh, line 39
if out=$(curl -fsS "http://127.0.0.1:${port}/api/health" 2>/dev/null); then
scripts/smoke_install.sh, line 45
page=$(curl -fsS "http://127.0.0.1:${port}/" 2>/dev/null) || {
docs/demo-en/assets/index-DyRw71Rw.js, line 1
var xm=Object.defineProperty;var gm=(e,n,s)=>n in e?xm(e,n,{enumerable:!0,configurable:!0,writable:!0,value:s}):e[n]=s;var Lc=(e,n,s)=>gm(e,typeof n!="symbol"?n+"":n,s);(function()
Show more
docs/demo-en/assets/index-DyRw71Rw.js, line 482
Reviewer can verify acceptance criteria`,"发单后自动绑定本会话为来源证据;任务详情里可推进执行、移交和交付回执。":"Dispatch links this session as source evidence. Use task details for execution, handoffs, and delive
docs/demo-en/assets/index-DyRw71Rw.js, line 483
`).map(H=>H.trim()).filter(Boolean);if(!o.some(H=>H.id===d)||!j.trim()||!_.trim()||!M.length){z(r("请选择执行者,并填写标题、委派要求和至少一条验收标准。"));return}if(h&&(h===d||!o.some(H=>H.id===h))){z(r("请
docs/demo/assets/index--qGG73dT.js, line 1
var xm=Object.defineProperty;var gm=(e,n,s)=>n in e?xm(e,n,{enumerable:!0,configurable:!0,writable:!0,value:s}):e[n]=s;var Lc=(e,n,s)=>gm(e,typeof n!="symbol"?n+"":n,s);(function()
docs/demo/assets/index--qGG73dT.js, line 482
Reviewer can verify acceptance criteria`,"发单后自动绑定本会话为来源证据;任务详情里可推进执行、移交和交付回执。":"Dispatch links this session as source evidence. Use task details for execution, handoffs, and delive
docs/demo/assets/index--qGG73dT.js, line 483
`).map(H=>H.trim()).filter(Boolean);if(!o.some(H=>H.id===d)||!j.trim()||!_.trim()||!M.length){z(r("请选择执行者,并填写标题、委派要求和至少一条验收标准。"));return}if(h&&(h===d||!o.some(H=>H.id===h))){z(r("请
tools/skill_dispatch.py, line 153
open_fn = opener or urllib.request.urlopen
webui/src/api.ts, line 31
const response = await fetch("api/_index.json");
Secrets
Concern
reads a credential or environment file.
SECRETS_ENV_READ SECRETS_PATH_CREDENTIAL SECRETS_PATH_DOTENV
core/cli/live.py, line 26
token_path = path or os.environ.get("RETINUE_TOKEN_FILE")
node/quota_probe.py, line 75
'claude': home / '.claude/.credentials.json',
scripts/export_community.py, line 93
any(p == '.env' or p.startswith('.env.') and not p.endswith('.example') for p in parts))
Agent instructions
Pass
No instruction to ignore earlier instructions or to hide a step.
Obfuscation
Concern
contains a minified payload.
OBFUSCATION_MINIFIED_PAYLOAD
core/panel.py, line 25
.card{display:block;color:inherit;text-decoration:none;background:#182238;border:1px solid #2b3855;border-radius:12px;padding:13px;margin-bottom:10px;box-shadow:0 8px 22px #0508125
core/panel.py, line 26
.overview{padding:12px 24px 44px;max-width:1180px}.overview-summary{display:flex;gap:14px;margin-bottom:18px}.stat{background:var(--panel);border:1px solid var(--line);border-radiu
core/panel.py, line 27
.thread{max-width:820px;margin:0 auto;padding:12px 24px 48px}.back{color:var(--accent);text-decoration:none}.thread-head{margin:24px 0 30px}.event{display:grid;grid-template-column
Show more
docs/demo/assets/index--qGG73dT.js, line 1
var xm=Object.defineProperty;var gm=(e,n,s)=>n in e?xm(e,n,{enumerable:!0,configurable:!0,writable:!0,value:s}):e[n]=s;var Lc=(e,n,s)=>gm(e,typeof n!="symbol"?n+"":n,s);(function()
docs/demo-en/assets/index-DyRw71Rw.js, line 1
var xm=Object.defineProperty;var gm=(e,n,s)=>n in e?xm(e,n,{enumerable:!0,configurable:!0,writable:!0,value:s}):e[n]=s;var Lc=(e,n,s)=>gm(e,typeof n!="symbol"?n+"":n,s);(function()
server/inbox.py, line 1
"""Attention inbox aggregation and daily digest (M0).
Licence
Pass
A licence file is present (LICENSE.md).
Maintainer activity
Pass
The latest commit is within the last 365 days.
Note
Hygiene check of commit 72aff265c4dd. can delete files. can reach a host that is not written as a fixed address. reads a credential or environment file. contains a minified payload.
Date and source
Date checked:
github.com
Commit graded: 72aff265c4dd4f01992f54298ca9bdaf5e04dafc
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.