Back to skill

Security audit

Animate Old Photos

Security checks for vulnerabilities and agentic risk

Overview

The skill appears to perform the advertised photo-animation workflow, but it needs review because it uploads user photos and handles a paid API key through under-scoped shell commands.

Install only if you are comfortable sending selected photos to Animate Old Photos and its storage provider, spending paid credits, and using shell execution. Prefer setting the API key through a protected environment or secret mechanism instead of command-line arguments, avoid sensitive photos unless you understand the service's privacy/retention behavior, and choose an output path that will not overwrite important files.

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

Warning
Location
scripts/animate.sh:38
Finding

API Key Exposed Through Command-Line Arguments

Content
View full analysis
[PROMPT] [OUTPUT_PATH] ``` ```bash API_KEY="${1:-${AOP_API_KEY:-}}" ``` The unsafe interface is also promoted in the documentation: ```bash bash scripts/animate.sh [PROMPT] [OUTPUT_PATH] ``` ```bash bash scripts/animate.sh aop_xxxx ./grandma.jpg "gentle smile and slight head turn" ./result.mp4 ``` ### Technical Analysis The script accepts the paid-service API key as its first positional command-line argument. Command-line arguments can be exposed through shell history, process inspection utilities, terminal or session recordings, job-control systems, agent execution traces, and centralized telemetry. Although the script supports the `AOP_API_KEY` environment variable as a fallback, its primary usage syntax and examples explicitly encourage users to place the credential on the command line. The environment-variable example also expands the secret into an argument: ```bash bash scripts/animate.sh "$AOP_API_KEY" ./grandma.jpg ``` Consequently, that example does not avoid command-line process exposure. ### Attack Path 1. A user follows the documented example and supplies the API key as the first script argument. 2. The complete command may be saved in shell history or captured by terminal, agent, or job-execution logs. 3. While the script is running, another sufficiently privileged local process may inspect its command-line arguments. 4. An attacker or unauthorized log reader extracts the API key. 5. The attacker submits the key to the Animate Old Photos authentication endpoint. 6. If the key remains valid, the attacker can consume the victim's paid credits and perform operations authorized by that key. ### Impact Assessment Successful ex ...[truncated 397 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/animate.sh:126
Finding

Unvalidated Server-Controlled URLs Passed Directly to curl

Content
View full analysis
/dev/null && [ -n "$RESOURCE" ]; then curl -s -o "$OUTPUT" "$RESOURCE" ok "Video saved to ${OUTPUT}" echo "" printf "${GREEN}Done!${NC} Animation complete. Output: %s\n" "$OUTPUT" exit 0 fi ``` ### Technical Analysis The script trusts the API-provided `uploadUrl` and `resource` fields as curl destinations without validating their schemes, hosts, ports, embedded credentials, or redirect targets. It also does not use an explicit `--` option terminator before these URL values. If the remote API or its backend is compromised, misconfigured, or returns attacker-controlled data, the script becomes a network-capable confused deputy: - The input image can be uploaded to an unintended attacker-controlled destination. - The host running the skill can be induced to request internal or local network resources. - Unsupported or dangerous curl URL schemes are not explicitly rejected. - A URL beginning with option-like syntax may be interpreted unexpectedly by ...[truncated 1900 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (21)

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

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

Step 1 — Authenticate

Exchange the API key for a short-lived access token and check the credit balance.

bash
API_KEY="${AOP_API_KEY}"

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/animate.sh (reported line 100)May include surrounding context.

sh
### Step 1 — Authenticate

Exchange the API key for a short-lived access token and check the credit balance.

```bash
API_KEY="${AOP_API_KEY}"

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/animate-old-photos-api.md (reported line 13)May include surrounding context.

md
### POST /api/extension/auth

Exchange an API key (license key) for a short-lived access token.

**Request**

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/animate-old-photos-api.md (reported line 224)May include surrounding context.

md
|------------|---------|
| `999990` | Insufficient credits |
| `10009` | Insufficient credits |
| `999998` | Access token invalid/expired |

---

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/animate-old-photos-api.md (reported line 289)May include surrounding context.

md
|------------|---------|
| `999990` | Insufficient credits |
| `10009` | Insufficient credits |
| `999998` | Access token invalid/expired |

---

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

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

md
4010|4011)
      fail "${context}: Invalid or expired API key. Get one at: ${BASE_URL}/profile/interface-key" 2 ;;
    999998)
      fail "${context}: Access token expired. Please re-run the script." 2 ;;
    999990|10009)
      fail "${context}: Insufficient credits. Purchase at: ${BASE_URL}/stripe" 3 ;;
    *)

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/animate.sh (reported line 81)May include surrounding context.

sh
4010|4011)
      fail "${context}: Invalid or expired API key. Get one at: ${BASE_URL}/profile/interface-key" 2 ;;
    999998)
      fail "${context}: Access token expired. Please re-run the script." 2 ;;
    999990|10009)
      fail "${context}: Insufficient credits. Purchase at: ${BASE_URL}/stripe" 3 ;;
    *)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The README explains that the skill uploads local images and submits them to an external API, but it does not prominently warn users that personal or sensitive local photos will leave the local environment and be sent to a third-party service. This can lead users or agents to transmit private images without informed consent, creating privacy and data-handling risk rather than a direct code-execution issue.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The README suggests activation phrases like "Animate this old photo" and "Turn this photo into a video" without defining boundaries, exclusions, or a narrower invocation context. These are natural user requests that could overlap with general image-editing conversations, making the trigger scope ambiguous for agents that auto-select skills from README descriptions.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
96% confidence
Finding

The skill invokes shell commands extensively but does not declare any tool scope or allowed-tools restrictions. This creates an unnecessary trust gap: an agent may execute shell-capable behavior without explicit sandboxing or least-privilege constraints, increasing the chance of unintended command execution or misuse if the skill is triggered in the wrong context.

Content

No source excerpt is available for this finding.

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 · SKILL.md (reported line 43)May include surrounding context.

bash
API_KEY="${AOP_API_KEY}"
AUTH=$(curl -s -X POST https://animateoldphotos.org/api/extension/auth \
  -H "Content-Type: application/json" \
  -d "{\"licenseKey\":\"${API_KEY}\"}")
TOKEN=$(echo "$AUTH" | jq -r '.accessToken')

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 · SKILL.md (reported line 64)May include surrounding context.

md
FILE_SIZE=$(stat -f%z "$IMAGE_PATH" 2>/dev/null || stat -c%s "$IMAGE_PATH" 2>/dev/null)
CONTENT_TYPE="image/jpeg"  # use image/png for .png files

UPLOAD=$(curl -s -X POST https://animateoldphotos.org/api/extension/upload-token \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"fileName\":\"$(basename "$IMAGE_PATH")\",\"contentType\":\"${CONTENT_TYPE}\",\"fileSize\":${FILE_SIZE}}")

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 · SKILL.md (reported line 72)May include surrounding context.

md
KEY=$(echo "$UPLOAD" | jq -r '.key')
PUBLIC_URL=$(echo "$UPLOAD" | jq -r '.publicUrl')

curl -s -X PUT "$UPLOAD_URL" \
  -H "Content-Type: ${CONTENT_TYPE}" \
  --data-binary "@${IMAGE_PATH}"
echo "Image uploaded."

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger includes a catch-all phrase such as "or similar," which broadens activation beyond well-defined user intents. Ambiguous activation is risky for a shell-executing, credit-spending skill because the agent may invoke it when the user did not clearly intend to upload a file, transmit data externally, and incur paid API charges.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The API reference explicitly documents that uploaded images are returned via a publicUrl, but it does not warn that the uploaded photo may become publicly accessible to anyone with the URL. Because this skill handles personal photos, including potentially sensitive family images, lack of a privacy warning can lead users or integrators to expose private content unintentionally.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The completed animation response returns a resource URL hosted on a public R2 domain, while the documentation does not clearly explain whether generated videos are publicly accessible or how long they remain reachable. Since the skill processes user-supplied photos into videos, unclear result visibility creates a meaningful privacy risk of unintended disclosure.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The script explicitly supports passing the API key as a positional command-line argument. On multi-user systems or logged shells, command-line arguments may be exposed via shell history, process listings, CI logs, or audit tooling, which can leak the paid service credential to other users or systems.

Content

No source excerpt is available for this finding.

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/animate.sh (reported line 94)May include surrounding context.

sh
# ---------------------------------------------------------------------------
step "1/5" "Authenticating..."

AUTH=$(curl -s -X POST "${BASE_URL}/api/extension/auth" \
  -H "Content-Type: application/json" \
  -d "{\"licenseKey\":\"${API_KEY}\"}")
check_error "$AUTH" "Auth"

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/animate.sh (reported line 113)May include surrounding context.

sh
# ---------------------------------------------------------------------------
step "2/5" "Uploading image ($(( FILE_SIZE / 1024 ))KB)..."

UPLOAD=$(curl -s -X POST "${BASE_URL}/api/extension/upload-token" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -d "{\"fileName\":\"$(basename "$IMAGE_PATH")\",\"contentType\":\"${CONTENT_TYPE}\",\"fileSize\":${FILE_SIZE}}")

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/animate.sh (reported line 121)May include surrounding context.

sh
UPLOAD_URL=$(echo "$UPLOAD" | jq -r '.uploadUrl // empty')
KEY=$(echo "$UPLOAD" | jq -r '.key // empty')
PUBLIC_URL=$(echo "$UPLOAD" | jq -r '.publicUrl // empty')

[ -z "$UPLOAD_URL" ] && fail "Failed to get upload URL." 4

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

The downloaded video is written directly to the user-supplied output path without checking whether the file already exists. This can unintentionally overwrite existing files or write sensitive content into an unexpected location if the caller supplies a dangerous path.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.generated_source_template_injection

User-controlled placeholder is embedded directly into generated source code.

Critical
Code
suspicious.generated_source_template_injection
Location
SKILL.md:42