Back to skill

Security audit

weclone-init-twin

Security checks for vulnerabilities and agentic risk

Overview

This skill creates local persona-template files for a digital twin and does not show hidden execution, exfiltration, or persistence beyond those files.

Install only if you want local digital-twin persona files. Keep the generated ai_twin files private, leave sensitive fields blank unless truly needed, avoid --force unless you mean to replace existing files, and do not run the initializer against directories writable by untrusted users.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/init_twin_profile.py:86
Finding
Symbolic-Link Following Allows Out-of-Directory File Overwrite## Vulnerability Details **File Location**: `scripts/init_twin_profile.py:86-90, 100-128` **Vulnerability Type**: Symbolic-link following and time-of-check/time-of-use file-write weakness **Risk Level**: Medium ### Vulnerable Code ```python def validate_targets(output_dir: Path, force: bool) -> None: conflicts = [] for name in TEMPLATE_NAMES: target = output_dir / name if target.exists() and not force: conflicts.append(str(target)) if conflicts: joined = "\n".join(f"- {item}" for item in conflicts) raise FileExistsError( "Refusing to overwrite existing files without --force:\n" f"{joined}" ) def main() -> int: args = parse_args() out_dir = Path(args.output_dir).expanduser().resolve() source_dir = template_dir() # ... out_dir.mkdir(parents=True, exist_ok=True) try: validate_targets(out_dir, args.force) except FileExistsError as exc: print(f"[ERROR] {exc}", file=sys.stderr) return 1 for name in TEMPLATE_NAMES: source = template_path(source_dir, name, language) if not source.is_file(): print(f"[ERROR] Missing template: {source}", file=sys.stderr) return 1 target = out_dir / name target.write_text(render_template(source, args.user_name), encoding="utf-8") print(f"[OK] Wrote {target}") ``` ### Technical Analysis The initializer checks target paths with `Path.exists()` and later writes them using `Path.write_text()`. It does not reject symbolic links or open destination files with no-follow semantics. `Path.write_text()` follows a destination symbolic link. When `--force` is enabled, validation permits any existing destination, including a symbolic link. A dangling symbolic link can also bypass the non-force check because `Path.exists()` normally returns false when the link's destination does not exist. The validation and write are separate filesystem ...[truncated 1488 chars]
Remediation
## Remediation Suggestions 1. Reject every destination that is a symbolic link, including dangling links. Use `lstat()` or equivalent link-aware checks rather than relying only on `exists()`. 2. Open destination files atomically with no-follow semantics. On supported platforms, use `os.open()` with `O_NOFOLLOW` and appropriate creation flags, then write through the returned file descriptor. 3. When creating new files, use exclusive creation such as `O_CREAT | O_EXCL` to prevent an existing entry from being followed or replaced silently. 4. For approved overwrites, securely open the existing destination without following links and verify through `fstat()` that it is a regular file. 5. Keep validation and opening atomic. Do not depend on a path check followed by a separate path-based write, because an attacker can alter the directory entry between those operations. 6. Consider restricting output directories to an approved repository subtree unless arbitrary output locations are required. If arbitrary destinations remain supported, clearly document that the directory must not be writable by untrusted users. 7. Add automated tests covering existing symlinks, dangling symlinks, non-regular files, `--force` behavior, and destination replacement during initialization.
Vulnerability Patterns
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (5)

Self-Modification

High
Category
Rogue Agent
Content
2. Scaffold the persona pack.
   Run `python3 skills/weclone-init-twin/scripts/init_twin_profile.py --user-name <name> --language <en|zh> [output_dir]`.
3. Regenerate only with explicit overwrite approval.
   Add `--force` only when the user clearly wants to replace existing files.
4. Hand off to reply generation.
   Tell the user to fill the generated markdown templates before using `$weclone-twin-reply`.
Confidence
85% confidence
Finding
Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Self-Modification

High
Category
Rogue Agent
Content
if conflicts:
        joined = "\n".join(f"- {item}" for item in conflicts)
        raise FileExistsError(
            "Refusing to overwrite existing files without --force:\n"
            f"{joined}"
        )
Confidence
85% confidence
Finding
Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill performs filesystem-affecting actions by scaffolding and potentially overwriting persona files, but it does not declare any explicit tool scope or permissions boundary. That omission weakens least-privilege controls and makes it harder for a runtime or reviewer to constrain the skill to only the intended directory and operations.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The template explicitly solicits personal and potentially sensitive attributes such as gender, age, city/time zone, relationship status context, and personality profiling without any accompanying privacy notice, minimization guidance, or consent checkpoint. In a digital-twin/persona skill, this creates a concrete risk of unnecessary collection and persistence of personal data that could enable profiling, re-identification, or misuse if the persona pack is shared, synced, or later consumed by other tools.

Natural-Language Policy Violations

Low
Confidence
93% confidence
Finding
This markdown file presents all instructions and examples only in Chinese, which can amount to a language/locale policy violation when no user opt-in or justification is provided. The file does not indicate that the skill is region-specific or that users may choose another language.

Static analysis

No suspicious patterns detected.