Back to skill

Security audit

Cognitive Topology

Security checks for vulnerabilities and agentic risk

Overview

This skill mostly matches its branching-and-synthesis purpose, but it can automatically persist task and branch content into long-term memory and can read arbitrary branch file paths from topology JSON without containment.

Install only if you are comfortable with this skill creating branch files, spawning branch-style workflows, and retaining task summaries in OpenClaw memory. Avoid using it with secrets or sensitive private data unless archival is disabled or reviewed, and require path validation so topology files cannot reference arbitrary local files.

Vulnerability Patterns
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/ct_integrate.py:13
Finding

Arbitrary Local File Read Through Attacker-Controlled Topology Paths

Content
View full analysis

Vulnerability Details

File Location: scripts/ct_integrate.py:13-45; scripts/ct_archive.py:130-148
Vulnerability Type: Path traversal and unrestricted local file read
Risk Level: High

Vulnerable Code

scripts/ct_integrate.py:13-45:

python
def main():
    topo_file = sys.argv[1] if len(sys.argv) > 1 else "/root/.openclaw/workspace/cognitive-topology/topology_latest.json"
    
    if not os.path.exists(topo_file):
        print(f"❌ 拓扑文件不存在: {topo_file}")
        sys.exit(1)
    
    with open(topo_file, 'r', encoding='utf-8') as f:
        topo = json.load(f)
    
    print(f"📊 整合拓扑: {topo['id']}")
    print(f"📝 主任务: {topo['task']}")
    print()
    
    all_l2 = []
    done_count = 0
    for branch in topo.get("branches", []):
        l2_file = branch.get("l2_file")
        status = branch.get("status", "unknown")
        
        # 优先读JSON中的status,其次读文件内容
        if status != "done" and l2_file and os.path.exists(l2_file):
            with open(l2_file, 'r', encoding='utf-8') as f:
                content = f.read()
            if "*(待填写)*" not in content:
                status = "done"
        
        icon = '✅' if status == 'done' else '⏳'
        print(f"{icon} {branch['id']} [{status}]")
        
        if status == 'done' and l2_file and os.path.exists(l2_file):
            with open(l2_file, 'r', encoding='utf-8') as f:
                content = f.read()
            all_l2.append({"branch_id": branch["id"], "content": content})

scripts/ct_archive.py:130-148:

python
    if not os.path.exists(topo_file):
        print(f"❌ 拓扑文件不存在: {topo_file}")
        sys.exit(1)
    
    with open(topo_file, 'r', encoding='utf-8') as f:
        topo = json.load(f)
    
    print(f"📦 归档拓扑: {topo['id']}")
    print(f"📝 任务: {topo['task']}")
    print()
    
    branch_summaries = []
    all_tags = set()
    
    for
...[truncated 3222 chars]
Remediation
View remediation

Remediation Suggestions

  1. Canonicalize every branch path with pathlib.Path.resolve(strict=True).
  2. Require the resolved path to be a regular file located beneath the canonical BRANCH_DIR.
  3. Reject absolute paths supplied by topology documents; preferably store only branch identifiers or basenames and construct the full path internally.
  4. Reject symbolic links or open files using platform protections such as O_NOFOLLOW where available.
  5. Enforce an allowlisted filename pattern, such as ct-[0-9]+-[0-9]{2}_L2.md.
  6. Validate topology documents against a strict schema before processing them.
  7. Apply size limits before reading files to prevent resource exhaustion.
  8. Run the scripts under a dedicated, least-privileged account that cannot read credentials or unrelated system files.
  9. Avoid automatically placing raw branch contents into agent-consumed synthesis or memory files.

Example containment check:

python
from pathlib import Path

branch_root = Path(BRANCH_DIR).resolve()
candidate = Path(l2_file).resolve(strict=True)

if candidate.parent != branch_root:
    raise ValueError("Branch file is outside the permitted directory")
if candidate.is_symlink() or not candidate.is_file():
    raise ValueError("Invalid branch file")

T02 · Agent Memory Poisoning

Error
Location
scripts/ct_archive.py:51
Finding

Automatic Persistent-Memory Poisoning With Untrusted Task and Branch Content

Content
View full analysis

Vulnerability Details

File Location: scripts/ct_integrate.py:75-84; scripts/ct_archive.py:51-82, 124, 134-156
Vulnerability Type: Persistent agent-memory poisoning
Risk Level: High

Vulnerable Code

scripts/ct_integrate.py:75-84:

python
    # 自动归档到长期记忆
    import subprocess
    try:
        result = subprocess.run(
            ['python3', '/root/.openclaw/workspace/skills/cognitive-topology/scripts/ct_archive.py', topo_file],
            capture_output=True, text=True, timeout=30
        )
        if result.returncode == 0:
            print(result.stdout)
        else:
            print(f"⚠️ 归档提示: {result.stderr}")

scripts/ct_archive.py:51-82:

python
def archive_to_memory(topo, branch_summaries, all_tags):
    """追加到 MEMORY.md"""
    topo_id = topo['id']
    task = topo['task']
    created = datetime.fromisoformat(topo['created']).strftime('%Y-%m-%d %H:%M')
    branch_count = len(topo['branches'])
    
    entry = f"""

## 认知拓扑归档 | {datetime.now().strftime('%Y-%m-%d')}

### 拓扑 {topo_id}
- **任务**: {task}
- **分支数**: {branch_count}
- **完成时间**: {created}
- **分支结论**:
{chr(10).join([s[0] for s in branch_summaries])}
"""
    
    # 追加到 MEMORY.md
    with open(MEMORY_FILE, 'r', encoding='utf-8') as f:
        content = f.read()
    
    # 找到最后一个 ## 标题 的位置,在其前插入
    # 或者追加到文件末尾
    with open(MEMORY_FILE, 'a', encoding='utf-8') as f:
        f.write(entry)
    
    return entry

scripts/ct_archive.py:134-156:

python
    with open(topo_file, 'r', encoding='utf-8') as f:
        topo = json.load(f)
    
    print(f"📦 归档拓扑: {topo['id']}")
    print(f"📝 任务: {topo['task']}")
    print()
    
    branch_summaries = []
    all_tags = set()
    
    for branch in topo.get('branches', []):
        l2_file = branch.get('l2_file')
        if l2_file and os.path.exists(l2_file):
            with open(l2_fi
...[truncated 3375 chars]
Remediation
View remediation

Remediation Suggestions

  1. Disable automatic archival during integration by default.
  2. Require explicit, informed user approval before modifying long-term memory.
  3. Treat all topology and branch content as untrusted data, not as agent instructions.
  4. Store generated records in a separate data archive that is not automatically loaded into the agent's instruction context.
  5. Attach provenance metadata, including source branch, author or session, timestamp, and trust level.
  6. Render archived text as escaped or fenced quoted data so headings and instruction-like content cannot be interpreted as trusted memory directives.
  7. Validate and normalize topology identifiers, task fields, tags, and conclusions.
  8. Add an allowlist-based extraction stage that stores concise factual summaries rather than arbitrary source text.
  9. Require review before promoting branch output from an untrusted archive into trusted long-term memory.
  10. Provide rollback, deduplication, and audit logging for every memory mutation.
  11. Update the Skill documentation to disclose persistent-memory writes and define their trust model.
  12. Ensure agents loading the archive receive a higher-priority instruction stating that archived records are untrusted historical data and must never override current system or user instructions.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (18)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

声明描述的是一个“认知拓扑引擎”编排器:负责复杂任务分叉、并行执行、追踪分支并最终整合结果。实际代码并不进行任务分解、分支创建、并行调度或主会话汇总,而是在已有拓扑结果基础上做离线归档:读取 topology 文件和各分支 L2 文件,抽取结论摘要与标签,并追加到长期记忆文件和每日快照。这不是对声明功能的实现细节,而是一个不同阶段、不同目的的工具。虽然它处理‘拓扑’和‘分支结论’,与整体系统主题相关,但其主要用途与声明的核心能力明显不一致,因此应判定为描述与行为不匹配。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The declared description presents a broader engine responsible for decomposing tasks into branches, using sessions_spawn for parallel execution, tracking branches, and integrating outputs. The supplied code chunk does not perform decomposition, branch spawning, or parallel execution at all. Its primary function is limited to integrating already-produced L2 branch files into a synthesis document. Additionally, it invokes ct_archive.py to automatically archive results, which is an undeclared capability. While synthesis is part of the declared workflow, the actual code is only one downstream component and does not accurately represent the full declared behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

声明描述的是一个完整的认知拓扑/分支执行引擎,重点在于自动拆解复杂任务、创建并行分支并汇总结果。但实际代码 ct_status.py 只是一个只读状态检查工具:它访问固定路径下的 topology JSON、分支文件和 synthesis 文件,输出当前分支完成情况。虽然它与“认知拓扑”领域相关,属于配套工具,但其主要用途与声明的核心功能明显不一致。代码没有创建分支、没有调用 sessions_spawn、没有执行子任务、没有写入 L2 结果、也没有进行整合,因此描述不能准确代表该代码块的实际行为。

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill instructs use of shell commands and file reads/writes but declares no explicit tool scope or permission boundaries. That creates an authorization ambiguity where an agent may invoke broader capabilities than reviewers or policy expect, increasing the risk of unintended filesystem access or command execution.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The activation criteria are broad enough to trigger on many ordinary analysis requests, causing the skill to auto-engage file and shell-based workflow more often than users may intend. In agent systems, over-broad autonomous activation increases the chance of unnecessary branching, unintended data propagation across task artifacts, and surprising tool use.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The language says the skill should automatically enable whenever any one of several common conditions is met, but does not define limits, approval gates, or safe defaults. Given the skill's use of sessions spawning concepts and workspace file aggregation, ambiguous auto-activation makes unintended execution and persistence more likely in benign user conversations.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The script persists topo['task'] and extracted branch conclusions into a long-term memory file automatically, with no consent gate, dry-run mode, or visibility controls. Because these fields originate from task and branch content, this can silently retain sensitive user prompts, secrets, or untrusted text in a durable location beyond the immediate session.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The script creates and appends daily snapshot files automatically, again persisting task text and branch summaries without explicit disclosure at write time. This increases the retention surface by duplicating potentially sensitive content into date-based archives, making unintended disclosure or later misuse more likely.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The module docstring and all CLI usage/error/status messages are written only in Chinese, which imposes a specific language on users with no opt-in or alternative locale support. Under the policy, forcing a specific language without user choice is a natural-language policy violation unless the locale restriction is clearly justified, which it is not here.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This code includes user-facing docstrings and console messages in Chinese only, such as the description and usage text. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale restriction is explicitly justified, which is not present here.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The module docstring claims the script only integrates branch L2 files and generates synthesis, but the implementation also triggers archival. This mismatch hides a data-handling side effect from users and reviewers, increasing the chance that sensitive information is persisted unexpectedly in a trusted automation flow.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The script's stated role is to integrate branch outputs into a synthesis, but it also automatically archives data to long-term memory. In an agent setting, this creates an undisclosed persistence channel for potentially sensitive task content, which can violate least surprise and lead to retention of user data without explicit consent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The archival action runs automatically after synthesis generation with no visible confirmation or up-front warning in the script behavior. In this skill context, branch outputs may contain intermediate reasoning, user prompts, or sensitive task data, so automatic persistence materially increases privacy and governance risk.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

Running an archival subprocess adds a secondary capability unrelated to the narrow integration task, violating separation of responsibilities. In agent skills, extra hidden capabilities increase attack surface and make it easier for benign-looking workflows to exfiltrate or retain information beyond user expectations.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/ct_integrate.py (reported line 78)May include surrounding context.

python
# 自动归档到长期记忆
    import subprocess
    try:
        result = subprocess.run(
            ['python3', '/root/.openclaw/workspace/skills/cognitive-topology/scripts/ct_archive.py', topo_file],
            capture_output=True, text=True, timeout=30
        )

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script's docstring and all user-facing status messages are hard-coded in Chinese, with no option to select another language or indication that the skill is intended only for a Chinese-speaking context. This creates a natural-language policy issue because it imposes a specific locale on all users without opt-in.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
97% confidence
Finding

The module docstring and user-facing console output are written exclusively in Chinese, which imposes a specific language on users without any visible opt-in or fallback. Under the language/locale policy, this is a natural-language constraint that should either be user-selectable or explicitly justified as region-specific.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
93% confidence
Finding

The file's natural-language interface text, including the description and usage instructions, is entirely in Chinese, which imposes a specific language on users without opt-in or explanation. Under the policy, locale or language restrictions should either provide a choice or be clearly justified as region-specific.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.