Back to skill

Security audit

Product to Ads (Ad-Ready)

Security checks for vulnerabilities and agentic risk

Overview

The skill matches its ad-generation purpose, but its auto-fetch path can retrieve arbitrary URLs and upload the result to a cloud service, and its talent prompts require sensitive appearance handling.

Review before installing. Use this only with trusted product URLs and assets, avoid auto-fetch for untrusted or internal URLs, and assume product data, uploaded images, model references, logos, and generated outputs interact with ComfyDeploy. Do not supply real talent/model images unless you have consent and rights to use the likeness. Prefer running it in a sandbox with restricted network access and pinned dependencies.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/generate.py:157
Finding
Unrestricted URL Fetching Enables Server-Side Request Forgery## Vulnerability Details **File Location**: `scripts/generate.py`, lines 157-235 and 432-455 **Vulnerability Type**: Server-Side Request Forgery through user-controlled URLs and redirects **Risk Level**: High ### Vulnerable Code ```python def download_to_file(client: httpx.Client, url: str, dest: Path) -> bool: """Download a URL to a local file. Returns True on success.""" try: headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36", "Accept": "image/*,*/*;q=0.8", } response = client.get(url, headers=headers, follow_redirects=True, timeout=20.0) if response.status_code == 200 and len(response.content) > 1000: content_type = response.headers.get("content-type", "") if "image" in content_type or "octet" in content_type or len(response.content) > 5000: dest.parent.mkdir(parents=True, exist_ok=True) dest.write_bytes(response.content) size_kb = len(response.content) / 1024 print(f" ✓ Downloaded: {dest.name} ({size_kb:.0f}KB)", flush=True) return True except Exception as e: print(f" ✗ Download failed: {e}", flush=True) return False def fetch_product_image(client: httpx.Client, product_url: str, dest: Path) -> bool: """Try to find and download the main product image from a product page.""" try: from bs4 import BeautifulSoup except ImportError: print(" ⚠ beautifulsoup4 not available for product image extraction", flush=True) return False print(" Fetching product page for main image...", flush=True) try: headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36", "Accept": "text/html,*/*", } response = client.get(product_url, headers=headers, follow_redir ...[truncated 4779 chars]
Remediation
## Remediation Suggestions 1. Accept only `https` URLs unless another scheme is explicitly required. 2. Resolve every hostname before connecting and reject loopback, private, link-local, multicast, unspecified, and reserved IPv4 and IPv6 addresses. 3. Disable automatic redirects or validate the scheme, hostname, port, and resolved address of every redirect hop. 4. Apply identical validation to product URLs, `og:image` URLs, HTML image URLs, and generated output URLs. 5. Use an outbound allowlist or isolated fetching proxy where practical. 6. Stream responses and enforce strict limits on response size, content type, and download duration. 7. Validate actual image structure using an image-decoding library rather than trusting headers or file size. 8. Require explicit user confirmation before uploading automatically fetched content to ComfyDeploy. 9. Document that the product URL and selected assets are transmitted to a third-party cloud service. 10. Ensure the remote ComfyDeploy deployment applies equivalent SSRF controls to its server-side scraper.

T08 · Insecure Dependencies

Warning
Location
scripts/generate.py:2
Finding
Unpinned Runtime Dependencies Create Supply-Chain Exposure## Vulnerability Details **File Location**: `scripts/generate.py`, lines 2-7 **Vulnerability Type**: Non-reproducible dependency resolution using open-ended version constraints **Risk Level**: Medium ### Vulnerable Code ```python # /// script # requires-python = ">=3.10" # dependencies = [ # "httpx>=0.25.0", # "beautifulsoup4>=4.12.0", # ] # /// ``` ### Technical Analysis The documented execution method uses `uv run`, which can resolve and install dependencies declared in the inline script metadata. Both dependencies have only lower version bounds. There is no lockfile, exact version pin, package hash, or upper bound in the audited project. As a result, the package versions executed in the future may differ from those reviewed during this audit. A compromised upstream release, malicious package-index substitution, or unexpectedly incompatible future release could enter the execution environment without a corresponding change to this repository. No evidence was found that `httpx` or `beautifulsoup4` are currently malicious. The vulnerability is the absence of reproducible and integrity-verified dependency resolution. ### Attack Path 1. A user runs the documented `uv run scripts/generate.py` command. 2. The required dependencies are absent from the local environment. 3. `uv` resolves any available versions satisfying the open-ended lower bounds. 4. Packages are downloaded from the configured package index and imported by the script. 5. If an accepted upstream release or configured index is compromised, its code executes with the same operating-system privileges as the Skill process. ### Impact Assessment A malicious dependency could access files, environment variables, API credentials, and network resources available to the Agent process. This includes the `COMFY_DEPLOY_API_KEY` environment variable and user-supplied advertising assets. The effective scope is limited by the operating-system pri ...[truncated 132 chars]
Remediation
## Remediation Suggestions 1. Pin dependencies to exact versions that have been reviewed. 2. Commit and enforce a lockfile generated from a trusted package index. 3. Verify package artifacts with cryptographic hashes. 4. Configure an explicit trusted index rather than inheriting arbitrary environment-level package sources. 5. Use automated dependency scanning and controlled update reviews. 6. Run the Skill in a sandbox with minimal filesystem, environment-variable, and network access. 7. Rebuild the lockfile only through a documented, reviewed dependency-update process.

T09 · Insecure Skill Coding Practices

Note
Location
scripts/generate.py:247
Finding
Logo Service Token Is Hardcoded in Source Code## Vulnerability Details **File Location**: `scripts/generate.py`, lines 247-255 **Vulnerability Type**: Hardcoded third-party service token **Risk Level**: Low ### Vulnerable Code ```python clean_name = brand_name.lower().replace("_", "").replace(" ", "").replace("-", "") logo_attempts = [ f"https://logo.clearbit.com/{clean_name}.com", f"https://logo.clearbit.com/{clean_name}.com.ar", f"https://img.logo.dev/{clean_name}.com?token=pk_X-1ZO13GSgeOoUrIuJ6GMQ", ] ``` ### Technical Analysis A Logo.dev token is embedded directly in the repository and included in a URL query parameter. Anyone with access to the Skill package can recover and reuse it. The `pk_` prefix suggests that this may be intended as a publishable client token. However, the audited project does not document its scope, quota restrictions, domain restrictions, or whether public distribution is intentional. Hardcoding the value still prevents independent configuration and controlled rotation, while URL query parameters may also be recorded in request logs. The ComfyDeploy API key is not hardcoded; it is read from an argument or the `COMFY_DEPLOY_API_KEY` environment variable and is not part of this finding. ### Attack Path 1. An attacker downloads or inspects the Skill package. 2. The attacker extracts the Logo.dev token from `scripts/generate.py`. 3. The attacker submits unrelated Logo.dev requests using that token. 4. Requests may consume associated quota or cause service-side abuse attribution to the token owner. 5. Revocation of the exposed token can subsequently disrupt the Skill's automatic logo-fetching behavior. ### Impact Assessment The likely impact is unauthorized use of the associated Logo.dev quota, attribution leakage, or operational disruption if the service blocks or revokes the token. This finding does not expose the ComfyDeploy or Gemini API keys and does not directly grant local system privileges. The practica ...[truncated 159 chars]
Remediation
## Remediation Suggestions 1. Remove the token from source control and rotate the exposed value. 2. Load the token from an environment variable or user-controlled configuration. 3. Clearly document whether the token is publishable and what restrictions protect it. 4. Apply the narrowest available quota, origin, domain, endpoint, and rate restrictions. 5. Avoid placing sensitive credentials in URL query parameters; use an authorization header when supported. 6. Allow automatic logo fetching to be disabled when no Logo.dev credential is configured.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (22)

Description-Behavior Mismatch

High
Confidence
98% confidence
Finding
The file’s behavior and identity materially conflict with the skill manifest: it invokes a Morfeo/Morfeo-style multimodal creative workflow driven by canonical product/talent images, not the declared URL-driven Ad-Ready pipeline. In an agent setting, this mismatch is dangerous because users and orchestrators may route data, permissions, and expectations based on the manifest, while the prompt actually steers the model into a different workflow with different inputs, outputs, and safety/privacy characteristics.

Intent-Code Divergence

High
Confidence
97% confidence
Finding
The prompt explicitly brands itself as 'MORFEO CREATIVE STAGE,' directly contradicting the skill’s advertised identity and differentiation. This increases the risk of deceptive execution, accidental misuse of the wrong pipeline, and policy bypass through configuration confusion, especially when downstream systems trust metadata to decide whether a skill is appropriate for a user request.

Lp3

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The skill clearly instructs the agent to use network access, environment variables, and local file writes/downloads, but it does not declare any explicit tool scope or permission boundaries. This creates a least-privilege failure: an agent may perform broader network/file operations than reviewers or users expect, increasing the chance of unintended data access, exfiltration, or unsafe side effects.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The skill says the `language` parameter should be omitted so the pipeline falls back to Spanish by default, even when the user did not request Spanish output. This can cause silent user-intent mismatch and unexpected transmission of generated marketing content in the wrong language, which is a consent and quality issue rather than a direct code-execution risk.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
The API documentation reinforces that Spanish is the implicit default output language and advises not sending the parameter unless the user requests another language. This hides a user-affecting behavior in backend defaults and can produce unintended ad copy, especially in multilingual or English-first contexts.

Context-Inappropriate Capability

Medium
Confidence
97% confidence
Finding
The skill explicitly directs analysis of sensitive human characteristics such as facial features, ethnicity, and body type before generation. Because the skill’s stated purpose is creating product ads from URLs, this broad sensitive-attribute processing is not clearly necessary and can enable demographic profiling, identity replication, or non-consensual likeness handling.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The prompt instructs the system to preserve and describe highly specific identity and body attributes of a referenced person, including facial structure, ethnicity, age range, and body proportions. For a URL-driven product-ad skill, this is unnecessary overcollection and use of sensitive biometric-like and demographic data, increasing privacy, profiling, and misuse risks if real people’s images are supplied.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
Mandating that the system describe ethnicity exactly as seen forces protected-attribute processing without user choice or clear necessity. In this ad-generation context, that creates avoidable fairness, privacy, and compliance risks and may normalize demographic classification from images.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
The prompt explicitly locks 'ethnicity' to the reference image as an immutable attribute, which bakes sensitive-attribute processing into the generation policy without any visible user opt-in, necessity test, or policy guardrails. In an ad-generation skill, this can lead to discriminatory or non-consensual identity handling and makes the system less able to honor user preferences or compliance requirements around protected traits.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
The output schema requires 'ethnicity_and_skin_tone: Exactly as reference,' which operationalizes sensitive-attribute retention as a mandatory output constraint. Because this skill is specifically for producing advertising creatives with talent imagery, the fixed handling of protected attributes is more dangerous in context: it can propagate bias, create compliance issues, and normalize protected-trait conditioning in commercial content workflows.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
The prompt explicitly locks 'ethnicity' to the reference image and instructs the system not to change it, without any visible user-controlled consent, necessity check, or policy guard. In an ad-generation skill, this creates sensitive-attribute handling risk because ethnicity is being inferred, preserved, and operationalized as a generation constraint, which can enable discriminatory or inappropriate personalization flows.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The prompt explicitly instructs preservation of a person's ethnicity from a reference image, which hard-codes a sensitive attribute into generation behavior without any visible consent, necessity check, or policy guardrail. In an ad-generation skill, this can enable sensitive-trait processing and discriminatory or non-consensual identity targeting, especially when combined with strict identity-lock instructions.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
This repeated constraint reinforces exact preservation of ethnicity and skin tone in the talent identity lock, making sensitive-attribute handling a core requirement of the workflow rather than an incidental description. Because the skill is designed for producing marketing creatives, the context increases risk of profiling, exclusionary audience tailoring, or unauthorized replication of a real person's protected characteristics.

Natural-Language Policy Violations

Medium
Confidence
84% confidence
Finding
The instruction "Generate ONLY this JSON Blueprint. No additional text, explanations, or markdown formatting outside the JSON" combines with the entire schema and directives being fixed in English, leaving no user opt-in or alternative locale path. This can violate language/locale policy when users or downstream systems expect localized output or language choice.

External Transmission

Medium
Category
Data Exfiltration
Content
sys.stderr.reconfigure(line_buffering=True)

DEPLOYMENT_ID = "e37318e6-ef21-4aab-bc90-8fb29624cd15"
API_BASE = "https://api.comfydeploy.com/api"

# Dynamic brand profiles from catalog
BRANDS_DIR = Path.home() / "clawd" / "ad-ready" / "configs" / "Brands"
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
sys.stderr.reconfigure(line_buffering=True)

DEPLOYMENT_ID = "e37318e6-ef21-4aab-bc90-8fb29624cd15"
API_BASE = "https://api.comfydeploy.com/api"

# Dynamic brand profiles from catalog
BRANDS_DIR = Path.home() / "clawd" / "ad-ready" / "configs" / "Brands"
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The CLI sets `--language` to `es` by default and later only sends a language value when it differs from Spanish, making Spanish the implicit output language for all runs. This is a natural-language locale policy issue because the skill imposes a specific language unless the user explicitly overrides it.

Context-Inappropriate Capability

Low
Confidence
82% confidence
Finding
The requirement to replicate a reference pose exactly broadens the skill from product-ad generation into close imitation of third-party creative material. While less severe than identity analysis, it raises copyright, style-copying, and unauthorized reference-reproduction risks, especially when users submit external images they do not own.

Natural-Language Policy Violations

Low
Confidence
76% confidence
Finding
The prompt hard-codes presentation choices such as 'observer POV,' 'informed, present gaze,' and 'Confident, calm, trustworthy' as mandatory outputs. While not a language restriction, this is a natural-language policy concern because it imposes a single communicative framing without any user opt-in or documented exception handling.

Natural-Language Policy Violations

Low
Confidence
81% confidence
Finding
The prompt prescribes fixed copy characteristics such as "Decisive, clear, confident" and constrains wording, but it never offers a user-selectable language or locale option for generated ad copy. This can violate language/locale policy expectations when a skill may be used in multilingual contexts and silently defaults to one style/language regime.

Natural-Language Policy Violations

Low
Confidence
85% confidence
Finding
The instruction "Think: Wes Anderson meets high fashion meets Latin American magical realism" imposes a specific stylistic and cultural framing as a default behavior. This can be a language/locale-style policy concern because it mandates a particular cultural expression without indicating user choice or opt-in.

Missing User Warnings

Low
Confidence
81% confidence
Finding
When `--auto-fetch` is used, the script downloads remote assets and writes them into `/tmp/ad-ready` without any explicit warning in the main help text or argument descriptions that local files will be created. Although progress is printed at runtime, the user-facing interface does not clearly disclose this file-writing side effect before execution.

Static analysis

No suspicious patterns detected.