Back to skill

Security audit

Text Directory Archiver

Security checks for vulnerabilities and agentic risk

Overview

This directory archiving skill is coherent, but its unpack script can write files or create symlinks outside the chosen output folder when given a crafted archive.

Review before installing. Use this only with archives you trust, unpack into a disposable empty directory, and avoid running it with elevated privileges until path traversal and symlink containment checks are added.

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

Error
Location
scripts/archive.py:53
Finding

Arbitrary Filesystem Write Through Path Traversal During Archive Extraction

Content
View full analysis

Vulnerability Details

File Location: scripts/archive.py, lines 53–67
Vulnerability Type: Unrestricted archive extraction path / arbitrary filesystem write
Risk Level: High

Vulnerable Code

python
def rebuild_directory(manifest, file_contents, base_dir="output"):
    for path, info in manifest["files"].items():
        full_path = os.path.join(base_dir, path)
        os.makedirs(os.path.dirname(full_path), exist_ok=True)
        ftype = info.get("type", "text")
        if ftype == "dir": os.makedirs(full_path, exist_ok=True)
        elif ftype == "symlink":
            target = info.get("target")
            if os.path.lexists(full_path): os.remove(full_path)
            try: os.symlink(target, full_path)
            except OSError as e:
                print(f"[警告] 无法创建软链接 {path} -> {target}: {e}")
                open(full_path, 'w').write(f"# symbolic link: {target}\n")
        else:
            with open(full_path, "wb") as f: f.write(file_contents.get(path, b""))
    print(f"目录结构已重建于: {os.path.abspath(base_dir)}")

Technical Analysis

The archive manifest fully controls path. The extraction routine passes this value directly to os.path.join(base_dir, path) without rejecting absolute paths, parent-directory components such as .., or platform-specific drive-qualified paths.

A relative path such as ../../target escapes the intended extraction directory after filesystem path resolution. An absolute archive path may cause os.path.join to discard base_dir entirely. The subsequent directory creation and file-writing operations therefore act on attacker-selected filesystem locations.

There is also a symlink-assisted variant. Because manifest entries are processed in their declared order, a crafted archive can first create a symbolic link inside the output tree that targets an external directory, then add a regular-file entry beneath that link. The later file operation follows the symbolic link and writes outside the ex ...[truncated 1839 chars]

Remediation
View remediation

Remediation Suggestions

  1. Reject archive paths that are absolute, drive-qualified, empty, or contain . or .. path components.
  2. Resolve the extraction root and every candidate destination to canonical absolute paths, then verify containment with os.path.commonpath before any filesystem operation.
  3. Account for platform-specific separators and Windows drive or UNC paths rather than validating only POSIX-style paths.
  4. Prevent writes through existing symbolic links. Validate every parent component or use descriptor-relative, no-follow filesystem operations where supported.
  5. Do not allow archive-created symlinks to influence later extraction. Extract regular files and directories into a controlled tree before handling symlinks, while still validating every destination.
  6. Validate symlink targets or represent links as inert placeholder files when archives are untrusted.
  7. Refuse duplicate and conflicting entries, such as a path declared as both a symlink and a parent directory.
  8. Perform all validation before creating any file or directory so that an invalid archive cannot leave a partially modified filesystem.
  9. Add regression tests covering ../ traversal, absolute paths, Windows drive paths, UNC paths, nested traversal, pre-existing symlink parents, and archive-created symlink traversal.

A containment check should follow this general pattern:

python
root = os.path.realpath(base_dir)
candidate = os.path.realpath(os.path.join(root, archive_path))

if os.path.commonpath([root, candidate]) != root:
    raise ValueError(f"Archive path escapes output directory: {archive_path}")

This check must be combined with explicit path-component validation and protections against symlink races; canonicalization alone is not sufficient in a concurrently modified directory.

Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • 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 (4)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill describes file packing and unpacking behavior and references a script that reads from and writes to the filesystem, but it does not declare any explicit tool scope or permissions. In an agent environment, undeclared file access increases the risk of over-broad execution, unexpected writes, or restoring attacker-controlled archives into sensitive paths if the skill is invoked without clear sandbox constraints.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This code file contains natural-language strings that force a specific language locale for usage instructions and operational messaging. Under the policy, language constraints should not be imposed without offering user choice or clearly documenting a justified locale-specific scope.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The unpack path will create symlinks directly from untrusted archive data without validating either the link path or the symlink target. An attacker can craft an archive that places links pointing outside the output directory or to sensitive filesystem locations, enabling confused-deputy behavior, overwrite chains, or later abuse by users and tools that traverse the restored tree.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
72% confidence
Finding

In addition to packaging regular files and directories, the code inspects symlinks and preserves their targets in the archive manifest. That is a broader capability than a straightforward plain-text project snapshot unless symlink handling is explicitly part of the skill's documented scope.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.