T09 · Insecure Skill Coding Practices
- Location
scripts/human_review.py:59- Finding
Caller-Controlled Approval Flag Bypasses Mandatory Human Review
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This skill is presented as a human approval safety gate, but its artifacts show broken approval controls plus unrelated persistent self-learning behavior that users should review carefully before installing.
Install only after reviewing the approval model. As written, this should not be relied on as a real human-approval enforcement layer for destructive, financial, deployment, privacy, or privileged actions. The learner should be disabled or removed unless you explicitly want local preference/history storage and have controls for retention, path containment, and human review of any SKILL.md changes.
scripts/human_review.py:59Caller-Controlled Approval Flag Bypasses Mandatory Human Review
scripts/human_review.py:96Reviewer Identity Can Be Spoofed and CLI Review State Is Discarded Between Commands
scripts/learner.py:71Untrusted Learning Data Can Persistently Influence Future Agent Instructions
scripts/learner.py:27Unrestricted Skill Directory and Symlink Following Permit Unsafe File Overwrite
This is a significant description-behavior mismatch: the skill claims to provide human approval gating for risky actions, but the documented added functionality is a generic learning system that stores history and preferences instead of enforcing review controls. That mismatch is dangerous because users may rely on the skill as a safety barrier when it does not actually implement the promised protections, creating a false sense of security around high-risk actions.
The instruction to write learned experience back into SKILL.md introduces self-modifying behavior unrelated to human approval routing. Self-modifying skill definitions can silently change future behavior, weaken auditability, and bypass normal code review expectations, which is especially risky in a component marketed as a safety control.
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
用法:
python human_review.py --selftest
python human_review.py --add '{"action":"delete /data","proposed_by":"agent-7"}'
python human_review.py --pending
python human_review.py --approve <id> --reviewer alice --note "确认可删"
python human_review.py --reject <id> --reviewer bob --note "先备份"
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
q = ReviewQueue()
# 1) 危险动作需审核
assert needs_review("rm -rf /data") is True
print("[1] 危险动作 needs_review=True ✓")
# 2) 已授权不需审核
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
q = ReviewQueue()
# 1) 危险动作需审核
assert needs_review("rm -rf /data") is True
print("[1] 危险动作 needs_review=True ✓")
# 2) 已授权不需审核
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
q = ReviewQueue()
# 1) 危险动作需审核
assert needs_review("rm -rf /data") is True
print("[1] 危险动作 needs_review=True ✓")
# 2) 已授权不需审核
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
print("[1] 危险动作 needs_review=True ✓")
# 2) 已授权不需审核
assert needs_review("delete /tmp/x", {"user_approved": True}) is False
print("[2] 已授权 needs_review=False ✓")
# 3) 入队 + 待审计数
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
print("[2] 已授权 needs_review=False ✓")
# 3) 入队 + 待审计数
rid = q.add("delete /var/log/app", proposed_by="agent-7")
assert rid in q.items
assert len(q.pending()) == 1
print("[3] 入队 + 待审计数=1 ✓")
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
print("[2] 已授权 needs_review=False ✓")
# 3) 入队 + 待审计数
rid = q.add("delete /var/log/app", proposed_by="agent-7")
assert rid in q.items
assert len(q.pending()) == 1
print("[3] 入队 + 待审计数=1 ✓")
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
print("[4] 审核通过 ✓")
# 5) 驳回 + 理由
rid2 = q.add("git push --force origin main", proposed_by="agent-3")
r2 = q.reject(rid2, "bob", "先走 PR 评审")
assert r2["status"] == "rejected" and "PR" in r2["decision_note"]
print("[5] 审核驳回 + 理由 ✓")
The manifest describes a skill whose purpose is to route risky actions into a human review queue with approve/reject/pending/summary workflows and audit records. This file instead documents and implements usage logging, preference storage, insights, and self-reflection for arbitrary skills, with no review queue, no approval decisioning, and no blocking of privileged or irreversible actions.
The skill documents executable scripts that write local state (learned_patterns.json) and potentially modify SKILL.md, but it does not declare any explicit tool scope or permissions. In an agent ecosystem, undeclared write capability weakens review and containment, because operators may trust the stated review-only purpose while the skill can persist data or alter files.
The trigger list contains broad phrases such as '操作确认' and 'agent 审核' that may match ordinary conversation and invoke the skill unintentionally. Accidental invocation is more concerning here because the skill also documents persistence and adaptive behavior, so spurious activations could create unnecessary state changes or data retention.
The documentation expands a review-gating skill into a generic self-learning system that accumulates experience and preferences across runs. This broadens the data collection and persistence surface beyond the skill's stated purpose, increasing privacy, integrity, and governance risk without clear justification.
Persisting user preferences and operational history is not necessary for a human-review queue and introduces avoidable collection of potentially sensitive metadata. In this context, the skill is expected to gate risky actions, so retaining broader user-behavior state makes the mismatch more dangerous because operators may not anticipate this storage.
The skill description presents a review-queue control but does not prominently warn that the documented learning module stores usage history and user preferences locally. This omission undermines informed consent and can expose sensitive behavioral data, especially since a safety-related skill would not ordinarily be expected to keep such memory.
The natural-language instructions explicitly tell the system to retain user preferences and usage-derived information for future automatic reuse. This creates persistent profiling behavior that is unrelated to the core review-gating function and can lead to privacy leakage, unexpected personalization, or unsafe reuse of stale assumptions.
The documented interface says --add accepts structured JSON with fields like action and proposed_by, but the implementation stores the raw string as the action and ignores the JSON structure. This mismatch can cause callers to believe metadata was captured for audit and authorization decisions when it was not, weakening traceability and potentially misclassifying or mishandling risky actions.
The CLI creates a brand-new in-memory ReviewQueue on every invocation, so review items are never persisted across add/pending/approve/reject operations. In a human-in-the-loop approval skill, this breaks the core security control: agents can appear to submit actions for review, but there is no durable queue or audit trail, making approvals unverifiable and enabling accidental or intentional bypass of oversight.
The natural-language interface text, usage instructions, and output strings are all Chinese-only. This effectively forces a specific language without user opt-in, which matches the language/locale policy violation criteria.
Functions such as record_op, record_preference, get_insights, and self_reflect collect behavioral statistics and user preferences and generate optimization suggestions for arbitrary skills. That generic learning capability is outside the stated scope of a human-in-the-loop approval layer, whose purpose is risk routing, human confirmation, and audit of sensitive actions.
The script persistently stores arbitrary user preferences and free-form notes in learned_patterns.json with no consent prompt, minimization, retention control, or warning about potentially sensitive content. In the context of an agent skill ecosystem, notes and preferences can easily contain secrets, personal data, or operational context, creating a local privacy leak and long-lived sensitive artifact.
No suspicious patterns detected.