Back to skill

Security audit

Multi-Council Decision Engine

Security checks for vulnerabilities and agentic risk

Overview

The skill appears to be a legitimate decision-analysis helper, but it sends business prompts to external AI models and writes local prompt/cost logs without enough disclosure or controls.

Install only if you are comfortable sending submitted prompts, campaign briefs, venture ideas, and context to OpenRouter and possible downstream model providers. Avoid pasting secrets, customer records, regulated data, or confidential strategy unless you have an approved data-handling path. Review or disable the local prompt and cost logs, and use a virtual environment with pinned dependencies instead of the suggested system pip command.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (2)

T09 · Insecure Skill Coding Practices

Warning
Location
business_mind_tree.py:99
Finding

Unredacted Sensitive Business Data Is Transmitted to an External AI Provider

Content
View full analysis
tuple: """Primary council backend. Uses OPENROUTER_API_KEY.""" try: from openai import OpenAI except ImportError: raise RuntimeError( "openai package not installed. " "Run: pip install openai --break-system-packages" ) api_key = os.environ.get("OPENROUTER_API_KEY") if not api_key: raise RuntimeError("OPENROUTER_API_KEY not set in environment") or_model = _to_or_model(model) client = OpenAI(api_key=api_key, base_url="https://openrouter.ai/api/v1") resp = client.chat.completions.create( model=or_model, max_tokens=max_tokens, messages=[ {"role": "system", "content": system}, {"role": "user", "content": user}, ], extra_headers={ "HTTP-Referer": os.environ.get("OPENROUTER_APP_URL", "https://github.com/openclaw"), "X-Title": os.environ.get("OPENROUTER_APP_NAME", "Multi-Council Decision Engine"), }, ) ``` The transmitted user value is assembled without filtering: ```python def _run_council(name: str, prompt: str, context: str = "") -> dict: """Generic council runner. Returns structured analysis dict.""" if name not in COUNCILS: return {"council": name, "ok": False, "error": f"unknown council: {name}"} cfg = COUNCILS[name] user = prompt.strip() if context.strip(): user += f"\n\nAdditional context:\n{context.strip()}" ``` ### Technical Analysis The Skill sends the complete caller-supplied prompt and optional context to OpenRouter over its chat-completions API. Gate functions can place venture pro ...[truncated 2726 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
business_mind_tree.py:100
Finding

Unsafe Recommendation to Install an Unpinned Dependency into the System Python Environment

Content
View full analysis
tuple: """Primary council backend. Uses OPENROUTER_API_KEY.""" try: from openai import OpenAI except ImportError: raise RuntimeError( "openai package not installed. " "Run: pip install openai --break-system-packages" ) ``` ### Technical Analysis When the `openai` module is unavailable, the Skill instructs the operator to install the latest package resolved under the unbounded name `openai`. The project does not include a lock file, a pinned version, or package hashes in the reviewed files. The command also uses `--break-system-packages`, which bypasses Python's externally managed environment safeguard. That safeguard exists to prevent pip from overwriting or conflicting with packages managed by the operating system. The package name is legitimate and there is no evidence that the Skill intentionally references a malicious or typosquatted package. The risk arises from mutable dependency resolution and the recommended installation context. A compromised package release, compromised transitive dependency, unexpected future version, or unsafe package-index configuration could execute installation or import-time code with the permissions of the operator running pip or the Skill. ### Attack Path 1. The Skill is invoked on a host where the `openai` module is not installed. 2. Importing `OpenAI` raises `ImportError`. 3. The displayed error directs the operator to run: `pip install openai --break-system-packages` 4. Pip resolves the current package and transitive dependencies without a project-controlled version lock or hashes. 5. If the selected package artifa ...[truncated 1287 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (12)

Tainted flow: 'req' from os.environ.get (line 219, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · business_mind_tree.py (reported line 223)May include surrounding context.

python
"https://openrouter.ai/api/v1/models",
            headers={"Authorization": f"Bearer {api_key}"},
        )
        with urllib.request.urlopen(req, timeout=10) as r:
            catalog = json.loads(r.read().decode())
        by_id = {m["id"]: m for m in catalog.get("data", [])}
        available = []

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The documented purpose says the skill provides an 8-council decision engine, but the analysis indicates additional undeclared councils, extra analysis actions, live external API/model-catalog access, and local file writes. This mismatch can mislead operators about the skill's real behavior, causing them to approve or run code with broader capabilities and side effects than expected.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill declares required environment variables and implies code execution, file writes, and network access, but does not declare an explicit tool/permission scope. That weakens user and platform visibility into what the skill can do and increases the chance of overbroad execution in hosts that rely on manifest scoping for safety decisions.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

User prompts and optional context are transmitted to external OpenRouter-hosted models, which can expose sensitive business or personal data to a third-party processor if users are unaware of the data flow. In this skill context, users are likely to submit strategic, competitive, operational, or compliance-sensitive information, making undisclosed external sharing materially risky.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The manifest describes a virtual board of 8 specialized reasoning frameworks: strategy, risk, market, operations, ethics, forecasting, execution, and AI-engineering. This file also defines CONTENT_PROMPT and SOCIAL_MEDIA_PROMPT and wires corresponding councils into COUNCILS, plus adds a competitive_differentiation_analysis function for local-business positioning, which expands the skill beyond the declared decision-engine scope.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The code logs a preview of the user's prompt to local files without explicit notice, which can persist confidential strategy, market, tax, or operational details on disk where other local users, backup systems, or support staff may later access them. Because this skill is designed for decision support on sensitive business matters, even truncated prompt logging can leak valuable or regulated information.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The public API docstring says run_campaign_gate runs a content council, and the implementation passes "content" in the councils list. However, the import block imports content_council but not a symbol named content, creating a mismatch between the documented available councils and what the imported module interface suggests.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The module persistently writes venture_key, gate type, timestamps, and cost data to a local JSON file even though the skill is described as a decision-evaluation/synthesis component. Persistent undeclared storage increases the data-retention and privacy surface, and if briefs or venture identifiers are sensitive this creates an audit artifact that operators may not expect or control.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

Campaign briefs, content text, and venture ideas are packaged into prompts and sent to external council functions without any visible disclosure, consent, or data-classification checks in this file. If these councils are backed by remote LLM/services, sensitive business plans, marketing copy, or regulated content may be transmitted off-box unexpectedly, creating confidentiality and compliance risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

For markdown files, this rule applies when the description omits warnings about behaviors that could affect user data, privacy, or system integrity. The setup instructs users to provide OPENROUTER_API_KEY, and later the document notes that usage is logged to cost_log.json, but there is no explicit user-facing warning that the skill will use external model services and create a local log file.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The manifest description focuses on independent reasoning frameworks producing a go/hold/kill verdict. However, the documented behavior also includes dynamic model selection across external models and logging costs to cost_log.json, which are extra operational behaviors not conveyed by the manifest description. These may be implementation details, but the file-writing side effect is substantive enough to merit disclosure.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

The top-level docstring lists the public actions 'registered via get_actions()' and presents a specific set, but the code later defines content_council and social_media_council and exposes content through COUNCILS/listing behavior without documenting it there. This is not just incomplete implementation detail because the documentation explicitly claims to enumerate the registered public actions.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.