Back to skill

Security audit

PhotoPlus Album Downloader

Security checks for vulnerabilities and agentic risk

Overview

The skill is for downloading PhotoPlus albums, but it runs mutable third-party code and can install unpinned Python packages, so it needs review before use.

Review before installing. Only run this in a disposable or constrained environment, avoid --install-deps in a shared Python environment, and prefer a vetted local checkout pinned to the documented commit or another trusted commit. Confirm you have permission to download the album contents, especially for third-party albums.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T03 · Remote Payload Retrieval and Execution

Error
Location
scripts/download_photoplus_album.py:53
Finding

Mutable Remote Code Is Downloaded and Executed Without Integrity Verification

Content
View full analysis
Path: script = repo_dir / "live_album_downloader.py" if script.exists(): return script repo_dir.parent.mkdir(parents=True, exist_ok=True) if shutil.which("git"): try: run(["git", "clone", "--depth", "1", REPO_URL, str(repo_dir)]) return script except subprocess.CalledProcessError: pass repo_dir.mkdir(parents=True, exist_ok=True) print(f"+ download {RAW_SCRIPT_URL} -> {script}", flush=True) urllib.request.urlretrieve(RAW_SCRIPT_URL, script) return script ``` ```python script = ensure_upstream(args.repo_dir) if args.install_deps: install_dependencies(args.repo_dir) args.workdir.mkdir(parents=True, exist_ok=True) run(build_args(args, activity_id, script.resolve()), cwd=args.workdir) ``` ### Technical Analysis The wrapper dynamically retrieves an executable Python program from an external GitHub repository. The Git path performs a shallow clone of the current default branch, while the fallback downloads `live_album_downloader.py` directly from the mutable `main` branch. The downloaded program is subsequently executed using the current Python interpreter without verifying a commit identifier, cryptographic checksum, or digital signature. HTTPS protects transport integrity but does not prevent the upstream repository owner, a compromised maintainer account, or an attacker controlling the repository from changing the effective ...[truncated 1546 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Error
Location
scripts/download_photoplus_album.py:73
Finding

Unpinned and Remotely Controlled Dependencies Can Execute Supply-Chain Payloads

Content
View full analysis
None: requirements = repo_dir / "requirements.txt" if requirements.exists(): run([sys.executable, "-m", "pip", "install", "-r", str(requirements)]) else: run([sys.executable, "-m", "pip", "install", "requests", "tqdm", "piexif"]) ``` ### Technical Analysis When `--install-deps` is supplied, the wrapper installs dependencies either from a `requirements.txt` file found in the dynamically retrieved upstream repository or from three package names without pinned versions or cryptographic hashes. Because the upstream repository is not pinned or authenticated beyond ordinary HTTPS, its requirements file can be changed to reference arbitrary packages, direct URLs, local paths, or malicious versions. The fallback installation is also non-reproducible because `requests`, `tqdm`, and `piexif` are installed without exact versions or hashes. Python package installation can execute attacker-controlled build logic for source distributions and installs package code that will later be imported by the downloader. Consequently, dependency installation expands the remote-code execution channel beyond the downloader script itself. ### Attack Path 1. An attacker compromises the mutable upstream repository and alters `requirements.txt`, or compromises a future release in the dependency supply chain. 2. A user invokes the wrapper with `--install-deps`. 3. The wrapper passes the unverified requirements file to `pip`, or resolves unpinned package names to the versions currently served by the configured package index. 4. `pip` downloads and installs the attacker-controlled component. 5. Malicious build-time logic may execute during installation, or malicious package code executes when imported by the ...[truncated 621 chars]
Remediation
View remediation
` so unexpected artifacts are rejected. 3. Do not consume `requirements.txt` from a repository that was downloaded dynamically at runtime. 4. Restrict dependency sources to approved HTTPS package indexes and disallow unreviewed direct URLs, VCS references, and local paths. 5. Install packages into a dedicated virtual environment rather than the user's global or shared Python environment. 6. Pin and verify the upstream downloader before deriving any dependency information from it. 7. Prefer prebuilt, reviewed artifacts and run installation and execution with minimal operating-system privileges. ]]>
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (5)

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill’s stated purpose is downloading and inspecting PhotoPlus albums, but the implementation includes a generic bootstrap mechanism that fetches executable code and packages at runtime. In the skill context, this is especially dangerous because users would reasonably expect media download behavior, not code acquisition and execution from third parties, increasing the chance of silent compromise.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill instructs the agent to run shell commands, install Python dependencies, clone or reuse an upstream repository, and access remote PhotoPlus content, but it does not declare any explicit tool scope or permissions boundaries. This creates a confused-deputy risk where an agent may perform network and shell actions without clear authorization constraints, increasing the chance of unintended command execution, dependency installation, or data retrieval.

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

python
def run(cmd: list[str], cwd: Path | None = None) -> None:
    print("+ " + " ".join(cmd), flush=True)
    subprocess.run(cmd, cwd=cwd, check=True)


def ensure_upstream(repo_dir: Path) -> Path:

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

This wrapper automatically clones a GitHub repository or downloads a raw Python script from the internet, then executes it locally, and can also install dependencies with pip. That creates a remote code execution supply-chain pathway far beyond simple album downloading, because compromise of the upstream repo, branch, network path, or dependency set would result in arbitrary code running on the host.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

This markdown file documents behavior that writes image bytes to local directories and can also write JSON sidecars, captions, and GPS EXIF metadata. While the behavior is described functionally, it does not explicitly warn users that running the tool will modify the filesystem and may embed metadata into files, which is the kind of user-affecting behavior SQP-2 asks markdown descriptions to disclose.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.