Back to skill

Security audit

Filtrix Video Gen

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent Filtrix video-generation helper, but it needs review because it can send API credentials and user content to an unvalidated custom endpoint and can download unbounded content from returned URLs.

Review this skill before installing. Use only the default Filtrix MCP endpoint unless you intentionally trust a custom endpoint, keep the API key scoped or disposable if possible, and do not submit sensitive prompts or images without understanding Filtrix's data handling. Treat downloaded videos as untrusted files, and avoid running downloads from untrusted or test MCP endpoints because returned URLs are not constrained or size-limited.

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/mcp_client.py:35
Finding
Unvalidated MCP Endpoint Can Expose API Credentials and User Content<![CDATA[ ## Vulnerability Details **File Location**: `scripts/mcp_client.py:35-43, 138-142` **Vulnerability Type**: Unrestricted credential-bearing endpoint configuration **Risk Level**: High **Category**: T09: Insecure Skill Coding Practices ### Vulnerable Code ```python def _post(self, payload: dict[str, Any], include_id: bool = True) -> dict[str, Any]: body = json.dumps(payload).encode("utf-8") headers = { "Authorization": f"Bearer {self.api_key}", "Content-Type": "application/json", "Accept": "application/json, text/event-stream", } if self.session_id: headers["mcp-session-id"] = self.session_id req = urllib.request.Request(self.endpoint, data=body, headers=headers, method="POST") ``` ```python def get_mcp_env() -> tuple[str, str]: api_key = os.environ.get("FILTRIX_MCP_API_KEY") or os.environ.get("MCP_API_KEY") if not api_key: raise RuntimeError("FILTRIX_MCP_API_KEY is required") endpoint = os.environ.get("FILTRIX_MCP_URL", DEFAULT_MCP_URL) return endpoint, api_key ``` ### Technical Analysis The client permits `FILTRIX_MCP_URL` to replace the default Filtrix endpoint without validating the URL scheme, hostname, port, or destination. The same client then attaches the Filtrix bearer token to every request sent to that endpoint. Generation requests can contain user prompts and Base64-encoded local images. Consequently, an attacker who can influence the environment variable can redirect the API key and user-supplied content to an attacker-controlled server. An `http://` endpoint is also accepted, allowing credentials and content to cross the network without transport encryption. Base64 conversion in `scripts/generate.py` is a documented serialization mechanism required by the image-to-video API and is not inherently covert. The vulnerability is that the resulting data and bearer credential can be sent to an unrestricted destination. ### Attack Path 1. An attacker, compromise ...[truncated 1326 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Parse the endpoint with `urllib.parse.urlparse` before creating any request. 2. Require the `https` scheme for all production connections. 3. Allowlist `mcp.filtrix.ai` as the default and expected credential recipient. 4. Reject URLs containing user information, fragments, unexpected ports, malformed hostnames, or ambiguous IP representations. 5. If custom endpoints are required for development, require a separate explicit opt-in flag and separate credentials rather than automatically forwarding the production Filtrix key. 6. Display a clear warning or require confirmation before sending credentials or user content to a non-default endpoint. 7. Document that custom MCP endpoints receive prompts, images, request identifiers, and authentication headers. 8. Keep the API key scoped to only the necessary video-generation operations, if the service supports scoped credentials. 9. Add automated tests confirming rejection of plaintext HTTP, unapproved hosts, userinfo URLs, and malformed endpoint values. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/mcp_client.py:226
Finding
Untrusted Video URLs Permit Server-Side Request Forgery and Unbounded Downloads<![CDATA[ ## Vulnerability Details **File Location**: `scripts/mcp_client.py:226-249, 260-269` **Vulnerability Type**: Client-side SSRF and unrestricted resource consumption **Risk Level**: Medium **Category**: T09: Insecure Skill Coding Practices ### Vulnerable Code ```python def extract_video_url(payload: dict[str, Any]) -> str | None: explicit = _find_string_by_keys( payload, ( "video_url", "videoUrl", "download_url", "downloadUrl", "result_url", "resultUrl", "output_url", "outputUrl", "file_url", "fileUrl", "signed_url", "signedUrl", ), ) if explicit and _is_http_url(explicit): return explicit generic = _find_string_by_keys(payload, ("url",)) if generic and _is_http_url(generic) and _looks_like_video_url(generic): return generic return None ``` ```python def download_binary(url: str) -> bytes: req = urllib.request.Request(url, method="GET") try: with urllib.request.urlopen(req, timeout=240) as resp: return resp.read() except urllib.error.HTTPError as exc: detail = exc.read().decode("utf-8", errors="replace") raise RuntimeError(f"Signed URL HTTP {exc.code}: {detail}") except urllib.error.URLError as exc: raise RuntimeError(f"Signed URL network error: {exc.reason}") ``` The download sinks are reached from `scripts/generate.py:197-203` and `scripts/status.py:62-68`. ### Technical Analysis The MCP response is treated as untrusted remote input, but any `http://` or `https://` value under an expected URL key is accepted as a video URL. The download function does not restrict the destination host or IP range, enforce HTTPS, validate the response content type, impose a maximum response size, or stream data with bounded storage. Python's `urllib.request.urlopen` also follows ordinary HTTP redir ...[truncated 2348 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Require HTTPS for all video download URLs. 2. Allowlist expected Filtrix storage or content-delivery domains where operationally possible. 3. Resolve the hostname before connecting and reject loopback, private, link-local, multicast, reserved, and unspecified IP ranges for both IPv4 and IPv6. 4. Repeat destination validation after every redirect and reject unapproved cross-origin redirects. 5. Defend against DNS rebinding by ensuring the validated address is the address used for the connection. 6. Enforce a strict maximum download size using both `Content-Length` checks and a streaming byte counter. 7. Stream downloads in bounded chunks directly to a temporary file instead of reading the entire response into memory. 8. Validate the response content type against an explicit set of supported video types. 9. Validate file signatures where practical and reject HTML, JSON, executable, or otherwise unexpected content. 10. Write to a temporary file first and atomically rename it only after all validation succeeds. 11. Apply separate connection, redirect, and read timeouts, and limit the number of redirects. 12. Add tests covering loopback URLs, RFC1918 addresses, IPv6 local addresses, cloud metadata addresses, redirects to private destinations, oversized payloads, and invalid content types. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (7)

Lp3

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding
The skill exposes broad capabilities through documented scripts and MCP usage but does not declare any explicit tool scope such as permissions or allowed-tools. That creates a least-privilege failure: an agent or runtime may permit environment access, file reads/writes, network, and MCP operations more broadly than necessary, increasing the blast radius if the skill is misused, prompt-injected, or invoked in an unexpected context.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The documentation directs prompts and potentially sensitive images to an external MCP endpoint but provides no user-facing disclosure about third-party data transfer, retention, or privacy implications. In this skill context, users may upload personal or proprietary images for video generation, so lack of transparency can lead to unintended exfiltration of sensitive content to an external service.

Description-Behavior Mismatch

Medium
Confidence
94% confidence
Finding
The documented `get_account_credits` capability expands the skill's effective scope beyond the stated manifest description of video generation, polling, and download-related actions. This creates an overprivileged or misleading interface: an agent or user may invoke billing/subscription queries without expecting that the skill can access account-level metadata, which increases privacy and least-privilege concerns even if the operation is read-only.

Missing User Warnings

Low
Confidence
88% confidence
Finding
The client sends JSON payloads and an Authorization bearer token to a remote MCP endpoint via HTTP POST, but the file contains no confirmation prompt, logging, print statement, or comment/docstring warning users that data will be transmitted off-host. Because this is a code file performing external network communication, the absence of any visible disclosure matches the missing-warning criterion.

Missing User Warnings

Low
Confidence
84% confidence
Finding
The function reads FILTRIX_MCP_API_KEY or MCP_API_KEY from the environment, but the file provides no user-facing notice, explanatory comment, or documentation warning that sensitive credentials are accessed. This fits the code-file warning rule for access to sensitive environment variables without visible disclosure.

Missing User Warnings

Low
Confidence
82% confidence
Finding
The function downloads arbitrary bytes from a caller-supplied URL with no allowlist, content-type validation, size limit, or destination trust checks. In this skill context, URLs may originate from remote MCP responses, so a compromised or malicious service could direct the client to fetch attacker-controlled content, enabling SSRF-like outbound access, resource exhaustion, or retrieval of unexpected payloads that downstream code may later treat as trusted video data.

Missing User Warnings

Low
Confidence
79% confidence
Finding
This function creates parent directories for an output path and prepares a location under /tmp or a user-supplied path, but the file contains no warning or explanatory note that the skill will write generated output to disk. For code files, filesystem-modifying behavior should have at least some visible disclosure when no other warning is present.

Static analysis

No suspicious patterns detected.