T09 · Insecure Skill Coding Practices
- Location
poetry_hub_entrypoint.py:8- Finding
All CLI Commands Unexpectedly Launch an Infinite Mutating Agent
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This skill is for a collaborative poetry hub, but its command wrapper and agent loop can unexpectedly run forever, post to the shared service, and reset shared posts even for commands that look read-only.
Review before installing. Use only in a disposable or classroom Poetry Hub where unexpected posting and reset are acceptable. Do not rely on the state, feed, or register commands as read-only or bounded until the entrypoint dispatch is fixed and reset is gated by explicit user or server authorization.
poetry_hub_entrypoint.py:8All CLI Commands Unexpectedly Launch an Infinite Mutating Agent
poetry_hub_agent.py:48Shared Hub Reset Occurs Without Authorization or First-Line Ownership Verification
The declared description presents a simple interaction/observation skill, but the body instructs autonomous polling, posting, persona selection, and use of a destructive control/reset endpoint. This mismatch is dangerous because users or orchestrators may invoke the skill expecting passive participation while it can act continuously and modify shared state without explicit, informed consent.
The manifest describes participation, orchestration, and observation, but the code includes a destructive hub reset operation that is not disclosed. This mismatch is dangerous because users or systems may grant the skill broader trust than warranted, leading to unexpected deletion or interruption of shared hub activity.
The skill exposes a remote control endpoint that resets the shared Poetry Hub, which is a destructive capability not necessary for ordinary participation or observation. Because the main loop invokes this reset automatically after posting FINAL, it can erase or disrupt other agents' shared state and be abused for denial-of-service against the collaborative game.
The reset operation is destructive and is performed without any warning, confirmation, or safety check. In this context, that makes accidental or repeated remote deletion of shared session state very likely, especially since the main loop can trigger it automatically.
The skill specifies networked behavior and the static analysis indicates shell/code capabilities, but it does not declare any tool scope or permission boundaries. That increases the chance an agent runtime grants broader capabilities than necessary, enabling unintended outbound requests or local command execution beyond the stated poetry-hub use case.
The specification repeatedly frames the game as English-only, including requiring "one line of English poetry." This imposes a language constraint without any opt-in, alternative language support, or justification such as a region-specific compliance requirement.
The skill documents a reset control action that clears shared posts, but it does not provide a clear warning that this is destructive to shared hub data. In a multi-agent collaborative service, an automatic reset can disrupt other participants, erase context, and be abused for denial-of-service or sabotage of the shared activity.
The skill allows use of externally supplied LLM_API_URL and LLM_API_KEY and suggests sending content to a custom LLM service, but it does not warn users that prompts, generated text, or possibly sensitive hub data may be transmitted to a third party. This creates data exfiltration and secret-handling risk, especially if agents forward conversation context or operational metadata to an untrusted endpoint.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
def register_agent():
url = f"{BASE_URL}/agents/register"
data = {"name": NAME, "profile": PROFILE}
r = requests.post(url, json=data, timeout=10)
r.raise_for_status()
return r.json()
The post_line function transmits caller-supplied text to an external service without any disclosure, validation, or consent mechanism. In a skill context, this can cause users to unknowingly send sensitive or inappropriate content to a third-party endpoint, creating privacy and data handling risks.
This POST sends text content to an external service, which is core functionality, but it becomes security-relevant because the text parameter may originate from user input and there is no visible disclosure or boundary around data sharing. In a collaborative hub context this is expected behavior, but it still creates privacy and exfiltration risk if users are unaware.
def post_line(text):
url = f"{BASE_URL}/posts"
payload = {"agent_name": NAME, "text": text}
r = requests.post(url, json=payload, timeout=10)
r.raise_for_status()
return r.json()
The inline comment suggests reset should be conditional, but the implementation resets the hub unconditionally after posting FINAL. This discrepancy increases operational risk because reviewers may underestimate the behavior, while actual execution consistently disrupts the shared service state.
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
feed = get_feed()
# Simple loop: if fewer than 4 lines, post a line; otherwise post feedback or reset via hub if first line
poem_lines = [p for p in feed.get("posts", []) if p.get("agent_name")==NAME] # simplistic
if len(poem_lines) < 4:
line = f"A line from {NAME} in the voice of {NAME.split('-')[0]}" # placeholder, replace with real generation
post_line(line)
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
cmd = sys.argv[1]
if cmd == "register":
# Run the existing agent's register path
subprocess.run([sys.executable, "poetry_hub_agent.py", "register"], check=True)
elif cmd == "run":
subprocess.run([sys.executable, "poetry_hub_agent.py"], check=True)
else:
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
# Run the existing agent's register path
subprocess.run([sys.executable, "poetry_hub_agent.py", "register"], check=True)
elif cmd == "run":
subprocess.run([sys.executable, "poetry_hub_agent.py"], check=True)
else:
# Fallback to delegating to the Python script for other commands if implemented
subprocess.run([sys.executable, "poetry_hub_agent.py", cmd], check=True)
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
subprocess.run([sys.executable, "poetry_hub_agent.py"], check=True)
else:
# Fallback to delegating to the Python script for other commands if implemented
subprocess.run([sys.executable, "poetry_hub_agent.py", cmd], check=True)
if __name__ == "__main__":
main()
The manifest advertises a collaborative poetry skill but does not disclose that it can call /control/reset, a destructive administrative action that can wipe or restart shared hub state. Hidden destructive capability increases the chance that users or orchestrators invoke the skill without understanding that it can disrupt other participants or destroy session continuity.
The manifest grants broad ability to perform network actions against an external service, including registration, posting, state inspection, and reset, without describing when those actions are allowed or what user intent should trigger them. Lack of trigger scope or activation constraints makes unintended external side effects more likely, especially in an autonomous agent setting where the skill could be invoked too broadly.
An administrative reset endpoint is exposed even though the stated purpose is collaboration and observation, which do not inherently require destructive control over the service. This mismatch broadens the skill's privilege surface and can enable denial of service or sabotage of the poetry game if the endpoint is triggered accidentally or abusively.
The file references a specific external service name, but it does not contain any explicit language or locale enforcement instructions. Because SQP-3 is limited to natural-language policy violations such as forcing a language or locale, this is at most a weak signal and likely not a true violation.