T01 · Skill Instruction Hijacking
- Location
scripts/dual_agent_debate.py:239- Finding
Prompt Injection Through Untrusted Open Brain Content
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This skill has a coherent debate-and-memory purpose, but it reads and persists sensitive memory data with broad SQL access and sends memory content to OpenAI without enough scoping or user control.
Review this before installing if your Open Brain contains private, personal, business, or credential-like notes. Use a least-privileged MCP/SQL role, avoid setting OPENAI_API_KEY unless external processing of memory content is acceptable, and consider disabling or modifying persistence and runtime table creation before use.
scripts/dual_agent_debate.py:239Prompt Injection Through Untrusted Open Brain Content
scripts/dual_agent_debate.py:174Excessive Disclosure of Private Thoughts to OpenAI
The declared purpose understates the actual capabilities: the skill not only debates ideas but also retrieves broader context, executes SQL against thought and memory tables, and may perform schema modification. That mismatch is dangerous because users and policy engines may approve the skill for a narrower use case while it retains direct data-access and write/DDL behavior with materially higher risk.
The code can create public.memories at runtime if insertion fails, which grants the skill schema-modification behavior beyond a normal debate/writeback operation. Allowing a content-processing skill to create database objects increases blast radius, can bypass deployment review/change control, and may create or re-create storage surfaces for unauthorized persistence.
The skill declares no explicit tool scope even though its documented behavior requires environment access, network calls, and shell/script execution. In agent systems, missing scope declarations weaken least-privilege controls and can cause the skill to be invoked with broader capabilities than users or orchestrators expect.
The skill advertises that it writes debate outcomes back to memory storage but provides no user-facing warning that potentially sensitive prompts, thoughts, or derived conclusions will be persisted. This creates a privacy and data-governance risk because users may unknowingly cause personal or confidential information to be stored long term.
The behavior section explicitly says the skill retrieves prior thoughts and persists full outcomes to database tables, yet it does not warn about the privacy implications of accessing historical thought data and storing new records. Because the context is a memory/brain system, the data is likely to be especially sensitive, making silent retrieval and persistence more dangerous.
The skill silently falls back to invoking a separate local agent binary (openclaw agent) when no OpenAI API key is present, which expands the trust boundary and causes user/query/context data to be routed into an unrelated execution path. In a skill meant to run a defined debate flow, this hidden capability can expose sensitive data to another local component and produce behavior inconsistent with the manifest.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
def cli_agent_chat(messages: list[dict]) -> str:
prompt = "\n\n".join([f"{m.get('role','user').upper()}: {m.get('content','')}" for m in messages])
cmd = ["openclaw", "agent", "--json", "--agent", "main", "--thinking", "off", "--message", prompt]
out = subprocess.check_output(cmd, text=True, stderr=subprocess.STDOUT)
data = None
try:
data = json.loads(out)
The script sends the user's query, retrieved context, and debate content to external or semi-external services without any visible consent, warning, or minimization controls. Because retrieved thoughts may contain sensitive personal memory data, undisclosed transmission materially raises privacy and compliance risk in this skill context.
This code transmits conversation content to the OpenAI chat completions API, which is an external boundary crossing with possible exposure of sensitive query, context, and thought data. In this skill, the risk is elevated because the transmitted content may include prior memories retrieved from Open Brain, not just the current prompt.
for attempt in range(retries + 1):
try:
out = post_json("https://api.openai.com/v1/chat/completions", payload, headers=headers, timeout=90)
return out["choices"][0]["message"]["content"].strip()
except Exception:
if attempt < retries:
The embedding request sends user query and candidate thought text to an external embeddings endpoint, again exposing potentially sensitive Open Brain content to a third party. Because this occurs during semantic reranking, multiple memory items may be transmitted, increasing aggregate data exposure.
for attempt in range(retries + 1):
try:
out = post_json("https://api.openai.com/v1/embeddings", payload, headers=headers, timeout=90)
return out["data"][0]["embedding"]
except Exception:
if attempt < retries:
The skill stores debate outcomes and the user's query in a generic public.memories table rather than clearly updating a dedicated thought store as described. This creates a data-governance mismatch that can persist sensitive prompts and inferred conclusions in a broader or unintended namespace, increasing the chance of later disclosure or misuse.
The skill persists debate outcomes, including the user query and generated reasoning metadata, into a database without explicit confirmation or consent. In a memory-oriented system this is especially sensitive, because it can create durable records of user ideas, personal reflections, or inferred judgments that may later be surfaced unexpectedly.
The code accesses sensitive credentials from environment variables (OPENBRAIN_MCP_TOKEN and OPENAI_API_KEY) and uses them in Authorization headers. Although this is common practice, this file provides no user-facing notice, confirmation, or explanatory comment around the use of these credentials.
No suspicious patterns detected.