Back to skill

Security audit

SWF Game Port Decompiler

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly coherent for SWF decompilation, but its helper script can overwrite or truncate arbitrary writable output files without a no-overwrite safeguard.

Install only if you are comfortable reviewing command arguments before running it. Use a fresh output directory, do not point dump output at an existing file, and avoid using the source SWF or important project files as output paths until the helper adds no-clobber and same-file safeguards.

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/ffdec_game_decompile.py:108
Finding

Arbitrary File Truncation Through Unrestricted Dump Output Path

Content
View full analysis

Vulnerability Details

File Location: scripts/ffdec_game_decompile.py:108-120 and scripts/ffdec_game_decompile.py:231-235
Vulnerability Type: Unrestricted file overwrite and truncation
Risk Level: Medium

Vulnerable Code

python
def run(cmd: list[str], dry_run: bool = False, stdout_path: Path | None = None) -> int:
    printable = " ".join(f'"{c}"' if " " in str(c) else str(c) for c in cmd)
    print(printable)
    if dry_run:
        return 0
    if stdout_path:
        stdout_path.parent.mkdir(parents=True, exist_ok=True)
        with stdout_path.open("w", encoding="utf-8", errors="replace") as fh:
            proc = subprocess.run(cmd, stdout=fh, stderr=subprocess.STDOUT, text=True)
        return proc.returncode
    proc = subprocess.run(cmd)
    return proc.returncode

The affected dump call site passes a user-controlled path directly to this function:

python
def dump_command(args) -> int:
    ffdec = str(find_ffdec(args.ffdec))
    swf = str(Path(args.swf).resolve())
    out = str(Path(args.output).resolve())
    return run([ffdec, "-dumpSWF", swf], args.dry_run, Path(out))

Technical Analysis

The positional output argument is fully controlled by the caller. Although it is converted to an absolute path, no validation ensures that it differs from the source SWF, points to an intended workspace, or does not identify an existing sensitive file.

The run() function opens this path using Python's "w" mode before FFDec is started. This mode creates a missing file or immediately truncates an existing file to zero bytes. Consequently, successful FFDec processing is not required for data loss to occur.

This behavior also conflicts with the safety guarantee in SKILL.md that the original SWF will never be overwritten. Path resolution alone does not enforce that guarantee. There is no no-clobber policy, source/output identity check, confirmation prompt, or ...[truncated 1590 chars]

Remediation
View remediation

Remediation Suggestions

  1. Reject identical source and output files before opening the destination. Resolve both paths and use Path.samefile() when both exist, with a normalized-path comparison as a fallback:

    python
    swf_path = Path(args.swf).resolve()
    output_path = Path(args.output).resolve()
    
    if output_path == swf_path:
        raise ValueError("The output path must not be the source SWF.")
    
    if output_path.exists() and swf_path.exists() and output_path.samefile(swf_path):
        raise ValueError("The output path identifies the source SWF.")
    
  2. Refuse to overwrite existing output files by default. Add an explicit --force option if replacement is required, and clearly warn that it permits destructive behavior.

  3. For no-clobber creation, use exclusive creation mode ("x") rather than "w" when the destination must not already exist.

  4. Capture FFDec output in a temporary file located in the destination directory. Only after FFDec exits successfully should the application atomically rename the temporary file to the requested destination.

  5. Remove the temporary file after subprocess failure and leave any existing destination untouched.

  6. Apply equivalent safeguards to predictable files generated by the full workflow. Require a new or empty output directory unless an explicit overwrite option is provided.

  7. Add automated tests covering:

    • Source and output paths that are textually identical.
    • Different paths that resolve to the same file through symbolic links.
    • Existing output files without --force.
    • FFDec failure without modification of an existing destination.
    • Successful atomic replacement when overwrite is explicitly authorized.
Vulnerability Patterns
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • 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)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 33)May include surrounding context.

md
- `python scripts/ffdec_game_decompile.py full game.swf out/game-decompile`

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
86% confidence
Finding

The skill instructs the agent to use Python, shell commands, environment/path discovery, and file writes, but it does not declare any explicit tool restrictions such as allowed-tools or permissions. That creates an authorization gap where an agent may execute filesystem and shell operations more broadly than intended, increasing the risk of unintended command execution, access to sensitive files, or overwriting user data if the skill is invoked in a permissive runtime.

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/ffdec_game_decompile.py (reported line 106)May include surrounding context.

python
if stdout_path:
        stdout_path.parent.mkdir(parents=True, exist_ok=True)
        with stdout_path.open("w", encoding="utf-8", errors="replace") as fh:
            proc = subprocess.run(cmd, stdout=fh, stderr=subprocess.STDOUT, text=True)
        return proc.returncode
    proc = subprocess.run(cmd)
    return proc.returncode

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/ffdec_game_decompile.py (reported line 108)May include surrounding context.

python
with stdout_path.open("w", encoding="utf-8", errors="replace") as fh:
            proc = subprocess.run(cmd, stdout=fh, stderr=subprocess.STDOUT, text=True)
        return proc.returncode
    proc = subprocess.run(cmd)
    return proc.returncode

Static analysis

No suspicious patterns detected.