Back to skill

Security audit

SaaS Video

Security checks for vulnerabilities and agentic risk

Overview

The skill appears to be a legitimate Pexo video-generation wrapper, but it handles API keys, external uploads, and persistent project data with weak scoping and disclosure.

Review before installing. Use it only for SaaS material you are allowed to send to Pexo, keep PEXO_BASE_URL set to https://pexo.ai, protect ~/.pexo/config with user-only permissions or use a safer secret store, and avoid uploading screenshots or files containing secrets unless approved.

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 (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/_common.sh:228
Finding

Unvalidated Network Destinations Can Receive API Credentials and User Media

Content
View full analysis
"$err_file") || curl_status=$? else http_code=$(curl -sS \ --connect-timeout "$_PEXO_CONNECT_TIMEOUT" \ --max-time "$_PEXO_REQUEST_TIMEOUT" \ -X "$method" \ -H "$(_pexo_auth_header)" \ -H "Content-Type: application/json" \ -D "$header_file" \ -o "$body_file" \ -w '%{http_code}' \ "$@" \ "${PEXO_BASE_URL}${path}" 2>"$err_file") || curl_status=$? fi ``` `scripts/pexo-doctor.sh:142-151`: ```bash if [[ -n "${PEXO_BASE_URL:-}" && -n "${PEXO_API_KEY:-}" ]]; then tmp_body=$(mktemp) tmp_err=$(mktemp) http_code=$(curl -sS \ --connect-timeout 10 \ -H "Authorization: Bearer $PEXO_API_KEY" \ -H "Content-Type: application/json" \ -o "$tmp_body" \ -w '%{http_code}' \ "${PEXO_BASE_URL}/api/biz/projects?page_size=1" 2>"$tmp_err" || echo "000") ``` `scripts/pexo-upload.sh:70-84`: ```bash # Phase 1: get upload credential cred=$(pexo_post "/api/biz/projects/${pid}/assets/upload-credential" \ "{\"file_name\":\"$filename\",\"file_size\":$filesize}") upload_url=$(echo "$cred ...[truncated 3382 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/_common.sh:7
Finding

API-Key Configuration Is Created Without Restrictive Permissions and Executed as Shell Code

Content
View full analysis
~/.pexo/config << 'EOF' PEXO_BASE_URL="https://pexo.ai" PEXO_API_KEY="sk-" EOF ``` ``` `scripts/_common.sh:7-8`: ```bash _PEXO_CONFIG="${PEXO_CONFIG:-$HOME/.pexo/config}" [[ -f "$_PEXO_CONFIG" ]] && source "$_PEXO_CONFIG" ``` `scripts/pexo-doctor.sh:73-76`: ```bash # 1. Config file if [[ -f "$config_path" ]]; then echo "$PASS Config file found: $config_path" source "$config_path" ``` ### Technical Analysis The setup procedure writes a long-lived API key to `~/.pexo/config` but does not set a restrictive umask or explicitly apply directory and file permissions. Actual permissions therefore depend on the user’s existing umask. In a permissive environment, other local users may be able to read the credential. Both the shared runtime and diagnostic script process the configuration with Bash’s `source` command. A sourced file is executable shell code, not a passive configuration format. Any command substitution, function definition, redirection, or arbitrary command placed in the file executes with the privileges of the user running the Pexo script. The `PEXO_CONFIG` environment variable also permits selection of another file. This is useful for legitimate customization, but no ownership, type, path, or permission checks are performed before that file is executed. ### Attack Path **Credential-disclosure path:** 1. The user follows the documented setup steps under a permissive umask. 2. `~/.pexo/config` is created with permissions that allow another local principal to read it. 3. That principal reads `PEXO_API_KEY`. 4. The principal uses the key against the Pexo API ...[truncated 1176 chars]
Remediation
View remediation
"$HOME/.pexo/config" <<'EOF' PEXO_BASE_URL="https://pexo.ai" PEXO_API_KEY="sk-" EOF chmod 600 "$HOME/.pexo/config" ``` 2. Before loading an existing configuration, verify: - It is a regular file rather than a symlink or special file. - It is owned by the current user. - It is not writable by group or others. - It is not readable by others when it contains an API key. 3. Do not use `source` for data-only configuration. Parse an explicit format such as JSON or a strict `KEY=VALUE` parser that only accepts known keys. 4. Reject unknown configuration fields, command substitutions, shell metacharacters, multiline values, and duplicate keys. 5. Validate custom paths supplied through `PEXO_CONFIG`, or remove that override if it is unnecessary. 6. Prefer an operating-system credential store or secret manager over a plaintext file where practical. 7. Update `pexo-doctor.sh` to report unsafe ownership or permissions without executing the configuration first. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (28)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description says the skill creates SaaS demo/explainer videos end-to-end from an app description, URL, or screenshot. The actual code does not generate scripts, visuals, narration, captions, or any video output. Its sole purpose is asset retrieval and download for an existing project asset. This is a materially different primary function and exposes undeclared capabilities involving API asset access and local file download/storage. Therefore the description does not accurately represent the code.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The declared description presents the skill as a full SaaS demo video generator that takes software information and produces a publish-ready video. The supplied code does not implement that workflow. Instead, it is a narrow utility for sending a message to an already existing Pexo project, with optional preview selection and asset-reference validation, then returning an asynchronous acknowledgement. While this may be part of a larger Pexo system, this specific code chunk’s actual behavior is materially different from the declared end-user purpose.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description says this skill makes SaaS demo or explainer videos using Pexo. The actual code does not generate any video content, scripts, visuals, narration, or captions, and it does not accept app descriptions, URLs, or screenshots for content creation. Instead, its primary purpose is operational diagnostics for a Pexo shell environment: reading a local config file, inspecting environment variables, checking installed command-line tools, testing connectivity, and validating an API key against a projects endpoint. These are materially different behaviors and represent undeclared capabilities unrelated to the stated end-user function of video creation.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

There is a clear description-behavior mismatch. The declared purpose is a content-generation workflow for creating SaaS demo or explainer videos from user inputs such as app descriptions, URLs, or screenshots. The actual code only performs an account-status check: it sources common helpers, calls pexo_get on /api/biz/auth/entitlements, parses available credits with jq, prints entitlement JSON, and suggests purchasing credits if the balance is zero. This is not a supporting implementation detail of video generation in this isolated chunk; its primary purpose is account/credits inspection, which is materially different from the declared end-user functionality.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The declared description promises an end-to-end SaaS demo/explainer video creation workflow. The actual code chunk is a narrow project-creation utility: it parses a project name, calls a project-creation API endpoint, and outputs a project ID. That may be a supporting step in a larger system, but by itself it does not perform the core capabilities described. Therefore the description materially overstates what this code actually does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description promises an end-user capability: generating a SaaS demo/explainer video from app details. The supplied code does not create videos, generate scripts, choose models, add narration, or return a publish-ready video. Instead, it is a backend/helper script for fetching an existing Pexo project's status and message history and computing what an agent should do next. While this may support a larger Pexo workflow, the code chunk’s primary purpose is project-state inspection and orchestration, which is materially different from the declared functionality.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

There is a clear mismatch between the declared purpose and the actual code behavior. The description promises a generative SaaS video creation capability, but the code only implements retrieval of existing project metadata via a paginated API call. This is not a supporting subtask of the described user-facing function; it is a different primary capability centered on listing resources. No video-generation logic, input handling for app descriptions/URLs/screenshots, or finished-video production appears in the code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The declared description emphasizes an end-to-end AI video creation workflow: taking a software description, app URL, or screenshot and producing a publish-ready SaaS demo/explainer video with generated script, visuals, narration, and captions. The actual code does not implement any of those creation features. Instead, it is a low-level asset upload utility for existing local media files. While asset upload could be a supporting component inside a broader video-generation system, this code chunk by itself performs a materially different function than the declared primary purpose and exposes undeclared capabilities/inputs (project asset upload via API using project_id and file_path).

Content

No source excerpt is available for this finding.

Context Leakage

High
Category
Data Exfiltration
Confidence
85% confidence
Finding

Code or instructions that leak agent conversation context to external services, potentially exposing sensitive user interactions.

Content

Scanner excerpt · references/TROUBLESHOOTING.md (reported line 125)May include surrounding context.

md
- `400`: the file was rejected — possible reasons: file exceeds the size limit, file format is not supported, or the file content does not match its extension. Convert or compress the file and re-upload from scratch using `pexo-upload.sh`.
- `401`: auth failure — see Auth and Proxy Errors above.
- `404`: the file record was not found. The upload session may have been cleaned up. Re-upload from scratch using `pexo-upload.sh`.
- `412`: the upload session has already expired or been completed. Re-upload from scratch using `pexo-upload.sh`.
- `500`: an unexpected server error occurred. Retry in a moment; if the problem persists, contact support at pexo.ai.

Context Leakage

High
Category
Data Exfiltration
Confidence
85% confidence
Finding

Code or instructions that leak agent conversation context to external services, potentially exposing sensitive user interactions.

Content

Scanner excerpt · references/TROUBLESHOOTING.md (reported line 126)May include surrounding context.

md
- `400`: the file was rejected — possible reasons: file exceeds the size limit, file format is not supported, or the file content does not match its extension. Convert or compress the file and re-upload from scratch using `pexo-upload.sh`.
- `401`: auth failure — see Auth and Proxy Errors above.
- `404`: the file record was not found. The upload session may have been cleaned up. Re-upload from scratch using `pexo-upload.sh`.
- `412`: the upload session has already expired or been completed. Re-upload from scratch using `pexo-upload.sh`.
- `500`: an unexpected server error occurred. Retry in a moment; if the problem persists, contact support at pexo.ai.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The script directly sources a user-controlled config file with source "$config_path", which executes arbitrary shell code in the current process rather than merely parsing variables. If an attacker can modify that file, influence PEXO_CONFIG, or trick a user into using a malicious config, they can run arbitrary commands under the user's privileges whenever this diagnostic tool is executed.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README encourages users to provide product descriptions or app URLs to a hosted backend but does not clearly warn that this data will be transmitted to a third-party service. In this skill context, users may paste internal SaaS URLs or sensitive product details, creating a realistic risk of unintended disclosure of confidential business information.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · README.md (reported line 15)May include surrounding context.

Configure

Create ~/.pexo/config:

text
PEXO_BASE_URL="https://pexo.ai"

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill declares shell-runtime requirements and operational scripts but does not declare any explicit tool scope or allowed-tools boundaries. That increases the attack surface because an agent may invoke shell capabilities more broadly than intended, making misuse or unexpected command execution harder to constrain and audit.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill explicitly instructs the agent to send the user's request verbatim to a hosted backend, but it does not require a clear user-facing notice or consent before transmitting potentially sensitive text, URLs, or screenshots. In a SaaS-demo context, those inputs may contain proprietary product details, internal links, unreleased UI, or credentials embedded in screenshots, so silent exfiltration to a third party is risky.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
78% confidence
Finding

The skill creates persistent remote projects and directs revisions to reuse the same project, which means user content and conversation context are retained server-side across turns. In this context, persistence is not inherently malicious, but without explicit disclosure, retention limits, or deletion guidance, sensitive business material may remain accessible longer than users expect.

Content

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

md
or a screenshot — to the hosted Pexo agent and deliver the result; Pexo writes the script,
generates the visuals, and adds narration and captions.

## Your role: relay, don't create

Create a project, send the user's request **verbatim**, poll, deliver. Pexo's backend handles
all creative work — scriptwriting, model choice, prompts, music. Adding your own direction

Session Persistence

Medium
Category
Rogue Agent
Confidence
88% confidence
Finding

These instructions establish persistent local storage of an authentication secret in a reusable config file, increasing the window of exposure beyond a one-time interactive use. Persistent session material is risky because compromise of the workstation, dotfile syncing, backups, or accidental sharing of home-directory contents can grant ongoing API access without re-authentication.

Content

Scanner excerpt · references/SETUP-CHECKLIST.md (reported line 7)May include surrounding context.

Quick Start

1. Create config file

bash
mkdir -p ~/.pexo

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The setup instructions tell users to place a live API key in a plaintext file under their home directory without any warning about credential sensitivity, file permissions, or safer secret-handling options. If the file is read by other local users, accidentally committed, included in backups, or exposed through support bundles, the API key could be stolen and used to access the user's Pexo account and resources.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
71% confidence
Finding

The documentation states that downloaded assets are written to a persistent local temp directory under ~/.pexo/tmp/ or an overrideable PEXO_TMP_DIR. In a skill context handling generated media, persistent local storage can increase exposure of potentially sensitive customer assets, especially on shared machines or if permissions on the temp path are weak, and allowing an arbitrary temp path via environment variable can worsen this if not validated by the implementation.

Content

Scanner excerpt · references/TROUBLESHOOTING.md (reported line 181)May include surrounding context.

md
- `403`: the download link has expired. Re-run `pexo-asset-get.sh` to get a fresh link.
- `000`: network request failed before receiving a response. Check network connectivity and retry.
- local filesystem write failure: the temp directory (`~/.pexo/tmp/`) is not writable or the disk is full. Free up space or set `PEXO_TMP_DIR` to a writable path.

Notes:

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% 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/_common.sh (reported line 228)May include surrounding context.

sh
err_file=$(mktemp)

  if [[ -n "$body" ]]; then
    http_code=$(curl -sS \
      --connect-timeout "$_PEXO_CONNECT_TIMEOUT" \
      --max-time "$_PEXO_REQUEST_TIMEOUT" \
      -X "$method" \

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% 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/_common.sh (reported line 241)May include surrounding context.

sh
err_file=$(mktemp)

  if [[ -n "$body" ]]; then
    http_code=$(curl -sS \
      --connect-timeout "$_PEXO_CONNECT_TIMEOUT" \
      --max-time "$_PEXO_REQUEST_TIMEOUT" \
      -X "$method" \

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% 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/_common.sh (reported line 335)May include surrounding context.

sh
set +o pipefail
  if [[ -n "$body" ]]; then
    curl -sS -N \
      --connect-timeout "$_PEXO_CONNECT_TIMEOUT" \
      --max-time "$timeout" \
      -X POST \

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · scripts/pexo-doctor.sh (reported line 79)May include surrounding context.

sh
source "$config_path"
else
  echo "$FAIL Config file not found: $config_path"
  echo "  Create it with:"
  echo '  mkdir -p ~/.pexo && cat > ~/.pexo/config << EOF'
  echo '  PEXO_BASE_URL="https://pexo.ai"'
  echo '  PEXO_API_KEY="sk-<your-api-key>"'

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% 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/pexo-upload.sh (reported line 83)May include surrounding context.

sh
[[ -n "$storage_path" && "$storage_path" != "null" ]] || { echo "Error: upload credential missing storagePath" >&2; echo "$cred" >&2; exit 1; }

# Phase 2: upload file
http_code=$(curl -sS -X PUT -H "Content-Type: $mime_type" \
  --data-binary "@$filepath" -o /dev/null -w '%{http_code}' "$upload_url" 2>/dev/null || echo "000")

[[ "$http_code" =~ ^2 ]] || { echo "Error: upload failed with HTTP $http_code" >&2; exit 1; }

Static analysis

No suspicious patterns detected.