other
- Location
blog-manager-kit.py:52- Finding
Undisclosed Transmission of User Data to a Hard-Coded External Server
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This blog-management skill is mostly purpose-aligned, but it silently falls back to an undisclosed hard-coded HTTP server while supporting uploads, passwords, and destructive API actions.
Install only if you trust the publisher and will configure BLOG_MANAGER_KIT_BASE_URL to a trusted HTTPS or local endpoint before use. Avoid sending passwords, personal data, or local files through the default configuration, and require explicit review before delete, hard-delete, upload, or Issue/PR comment actions.
blog-manager-kit.py:52Undisclosed Transmission of User Data to a Hard-Coded External Server
SKILL.md:426Forced Final-Response and Task-Termination Instructions
blog-manager-kit.py:52Sensitive Information Can Be Sent over Plaintext HTTP
requirements.txt:1Dependency Version Is Not Reproducibly Pinned
The skill explicitly exposes a destructive DELETE flow where a boolean-like query parameter (soft=false) switches a normal delete into an irreversible hard delete, and it also documents bypassing confirmation with --yes. In an unauthenticated public API context, a mistaken or manipulated parameter selection could permanently destroy content with no recovery path, making the context substantially more dangerous.
1. **API 路径拼写 `lables`。** API 实际路径为 `/api/lables`(原文拼写错误),子命令用正确拼写 `labels`(list-labels / create-label),脚本内部请求时用 `lables`。详见 api-reference.md。
2. **硬删除不可逆。** `hard-delete-article` 永久删除文章且无法 restore 恢复。子命令默认二次确认(输入 `yes`),自动化场景用 `--yes` 跳过。软删除用 `delete-article`(可 `restore-article` 恢复)。
3. **DELETE 软/硬删除同一端点。** `DELETE /api/articles/{id}` 通过 query 参数 `soft` 区分:`soft=true`(默认,软删除)/ `soft=false`(硬删除)。本 skill 拆为两个子命令避免误操作。
4. **文件上传字段名不同。** 单文件上传字段 `file`(`files={'file': f}`),批量上传字段 `files`(`files=[('files', f)...]`)。批量上传不能用 dict value 为列表(requests 会报 unpack 错误),必须用元组列表。
5. **响应结构包裹在 `code`/`data`。** 列表/详情返回 `{"code":200,"data":[...]}`,不是直接返回数组。解析时取 `data` 字段。
6. **分页参数。** `list-articles` 用 `page`(从 1 开始)/`size`(最大 100),不是 offset/limit。`lid=0` 表示不按标签过滤。
Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.
# 1. 项目知识优先
creds.update(_load_from_project_knowledge())
# 2. 环境变量回退:项目知识缺失的字段从环境变量补充
for k, v in os.environ.items():
u = k.upper()
if u.startswith(_CRED_PREFIX):
if 'BASE_URL' in u:
The skill reads local files and sends their contents to a remote API via the requests files parameter. Because the skill is explicitly unauthenticated and uses a default remote HTTP endpoint, this creates a real exfiltration path for local data if a user is induced to upload sensitive files.
if method == 'GET':
resp = requests.get(url, params=params, timeout=30, **auth_kwargs)
elif method == 'POST':
resp = requests.post(url, json=payload, files=files, timeout=30, **auth_kwargs)
elif method == 'PUT':
resp = requests.put(url, json=payload, files=files, timeout=30, **auth_kwargs)
elif method == 'PATCH':
File contents flow to a network sink. This may indicate data exfiltration of sensitive files.
elif method == 'POST':
resp = requests.post(url, json=payload, files=files, timeout=30, **auth_kwargs)
elif method == 'PUT':
resp = requests.put(url, json=payload, files=files, timeout=30, **auth_kwargs)
elif method == 'PATCH':
resp = requests.patch(url, json=payload, timeout=30, **auth_kwargs)
elif method == 'DELETE':
This command directly exposes a destructive delete operation that can be driven by user-supplied parameters against a public unauthenticated API. In agent settings, such parameterized destructive actions are susceptible to misuse through prompt injection, operator error, or automated invocation without adequate safeguards.
def cmd_delete_article(args):
"""能力 F:删除文章(软删除,可恢复)。"""
# DELETE /api/articles/{article_id}?soft=true
return _api_request('DELETE', f'/api/articles/{args.article_id}',
params={'soft': True})
Hard delete permanently removes content and is therefore a clear high-risk destructive capability. Although the function includes a confirmation prompt, it can be bypassed with --yes, so the skill still exposes dangerous parameterized deletion to agents and automation against an unauthenticated API.
def cmd_hard_delete_article(args):
"""能力 G:硬删除文章(不可逆,需二次确认)。"""
# DELETE /api/articles/{article_id}?soft=false
if not args.yes:
print("⚠️ 警告:硬删除不可逆,文章将被永久删除且无法恢复!", file=sys.stderr)
print(f" 目标文章 ID:{args.article_id}", file=sys.stderr)
Deleting comments by ID is a destructive parameterized action with no built-in verification or confirmation. Because the backend is unauthenticated, the skill meaningfully lowers the barrier to misuse or accidental moderation actions.
def cmd_delete_comment(args):
"""能力 P:删除评论(软删除)。"""
# DELETE /api/comments/{comment_id}
return _api_request('DELETE', f'/api/comments/{args.comment_id}')
Deleting messages by ID is another destructive action that the skill exposes directly to callers. In the context of a public unauthenticated API, this presents a real misuse risk rather than a purely theoretical one.
def cmd_delete_message(args):
"""能力 T:删除留言(软删除)。"""
# DELETE /api/messages/{message_id}
return _api_request('DELETE', f'/api/messages/{args.message_id}')
Deleting moods by ID is a direct state-changing action that can be abused or triggered accidentally. The lack of authentication and limited safeguards in the skill make this materially risky in an agent environment.
def cmd_delete_mood(args):
"""能力 W:删除说说。"""
# DELETE /api/moods/{mood_id}
return _api_request('DELETE', f'/api/moods/{args.mood_id}')
Deleting uploaded files by arbitrary filename exposes a high-risk destructive capability over a public unauthenticated API. Depending on server-side handling, this could lead to remote file loss and may be especially sensitive if filenames are guessable or map to broader storage objects.
def cmd_delete_upload(args):
"""能力 AA:删除已上传文件。"""
# DELETE /api/uploads/{filename}
return _api_request('DELETE', f'/api/uploads/{args.filename}')
The skill declares powerful capabilities (environment access, local file reads, and network access) but does not constrain them with an explicit allowlist or permissions block. In practice, this leaves the agent free to combine local configuration discovery with outbound requests in ways users may not expect, increasing the risk of unintended data exposure or scope creep.
The manifest trigger list includes generic terms such as "blog" and "article", which are common words in everyday conversation and could cause the skill to activate outside a clearly intended command context. The file does not provide exclusion conditions, negative examples, or a narrower invocation scope to limit unintended matches.
The skill introduces Issue/PR commenting behavior even though its declared purpose is managing a blog REST API. This creates an additional side effect in a different trust domain (repository collaboration) and could let normal blog-management requests trigger unsolicited comments or leak operational details into a repo.
The output specification mandates posting Issue comments after operations, which adds repository-side effects outside the stated blog API management scope. This broadens what the skill can do from remote API management to modifying collaboration artifacts, creating opportunities for unintended writes and information leakage.
The task completion instructions require Issue comment reporting regardless of operation outcome, again extending the skill beyond its declared REST API role. Because this behavior is framed as mandatory, it increases the chance that unrelated user requests cause writes to repository resources without clear consent.
The skill documents and exposes unauthenticated destructive and file-upload operations, including hard delete, delete-upload, and content creation endpoints, while explicitly stating there is no authentication. In the context of a blog-management skill, this enables any caller who can reach the configured base URL to modify or destroy content and potentially abuse upload functionality, making the lack of warnings secondary to the more serious unsafe capability exposure.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
if method == 'GET':
resp = requests.get(url, params=params, timeout=30, **auth_kwargs)
elif method == 'POST':
resp = requests.post(url, json=payload, files=files, timeout=30, **auth_kwargs)
elif method == 'PUT':
resp = requests.put(url, json=payload, files=files, timeout=30, **auth_kwargs)
elif method == 'PATCH':
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
elif method == 'POST':
resp = requests.post(url, json=payload, files=files, timeout=30, **auth_kwargs)
elif method == 'PUT':
resp = requests.put(url, json=payload, files=files, timeout=30, **auth_kwargs)
elif method == 'PATCH':
resp = requests.patch(url, json=payload, timeout=30, **auth_kwargs)
elif method == 'DELETE':
The soft-delete article command performs a destructive state-changing action immediately with no user-facing confirmation. In an agent/tooling context, this increases the chance of accidental or prompt-induced destructive actions against a public unauthenticated API.
Comment deletion is executed immediately without any warning or confirmation. Since the API is described as public and unauthenticated, even low-friction deletions are more dangerous because there is no compensating access-control check in the skill.
Message deletion is a destructive operation with no confirmation prompt or user disclosure. In an agent environment, this makes accidental or manipulated deletion easier, especially when the backend is unauthenticated.
Mood deletion is performed without a warning or consent checkpoint. The lack of friction is risky because it enables accidental destructive requests to a public management API.
The single-file upload command transmits a local file over the network without runtime disclosure or confirmation. This is especially dangerous here because the skill targets an unauthenticated remote service and defaults to plain HTTP, so sensitive local data could be sent unintentionally or intercepted.
Batch upload can send multiple local files off-host with no runtime disclosure or confirmation. Because multiple files may be involved, the blast radius is larger than the single-file case, particularly with an unauthenticated HTTP endpoint.
Uploaded-file deletion occurs without any warning or confirmation. This can cause unintended remote data loss, and the public unauthenticated API context increases the operational risk.
No suspicious patterns detected.