T03 · Remote Payload Retrieval and Execution
- Location
SKILL.md:68- Finding
Unverified Remote Installer Scripts Are Executed Directly
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill matches its Fotor media purpose, but its setup and runtime give it more changeable code and credential-routing authority than users should accept without review.
Install only after reviewing the setup path. Use a dedicated Fotor API key, avoid custom endpoints unless you fully trust them, treat uploaded media and prompts as sent to Fotor, keep command logs private because they may contain signed URLs, and prefer pinned/verified installs over the provided latest-version installer and upgrade commands.
SKILL.md:68Unverified Remote Installer Scripts Are Executed Directly
scripts/ensure_sdk.py:16Unpinned Fotor SDK Is Automatically Upgraded Before Every Task
scripts/upload_image.py:45API Credentials and Task Data Can Be Redirected to an Arbitrary Endpoint
scripts/upload_image.py:128Signed Upload URL Is Exposed in Normal Script Output
The skill claims to provide Fotor media generation/editing, but its workflow also installs Python, creates environments, and upgrades packages from PyPI before tasks. Automatic environment and package management introduces supply-chain and code-execution risk beyond the advertised functionality, especially when done by default.
The skill claims to provide Fotor media generation/editing, but its workflow also installs Python, creates environments, and upgrades packages from PyPI before tasks. Automatic environment and package management introduces supply-chain and code-execution risk beyond the advertised functionality, especially when done by default.
The curl ... | sh and PowerShell iex patterns are classic command-chaining risks because they combine retrieval and execution without inspection or verification. This removes any meaningful trust boundary and enables full command execution if the fetched content is malicious or altered.
# macOS / Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# Windows (PowerShell)
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
Referenced artifact was not completely inspected
- For `skills-github`, reads local `SKILL.md` frontmatter top-level `version` field, falls back to legacy `metadata.version`, finds the GitHub source, and fetch
Referenced artifact was not completely inspected
- For `skills-github`, reads local `SKILL.md` frontmatter top-level `version` field, falls back to legacy `metadata.version`, finds the GitHub source, and fetch
Referenced artifact was not completely inspected
- For `skills-github`, reads local `SKILL.md` frontmatter top-level `version` field, falls back to legacy `metadata.version`, finds the GitHub source, and fetch
The skill clearly performs privileged actions including shell execution, network access, environment variable use, and local file reads/writes, yet it declares no explicit tool scope or permissions boundary. This weakens policy enforcement and reviewability because consumers cannot easily tell what capabilities the skill may exercise before installation or execution.
Referencing an MCP/server launcher via npx skills without a pinned version allows execution of whatever package version is current at runtime. If the upstream package is compromised or a breaking/malicious release is published, users may run unreviewed code during installation or operation.
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.
- Use this guide when the user asks for an API key or needs the official `fotor-skills` homepage during setup
- When this guide is used, include both the homepage and the API-key dashboard entry
- Use `install-or-upgrade.md` when the user asks how to install or upgrade the skill
- Keep secrets out of chat and never ask the user to commit `.env`
This section explicitly supports portrait modification capabilities such as changing facial expressions, age progression/regression, and virtual try-on, but provides no safety constraints, consent requirements, or disclosure expectations. In an image-generation/editing skill, that omission can enable deceptive edits, non-consensual manipulation of people’s likenesses, or privacy-invasive transformations, especially when combined with realistic editing models.
The installation command uses npx skills add ... -y without pinning the skills package to a specific version. npx resolves the latest available package at execution time, which creates a supply-chain risk: a compromised, typosquatted, or unexpectedly changed upstream package could execute arbitrary code during install. In this context, the file is explicitly instructing users how to install and upgrade the skill, which increases practical exploitability because users are likely to copy-paste the command verbatim.
The upgrade instruction npx skills update invokes an unpinned npx package, so the actual code fetched and executed can vary over time. That makes the upgrade path susceptible to upstream compromise or unexpected breaking behavior, and upgrade commands are especially sensitive because they are likely to be run repeatedly by existing users who trust the workflow.
This line repeats the recommendation to use npx skills update, again referencing an unpinned executable source. Although this occurrence is only example text rather than a code block, it still normalizes and propagates the insecure command, which can lead users to run untrusted latest-version code.
This reminder text again instructs use of npx skills update without version pinning. Even in narrative guidance, repeating an unpinned remote execution pattern contributes to supply-chain exposure because users often copy exact commands from documentation snippets and reminder text.
The documentation explicitly encourages passing user-supplied image_url/image_urls values and arbitrary **extra fields into outbound API payloads, but it does not warn that these inputs will be transmitted to a third-party service. In a skill centered on image/video generation, this creates a real privacy and data-handling risk because users may provide sensitive media URLs, signed URLs, internal links, or metadata-bearing extra fields without informed consent or validation guidance.
The manifest describes a Fotor media-generation/editing skill for images and videos, but this script executes the external clawhub command to inspect package metadata. Spawning subprocesses is a packaging/maintenance capability rather than an obvious requirement of photo/video generation itself, making it context-inappropriate relative to the stated skill purpose.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
def check_clawhub_latest(slug: str, timeout: float) -> tuple[str, str | None]:
cmd = ["clawhub", "inspect", slug, "--json"]
proc = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout)
if proc.returncode != 0:
raise RuntimeError((proc.stderr or proc.stdout or "clawhub inspect failed").strip())
start = proc.stdout.find("{")
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
def github_repo_default_branch(source: str, timeout: float) -> str:
data = http_get_json(f"https://api.github.com/repos/{source}", timeout=timeout)
return data.get("default_branch") or "main"
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
def _uv_pip_install(*args: str) -> None:
subprocess.check_call(
["uv", "pip", "install", "--python", sys.executable, "-q", *args],
stdout=sys.stderr,
stderr=sys.stderr,
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
def _sdk_version() -> str:
return subprocess.check_output(
[sys.executable, "-c", "import fotor_sdk; print(fotor_sdk.__version__)"],
text=True,
).strip()
This code reads a local file and sends its bytes to a remote upload URL, and also requests an upload ticket from the API. While the script name and module docstring indicate uploading is its purpose, there is no explicit warning in the user-facing CLI help or runtime output that local file contents and authorization-backed metadata will be transmitted over the network.
The skill instructs users to fetch and execute a remote installer script directly from the network. This is dangerous because any compromise of the remote host, transport, or script contents results in immediate arbitrary code execution on the local machine.
# macOS / Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# Windows (PowerShell)
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
The instructions direct the skill to silently perform a networked update check and only notify the user conditionally, meaning background outbound requests occur without clear disclosure. While not inherently malicious, this undermines transparency and can leak metadata about installed versions or usage context.
No suspicious patterns detected.