Back to skill

Security audit

web-ai-image-generation

Security checks for vulnerabilities and agentic risk

Overview

The skill matches its stated image-generation purpose, but it uses a persistent logged-in browser profile and disables key browser protections while downloading page-selected URLs, so users should review it before installing.

Install only if you are comfortable with a local browser profile retaining Gemini or ChatGPT login state and with the script saving generated images to disk. Use a dedicated isolated profile, avoid running it as an elevated user, keep the output directory separate from unrelated files, and consider removing --no-sandbox plus restricting downloads to known image hosts before use.

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/ai_image_playwright.py:199
Finding

Unrestricted Authenticated URL Fetching from Page-Controlled Image Sources

Content
View full analysis

Vulnerability Details

File Location: scripts/ai_image_playwright.py, lines 199-218
Vulnerability Type: Server-Side Request Forgery-like arbitrary URL fetching
Risk Level: High

Vulnerable Code

python
if platform == "chatgpt":
    is_candidate = (
        info["width"] >= 300
        and info["height"] >= 300
        and (
            "chatgpt.com/backend-api/estuary/content" in info["src"]
            or "已生成图片" in info["alt"]
            or ("absolute" in info["className"] and "z-1" in info["className"])
            or ("chatgpt.com" in info["src"] and info["width"] >= 500 and info["height"] >= 500)
            or (info["src"].startswith("http") and info["width"] >= 500 and info["height"] >= 500)
        )
    )
else:
    is_candidate = info["width"] >= 400 and info["height"] >= 400
if is_candidate:
    print(f"[download] ✓ Candidate matched: {info['width']}x{info['height']}, src: {info['src'][:60]}...")
    candidates.append((img, info))
python
if platform == "chatgpt" and src.startswith("http"):
    try:
        print(f"[download] Trying page.request.get()...")
        response = await page.request.get(src)
        if response.ok:
            dest_path.write_bytes(await response.body())
            print(f"[download] ✓ Downloaded via page.request")
    except Exception as exc:
        print(f"[download] page.request failed: {exc}")

Technical Analysis

The ChatGPT candidate-selection logic accepts any image whose source starts with http and whose rendered dimensions meet the threshold. The selected URL is then passed directly to page.request.get() without validating its scheme, hostname, resolved address, port, redirect destination, response content type, or response size.

Because Playwright's request context is associated with the active browser context, the request may carry cookies applicable to the destination. More importantly, the requ ...[truncated 1581 chars]

Remediation
View remediation

Remediation Suggestions

  • Parse image URLs with a standard URL parser and allow only https.
  • Maintain an exact allowlist of required image hosts rather than accepting every HTTP URL.
  • Do not use substring checks for hostname validation; compare normalized hostnames against exact approved names or carefully defined subdomains.
  • Resolve destination hostnames and reject loopback, private, link-local, multicast, reserved, and unspecified IP address ranges for both IPv4 and IPv6.
  • Disable redirects or validate every redirect destination using the same scheme, hostname, port, and resolved-address rules.
  • Use a request context that does not automatically share authentication state unless authenticated downloading is strictly required.
  • Validate the response Content-Type against an explicit image-media allowlist.
  • Impose strict response-size, timeout, and download-count limits before loading the entire response into memory or writing it to disk.
  • Decode and validate the response as an actual image before retaining it.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/ai_image_playwright.py:276
Finding

Chromium Sandbox Explicitly Disabled While Processing Remote Content

Content
View full analysis

Vulnerability Details

File Location: scripts/ai_image_playwright.py, lines 276-282
Vulnerability Type: Browser isolation hardening disabled
Risk Level: High

Vulnerable Code

python
context = await p.chromium.launch_persistent_context(
    user_data_dir=str(profile_dir),
    headless=False,
    executable_path=executable_path,
    args=["--lang=zh-CN", "--disable-blink-features=AutomationControlled", "--no-sandbox"],
    viewport={"width": 1280, "height": 800},
)

Technical Analysis

The browser is launched with Chromium's --no-sandbox flag. The script then processes remote Gemini, ChatGPT, and associated third-party web content while using a persistent profile containing authenticated sessions.

Chromium's sandbox is a defense-in-depth boundary intended to restrict a compromised renderer or related browser process. Disabling it does not independently create a browser exploit, but it substantially weakens containment if malicious web content exploits a browser vulnerability. This is particularly significant because the browser profile preserves sensitive login state across executions.

Attack Path

  1. The Skill launches Chromium with --no-sandbox.
  2. The browser loads Gemini or ChatGPT and any associated remote or third-party resources.
  3. Malicious or compromised web content exploits a vulnerability in Chromium or a browser component.
  4. Because the sandbox is disabled, the compromised process has fewer operating-system containment boundaries.
  5. The attacker may act with the operating-system privileges of the user running the Skill, subject to remaining host controls.

Impact Assessment

A successful browser exploit could potentially access files and resources available to the Skill's operating-system account, alter generated output, interact with the persistent browser profile, or expose authenticated session material. The ultimate scope is the privilege level of the p ...[truncated 146 chars]

Remediation
View remediation

Remediation Suggestions

  • Remove --no-sandbox from the default Chromium arguments.
  • Run the browser as a dedicated, unprivileged operating-system user.
  • Ensure the execution environment supports Chromium's user-namespace or setuid sandbox as appropriate.
  • If an exceptional deployment cannot enable the browser sandbox, run it in a tightly isolated, non-root container or virtual machine with a read-only filesystem where practical.
  • Deny unnecessary host mounts, devices, capabilities, and network access in that isolated environment.
  • Keep the persistent profile outside directories accessible to unrelated users and enforce restrictive filesystem permissions.
  • Keep Chrome or Playwright Chromium current with security updates.
  • Fail closed when sandbox initialization fails rather than silently retrying with sandboxing disabled.

T08 · Insecure Dependencies

Warning
Location
requirements.txt:1
Finding

Unpinned and Unhashed Third-Party Dependencies

Content
View full analysis

Vulnerability Details

File Location: requirements.txt, lines 1-2
Vulnerability Type: Non-reproducible dependency resolution and insufficient supply-chain integrity controls
Risk Level: Medium

Vulnerable Code

text
playwright>=1.40
Pillow>=10.0

The documented installation command installs these open-ended dependencies directly:

bash
python -m pip install -r requirements.txt

Technical Analysis

Both dependencies use lower-bound-only constraints. A fresh installation may therefore select any later release accepted by the package resolver. No hashes or lock file are supplied to verify that the installed artifacts are the versions reviewed during the audit.

This makes builds non-reproducible and allows future dependency changes to enter the execution environment without corresponding review. If a package release or distribution channel is compromised, installation or runtime code from the affected artifact may execute locally. Pillow is also not imported by the current script, so retaining it unnecessarily increases the dependency and vulnerability surface.

The package names themselves appear legitimate; the issue is unsafe version and integrity management rather than demonstrated typosquatting or a known malicious package.

Attack Path

  1. A user follows the documented installation command.
  2. The package resolver selects the newest releases satisfying the open-ended >= constraints.
  3. A selected release is compromised, malicious, or unexpectedly incompatible, or its distribution artifact differs from the version previously reviewed.
  4. The artifact is downloaded without project-specified hash verification.
  5. Dependency installation or later import and execution runs the unreviewed code with the privileges of the installing or executing user.

Impact Assessment

A compromised dependency could execute code under the user account performing installation or running ...[truncated 321 chars]

Remediation
View remediation

Remediation Suggestions

  • Pin each direct dependency to an exact reviewed version.
  • Generate a lock file containing exact transitive dependency versions.
  • Require cryptographic hashes for downloaded artifacts, for example through a hash-locked requirements file and pip's --require-hashes option.
  • Update dependencies through a controlled process that includes vulnerability scanning, compatibility testing, and code review.
  • Install packages from an approved package index and protect package-index configuration from untrusted modification.
  • Remove Pillow if image processing does not require it; otherwise explicitly document and test its use.
  • Run dependency installation in a dedicated virtual environment as an unprivileged user.
  • Record and verify the Playwright browser build as part of the reproducible environment, because the Python package and browser binary are separate components.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (10)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- `requirements.txt`:Python 包依赖。

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The document states that the tool reuses a persistent browser profile containing login state, but it does not warn users that session cookies, tokens, and other sensitive account data will be stored locally on disk. In the context of a browser automation skill for Gemini/ChatGPT, this increases the chance that users unknowingly retain sensitive credentials in a predictable directory that could be exposed to other local users, backups, or accidental publication.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill explicitly describes launching a persistent browser context, reusing an existing logged-in profile, and downloading images with authenticated session cookies, but it does not present this as a prominent user-facing warning. This is dangerous because downstream users or orchestrators may invoke the skill without realizing it can act with the full authority of the user's Gemini/ChatGPT web session and save content fetched through those authenticated sessions.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The built-in prompt builder hardcodes Chinese instructions and content, which constrains output language regardless of user preference. This is a natural-language locale policy issue because the script does not offer any language choice or opt-in for these prompts.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The Playwright launch arguments force the browser locale to zh-CN, which may alter UI language and behavior for all users. Because there is no user opt-in or documented region-specific justification in this file, this is a locale policy violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

All user-facing instructions in this file are presented exclusively in Chinese, and the document does not indicate that this is an optional locale or a region-specific requirement. Under the language/locale policy, forcing a single language without opt-in can be a natural-language policy violation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill documents output behavior, but it does not clearly warn users that generated files are written to local storage and that post-processing may delete files deemed invalid. This can cause unexpected persistence of potentially sensitive generated images or surprise deletion behavior, especially when the output directory is shared or user-specified.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
96% confidence
Finding

The dependency specification for Playwright is only lower-bounded (>=1.40) rather than pinned to an exact version. This makes builds non-reproducible and can silently pull in newer releases with security regressions or breaking changes, increasing supply-chain risk even though no specific exploit is evident from this file alone.

Content

Scanner excerpt · requirements.txt (reported line 1)May include surrounding context.

text
playwright>=1.40
Pillow>=10.0

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
99% confidence
Finding

Pillow is specified as >=10.0 instead of an exact version, so the actual installed release cannot be verified and may vary across environments. Because Pillow has a history of multiple security advisories, leaving it unpinned increases the chance of installing a vulnerable or otherwise unreviewed version and weakens reproducibility and auditability.

Content

Scanner excerpt · requirements.txt (reported line 2)May include surrounding context.

text
playwright>=1.40
Pillow>=10.0

Unverifiable Dependency: Pillow has 16 known advisory(ies) (CVE-2016-2533 (Pillow buffer overflow in ImagingPcdDecode); CVE-2023-50447 (Arbitrary Code Execution in Pillow); CVE-2021-27922 (Pillow Uncontrolled Resource Consumption) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
95% confidence
Finding

The manifest includes Pillow without pinning a specific version, while the package has numerous known advisories, including past code execution and denial-of-service issues. Since the resolved version is unknown, consumers of this skill may install an affected release, especially in environments that do not consistently resolve to the latest safe version.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.