Back to skill

Security audit

Douyin To Photos

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent Douyin-to-Photos shortcut helper, but users should understand that shared links go to third-party resolver APIs and downloaded media is added to Photos.

Install only if you are comfortable sending Douyin share links to TikWM or your configured resolver and adding the downloaded video to Photos. Prefer a trusted or self-hosted fallback endpoint, avoid using arbitrary parser APIs, and review the Shortcut so it validates real Douyin hostnames and confirms before saving media.

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/fetch_douyin_no_watermark.sh:39
Finding
Douyin domain validation can be bypassed through substring matching<![CDATA[ ## Vulnerability Details **File Location**: `scripts/fetch_douyin_no_watermark.sh`, lines 39-42 **Additional Locations**: `references/shortcut-build-guide.md`, lines 44-47; `assets/shortcut-logic.json`, line 14 **Vulnerability Type**: Improper URL hostname validation **Risk Level**: Medium ### Vulnerable Code ```bash is_valid_douyin_url() { local value="$1" [[ "$value" =~ https?://[^[:space:]]+ ]] && [[ "$value" =~ (douyin\.com|iesdouyin\.com) ]] } ``` The corresponding Shortcut architecture also specifies substring-based validation: ```json {"step": "validate_domain", "action": "must_contain:douyin.com|iesdouyin.com"} ``` ### Technical Analysis The validation checks whether the complete URL string contains `douyin.com` or `iesdouyin.com`. It does not parse the URL and verify its hostname. Consequently, attacker-controlled URLs such as the following satisfy the check even though their actual host is not operated by Douyin: ```text https://attacker.example/path?target=douyin.com https://douyin.com.attacker.example/video https://attacker.example/douyin.com/video ``` The same validation pattern is prescribed by the Shortcut build guide and represented in the Shortcut architecture, so the weakness affects both the shell resolver and implementations created from the documentation. ### Attack Path 1. An attacker supplies or places an attacker-controlled URL in Share Sheet input, text input, or the clipboard. 2. The URL contains the text `douyin.com` or `iesdouyin.com` somewhere outside the legitimate hostname boundary. 3. The substring-based validation accepts the URL. 4. The skill sends the attacker-controlled URL to TikWM or the configured fallback parser. 5. The external parser processes a URL that should have been rejected by the skill's stated domain restriction. ### Impact Assessment This bypass defeats the skill's input-domain security boundary and discloses the supplied URL to an external parser service. Depending on how that exte ...[truncated 354 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Parse the URL and validate the normalized hostname rather than searching the entire string. 1. Require an HTTPS URL unless HTTP support is explicitly necessary. 2. Extract the hostname using a well-tested URL parser. 3. Normalize the hostname to lowercase and remove a trailing dot. 4. Accept only exact approved hosts or subdomains with a dot boundary: - `douyin.com` - `*.douyin.com` - `iesdouyin.com` - `*.iesdouyin.com` 5. Reject malformed URLs, embedded credentials, missing hosts, and ambiguous representations. 6. Apply the same validation logic in the shell script, Shortcut instructions, and architecture asset. 7. Add negative tests for: - `douyin.com.attacker.example` - `attacker.example/?url=douyin.com` - `attacker.example/douyin.com` - encoded or malformed hostnames For shell implementations, hostname extraction should use a proper URL-parsing utility or a small trusted language runtime rather than another permissive regular expression. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
assets/shortcut-logic.json:15
Finding
Provider-controlled media URLs are downloaded without destination or content validation<![CDATA[ ## Vulnerability Details **File Location**: `assets/shortcut-logic.json`, lines 15-30 **Additional Locations**: `scripts/fetch_douyin_no_watermark.sh`, lines 68-74 and 132-148; `references/shortcut-build-guide.md`, lines 89-104 **Vulnerability Type**: Unvalidated server-supplied URL retrieval **Risk Level**: Medium ### Vulnerable Code ```json { "step": "resolve_video_url_primary", "action": "http_post_form", "url": "{{api_primary}}", "body": {"url": "{{share_url}}", "hd": 1, "count": 12}, "expect": {"code": 0, "video_url": "data.hdplay|data.play"} }, { "step": "resolve_video_url_fallback", "when": "primary_failed", "action": "http_post_json", "url": "{{api_fallback}}", "body": {"url": "{{share_url}}"}, "expect": {"video_url": "video_url|data.video_url|data.hdplay|data.play"} }, {"step": "download_video", "action": "http_get_file", "url": "{{video_url}}"} ``` The resolver accepts any non-empty value from the provider: ```bash extract_primary_video_url() { jq -r '.data.hdplay // .data.play // empty' | head -n 1 } extract_fallback_video_url() { jq -r '.video_url // .data.video_url // .data.hdplay // .data.play // empty' | head -n 1 } ``` ### Technical Analysis The workflow treats any non-empty provider response field as a trusted media URL. Before downloading it, the design does not require HTTPS, validate the destination hostname or resolved address, constrain redirects, verify a video content type, or enforce a maximum response size. A compromised parser service or maliciously configured fallback endpoint can therefore return an arbitrary URL. The Shortcut then retrieves that destination using its own network context. Potential targets include loopback services, private-network hosts, link-local endpoints, or attacker-controlled oversized resources. Although the shell resolver only emits the URL, the supplied Shortcut architecture and build guide explicitly consume that value with an unrestricted HTTP GET. ### Atta ...[truncated 1316 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Validate every provider-returned media URL before downloading it: 1. Parse the returned value as an absolute URL. 2. Require HTTPS and reject other schemes. 3. Allowlist expected media or CDN hostnames where operationally possible. 4. Resolve the hostname and reject loopback, private, link-local, multicast, reserved, and unspecified IP address ranges for both IPv4 and IPv6. 5. Repeat destination validation after every redirect, or disable redirects unless explicitly required. 6. Apply a strict request timeout and maximum redirect count. 7. Enforce a maximum download size before and during transfer. 8. Require an expected video MIME type, such as `video/mp4`, and verify the downloaded file signature before importing it. 9. Reject URLs containing credentials or malformed authority components. 10. Treat custom fallback endpoints as trusted security-sensitive configuration and clearly warn users against arbitrary third-party providers. 11. Ensure temporary files are removed on all success, validation-failure, timeout, oversized-response, and import-failure paths. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • 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 (15)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The skill description claims end-to-end local Shortcuts automation, Photos import, cleanup, and privacy-safe behavior, but the documented implementation relies on external API resolution and included resources that do not actually provide the full stated workflow. This mismatch can mislead users and reviewers about what executes, what data leaves the device, and which privacy or platform actions are really implemented.

Ae1

High
Category
analysis-evasion
Content
- `scripts/fetch_douyin_no_watermark.sh`: provider-chain URL resolver with timeout and structured errors.
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill advertises shell-backed functionality via an included resolver script but does not declare any tool scope such as shell or network permissions. This creates a transparency and policy-enforcement gap: reviewers and users cannot accurately assess what capabilities the skill needs, and automated guardrails may fail to apply the right restrictions.

Vague Triggers

Medium
Confidence
89% confidence
Finding
This JSON manifest accepts input from the share sheet, arbitrary text, and the clipboard, but it does not specify when the skill should activate versus when it should ignore unrelated content. For a manifest-scoped file, that lack of trigger specificity can lead to unintended invocation from common user inputs.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The workflow transmits a user-provided Douyin share URL to a third-party API service to resolve the downloadable video URL, but this file shows no disclosure, consent step, or trust boundary warning. Share links can reveal viewing interests, creator relationships, referral data, and other metadata to an external service, creating a privacy leak and possible compliance issue.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The shortcut automatically saves downloaded media into the Photos app, but this file does not show a confirmation step, provenance warning, or disclosure that external content will be written into the user's library. Saving untrusted remote content directly to Photos can surprise users, pollute personal libraries, and create privacy or content-safety issues if the fetched file is not what the user expected.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The manifest routes user-supplied Douyin links to configurable third-party API providers, but it does not clearly warn users that shared links are transmitted off-device. This creates a privacy and consent issue because those links may reveal viewing interests, identifiers embedded in share URLs, or other metadata to external services despite the local-storage privacy statement.

Vague Triggers

Medium
Confidence
88% confidence
Finding
The manifest allows invocation from generic input types like text and clipboard, but does not specify what exact content qualifies beyond the high-level description. For a manifest file, this leaves activation scope ambiguous and could cause unintended triggering from ordinary shared text or clipboard contents.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The shortcut is designed to send Douyin share links, potentially sourced from the clipboard, to third-party resolver APIs such as tikwm or a fallback provider. Those links may contain user-specific tracking parameters or private sharing context, and the guide does not require an explicit user-facing disclosure or consent step before transmitting them off-device.

External Transmission

Medium
Category
Data Exfiltration
Content
local share_url="$2"
  local timeout_sec="$3"

  curl -fsS --max-time "$timeout_sec" \
    -X POST "$api_url" \
    -H 'Content-Type: application/x-www-form-urlencoded' \
    --data-urlencode "url=$share_url" \
Confidence
88% confidence
Finding
This curl call performs direct external transmission of the provided Douyin URL to a third-party API. In the context of a shortcut meant to process user-shared links, that behavior is expected, but it still creates a privacy and trust boundary because link contents and associated metadata leave the local device.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The script sends the user-provided Douyin share URL to a third-party service (tikwm) to resolve a downloadable video URL. Even if functionally necessary, this is still an external disclosure of user-supplied data and can expose viewing/sharing interests, tracking tokens embedded in URLs, or other metadata without any visible consent or notice at this layer.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The fallback path transmits the same share URL to another external API, again disclosing user input to a third party. Because the fallback endpoint is configurable, the privacy risk can increase further if a malicious or untrusted endpoint is supplied, making the data flow less predictable for users.

Natural-Language Policy Violations

Low
Confidence
97% confidence
Finding
The natural-language strings in the errors section force Chinese responses for all users, which can violate language or locale policy when no opt-in or locale selection is provided. There is no accompanying field indicating that the skill is region-specific or that users can choose their preferred language.

Natural-Language Policy Violations

Low
Confidence
96% confidence
Finding
All user-facing error messages are hard-coded in Chinese, while the manifest otherwise uses English and does not document a Chinese-only audience or offer locale selection. This creates a language policy concern because the skill appears to force one language without user opt-in or a stated regional limitation.

Missing User Warnings

Low
Confidence
85% confidence
Finding
The guide automates saving downloaded media into the Photos library but does not emphasize this with an explicit warning or confirmation in the user flow. While the skill description mentions saving to Photos, omission in the build guide can still lead to unintended persistence of content in a sensitive personal media store.

Static analysis

No suspicious patterns detected.