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

Content
View full analysis
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
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/mcp_client.py:226
Finding

Untrusted Video URLs Permit Server-Side Request Forgery and Unbounded Downloads

Content
View full analysis
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
View remediation
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)

Undeclared Tool Scope

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.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.