Back to skill

Security audit

fotor-skills

Security checks for vulnerabilities and agentic risk

Overview

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.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (4)

T03 · Remote Payload Retrieval and Execution

Error
Location
SKILL.md:68
Finding

Unverified Remote Installer Scripts Are Executed Directly

Content
View full analysis
Remediation
View remediation

T08 · Insecure Dependencies

Error
Location
scripts/ensure_sdk.py:16
Finding

Unpinned Fotor SDK Is Automatically Upgraded Before Every Task

Content
View full analysis
None: subprocess.check_call( ["uv", "pip", "install", "--python", sys.executable, "-q", *args], stdout=sys.stderr, stderr=sys.stderr, ) ``` ```python def main() -> None: print("Installing or upgrading fotor-sdk with uv from PyPI...", file=sys.stderr) _uv_pip_install("--upgrade", "fotor-sdk") print(json.dumps({"status": "upgraded", "version": _sdk_version()})) ``` The Skill makes this installation mandatory: ```markdown 4. Run `./.venv/bin/python scripts/ensure_sdk.py` before every task to install or upgrade the latest `fotor-sdk` with `uv`. 5. After `.venv` is ready and `ensure_sdk.py` completes, silently run `./.venv/bin/python scripts/check_skill_update.py --mark-notified --check-interval-hours 24`. ``` ### Technical Analysis The command installs the latest available release of `fotor-sdk` from PyPI using the unbounded requirement `fotor-sdk`. There is no exact version constraint, lock file, hash verification, or reviewed release boundary. Because the installation is performed with `--upgrade` before every task, the code that ultimately runs can change between invocations even when the Skill itself has not changed. A compromised maintainer account, malicious upstream release, or package-distribution incident could therefore introduce arbitrary code into ordinary Skill execution. The subprocess call uses an argument array and does not use `shell=True`, so command injection through this call was not identified. The issue is the mutable, automatically upgraded dependency rather than shell command construction. ### Attack Path 1. An attacker compromises the upstream package publisher or distribution p ...[truncated 1119 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/upload_image.py:45
Finding

API Credentials and Task Data Can Be Redirected to an Arbitrary Endpoint

Content
View full analysis
dict: query = parse.urlencode({"type": upload_type, "suffix": suffix}) req = request.Request( f"{endpoint.rstrip('/')}/v1/upload/sign?{query}", headers={ "Authorization": f"Bearer {api_key}", "User-Agent": "curl/8.5.0", }, method="GET", ) with request.urlopen(req) as resp: payload = json.loads(resp.read().decode("utf-8")) ``` The destination is configurable without scheme or hostname validation: ```python parser.add_argument( "--endpoint", default=os.environ.get("FOTOR_OPENAPI_ENDPOINT", DEFAULT_ENDPOINT), help=f"Fotor API endpoint (default: {DEFAULT_ENDPOINT})", ) ``` ```python ticket = request_upload_ticket( endpoint=args.endpoint, api_key=api_key, upload_type=upload_type, suffix=suffix, ) ``` The task runner similarly passes an unrestricted environment-controlled endpoint to the SDK: ```python api_key = os.environ.get("FOTOR_OPENAPI_KEY", "") if not api_key: print(json.dumps({"error": "FOTOR_OPENAPI_KEY not set"}), file=sys.stderr) return 1 client = FotorClient( api_key=api_key, endpoint=os.environ.get("FOTOR_OPENAPI_ENDPOINT", "https://api-b.fotor.com"), poll_interval=args.poll_interval, max_poll_seconds=args.timeout, ) ``` ### Technical Analysis The normal default destination is the expected Fotor endpoint, `https://api-b.fotor.com`. However, `FOTOR_OPENAPI_ENDPOINT` and the `--endpoint` argument can replace it with an ...[truncated 2105 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/upload_image.py:128
Finding

Signed Upload URL Is Exposed in Normal Script Output

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (23)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

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.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

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.

Content

No source excerpt is available for this finding.

Chaining Abuse

High
Category
Tool Misuse
Confidence
98% confidence
Finding

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.

Content

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

bash
# 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"

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- For `skills-github`, reads local `SKILL.md` frontmatter top-level `version` field, falls back to legacy `metadata.version`, finds the GitHub source, and fetch

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- For `skills-github`, reads local `SKILL.md` frontmatter top-level `version` field, falls back to legacy `metadata.version`, finds the GitHub source, and fetch

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- For `skills-github`, reads local `SKILL.md` frontmatter top-level `version` field, falls back to legacy `metadata.version`, finds the GitHub source, and fetch

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

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.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
80% confidence
Finding

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.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
80% confidence
Finding

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.

Content

Scanner excerpt · references/get_api_key.md (reported line 63)May include surrounding context.

md
- 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`

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

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.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
90% confidence
Finding

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.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
89% confidence
Finding

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.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
84% confidence
Finding

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.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
84% confidence
Finding

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.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

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.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

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.

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

python
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("{")

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/check_skill_update.py (reported line 211)May include surrounding context.

python
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 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/ensure_sdk.py (reported line 17)May include surrounding context.

python
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 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/ensure_sdk.py (reported line 25)May include surrounding context.

python
def _sdk_version() -> str:
    return subprocess.check_output(
        [sys.executable, "-c", "import fotor_sdk; print(fotor_sdk.__version__)"],
        text=True,
    ).strip()

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

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.

Content

No source excerpt is available for this finding.

External Script Fetching

Low
Category
Supply Chain
Confidence
96% confidence
Finding

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.

Content

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

bash
# 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"

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

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.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.