Back to skill

Security audit

WorkBuddy 项目续接

Security checks for vulnerabilities and agentic risk

Overview

The skill appears intended for encrypted workspace migration, but it handles sensitive project secrets and imported agent instructions with too little user control.

Install only if you are comfortable migrating an entire project workspace, including .env secrets and project-local agent instructions. Use strong passphrases, transfer .wbpack files like confidential credentials, and restore only packages from sources you trust after reviewing imported rules before continuing agent work.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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 (2)

T01 · Skill Instruction Hijacking

Warning
Location
references/agent-workflow.md:50
Finding
Restored Packages Can Inject Instructions into the Agent Workflow## Vulnerability Details **File Location**: `references/agent-workflow.md:50` **Vulnerability Type**: Untrusted instruction adoption **Risk Level**: Medium **Relevant Code / Instructions**: ```text 6. After restoration succeeds, first read the restored directory's .workbuddy-relay/HANDOFF.md, then read the project rules and key files. Explain the project goal, current phase, blockers, and next step, and continue the current task; do not automatically execute restored scripts, install dependencies, or switch the current WorkBuddy workspace. ``` Supporting implementation in `scripts/relay.py:595-599`: ```python def _prepare_restore_root(extracted: Path, destination: Path) -> None: payload = extracted / "payload" workspace = payload / "workspace" shutil.copytree(workspace, destination, symlinks=False) metadata = destination / METADATA_DIR metadata.mkdir(parents=True, exist_ok=True) for name in ("HANDOFF.md", "manifest.json", "runtime.json"): _copy_file(payload / name, metadata / name) ``` ### Technical Analysis A package author controls the restored `HANDOFF.md`, project rules, Agent configuration, and project-local Skills. The restoration checks establish archive safety and internal integrity, but they do not authenticate the package author or determine whether textual content contains adversarial Agent instructions. The workflow directs the Agent to read the package-controlled handoff and project rules and then continue the task. It does not explicitly classify these files as untrusted data, prevent them from overriding the current task, or require user approval before acting on newly imported instructions. Cryptographic age encryption does not eliminate this trust-boundary issue. An attacker can create a structurally valid package, choose its password, and provide both to a victim. SHA-256 checks only prove that restored files match the package manifest create ...[truncated 1521 chars]
Remediation
## Remediation Suggestions 1. Explicitly classify all restored handoff files, project rules, Agent configurations, and Skills as untrusted content. 2. Require the Agent to summarize imported instructions for the user and obtain approval before adopting new goals or invoking tools. 3. State that restored content cannot override system or developer instructions, expand workspace authorization, request secrets, or authorize access outside the restored project. 4. Separate descriptive handoff data from executable Agent instructions by using a constrained, schema-validated metadata format. 5. Disable restored project-local Skills and persistent Agent rules by default until the user explicitly enables them. 6. Consider adding package signatures tied to trusted identities. Encryption with a shared passphrase provides confidentiality and integrity but does not establish the package author's identity. 7. Continue enforcing the existing prohibition against automatically running restored scripts or installing dependencies.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/relay.py:477
Finding
Unbounded Archive Processing Allows Resource-Exhaustion Attacks## Vulnerability Details **File Location**: `scripts/relay.py:477-500` **Vulnerability Type**: Unbounded archive extraction **Risk Level**: Medium **Complete Vulnerable Code Segment**: ```python def _extract_archive(tar_path: Path, destination: Path) -> None: seen: set[str] = set() with tarfile.open(tar_path, mode="r:gz") as archive: members = archive.getmembers() if not members: raise RelayError("migration package archive is empty") for member in members: safe_name = _validate_archive_name(member.name) if member.name in seen: raise RelayError("migration package contains duplicate paths") seen.add(member.name) if not (member.isdir() or member.isreg()): raise RelayError("migration package contains a link or special file") target = destination.joinpath(*safe_name.parts) if not _is_within(target, destination): raise RelayError("migration package escapes the extraction directory") if member.isdir(): target.mkdir(parents=True, exist_ok=True) continue target.parent.mkdir(parents=True, exist_ok=True) source = archive.extractfile(member) if source is None: raise RelayError("migration package contains an unreadable file") with source, target.open("wb") as output: shutil.copyfileobj(source, output, length=CHUNK_SIZE) try: os.chmod(target, stat.S_IMODE(member.mode)) except OSError: pass ``` Validation occurs only after extraction in `scripts/relay.py:741-745`: ```python extracted = staging_parent / "extracted" extracted.mkdir() _extract_archive(decrypted, extracted) manifest, _, project_name = _validate_manifest(extracted) target = _unique_restore_t ...[truncated 2119 chars]
Remediation
## Remediation Suggestions 1. Define conservative configurable limits for encrypted size, decrypted archive size, archive member count, per-file size, cumulative extracted bytes, path length, and directory depth. 2. Reject oversized input packages before invoking age. 3. Process tar members incrementally rather than calling `getmembers()` for the entire archive. 4. Track the actual number of bytes copied from every member and abort immediately when per-file or cumulative limits are exceeded. 5. Validate each member's declared size before opening its output file, while also enforcing limits against actual streamed bytes. 6. Check available temporary-disk capacity and reserve a safety margin before extraction. 7. Add an extraction deadline or watchdog in addition to the existing age-operation timeout. 8. Apply strict size limits to `manifest.json`, `runtime.json`, and `HANDOFF.md` before parsing or reading them fully. 9. Clean up the temporary directory on every limit violation, retaining the existing fail-before-publication behavior. 10. Add tests for gzip bombs, oversized sparse-looking members, excessive member counts, deeply nested paths, and disk-capacity failures.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (8)

Lp3

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding
The skill describes behavior that relies on file read, file write, and shell-capable operations, but it does not declare an explicit tool scope or permissions boundary. This can lead to overbroad execution in hosts that default to permissive tool access, increasing the risk of unintended filesystem access or command execution during packaging and restore flows.

Natural-Language Policy Violations

Medium
Confidence
85% confidence
Finding
Natural-language policy violations include forcing a specific language or locale without user opt-in. The skill metadata, overview, and sample requests are entirely in Chinese, and the file does not indicate that the skill supports other languages or that Chinese is a justified region-specific requirement.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill states that project .env files are included by default in the encrypted package, which can silently capture API keys, database passwords, and other secrets. Even if encrypted, this increases secret exposure risk through weak passphrases, accidental transfer to the wrong device, insecure storage, or later decryption on a compromised host.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
def _git_branch(workspace: Path) -> str | None:
    try:
        result = subprocess.run(
            ["git", "-C", os.fspath(workspace), "branch", "--show-current"],
            check=False,
            capture_output=True,
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
import pty

    master, slave = pty.openpty()
    process = subprocess.Popen(
        command,
        stdin=slave,
        stdout=slave,
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
del password
    creation_flags = getattr(subprocess, "CREATE_NEW_CONSOLE", 0)
    try:
        result = subprocess.run(
            command,
            check=False,
            creationflags=creation_flags,
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
In restore mode, if the destination root is empty, the code moves restored children directly into that directory with `os.replace`, which will overwrite any conflicting paths that appear between the emptiness check and the final move. Because this skill is specifically designed to import a packaged workspace onto another machine, unintended overwrites can destroy local files or project state in a realistic workflow.

Natural-Language Policy Violations

Low
Confidence
96% confidence
Finding
The Tkinter prompt hard-codes Chinese text such as '设置迁移密码', '输入迁移密码', '密码', '再次输入', and '继续'. This imposes a specific language on users without opt-in or locale selection, which matches the policy category for language or locale constraints.

Static analysis

No suspicious patterns detected.