Back to skill

Security audit

drivethru-graphic-artist

Security checks for vulnerabilities and agentic risk

Overview

The skill is purpose-aligned, but it needs review because it can run background jobs, write business product and decoration records, and fetch unvalidated external image URLs.

Install only in an environment where this skill is allowed to modify Odoo catalog and decoration records. Use tightly scoped Odoo credentials, restrict outbound network access, configure the vision provider deliberately, and avoid unattended web-image routines until URL-fetch validation or an egress allowlist is in place.

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 (1)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/web_mockup_job.py:153
Finding

Server-Side Request Forgery Through Unrestricted Image URL Fetching

Content
View full analysis

Vulnerability Details

File Location: scripts/web_mockup_job.py:153-155
Vulnerability Type: Server-Side Request Forgery (SSRF)
Risk Level: Medium

Vulnerable code:

python
elif source.get("url"):
    import requests

    # Public CDN/vendor URL — do not send the Odoo credential elsewhere.
    resp = requests.get(source["url"], timeout=HTTP_TIMEOUT)

Technical Analysis

The web mockup workflow accepts image source URLs returned by the remote Odoo planning service and passes them directly to requests.get(). It does not validate:

  • The URL scheme
  • The destination hostname
  • Resolved IP address ranges
  • Redirect destinations
  • Whether the destination is loopback, link-local, private, reserved, or otherwise non-public

requests.get() follows redirects by default. Consequently, even a URL initially pointing to an approved public image host can redirect the agent host to an internal destination.

The comment correctly notes that the Odoo authorization header is not attached to this separate request. This prevents direct disclosure of the Odoo token but does not prevent SSRF from the agent host.

Attack Path

  1. An attacker controls or influences an art or blank image URL returned in a web_mockup_plan response, or controls an external image endpoint used by that response.
  2. The workflow reaches Odoo.download() while processing the affected source.
  3. The attacker supplies a direct internal URL or returns an HTTP redirect to a destination such as a loopback, link-local, or private-network service.
  4. requests.get() connects to that destination using the network privileges of the agent host.
  5. The workflow checks only the status and broad Content-Type conditions before writing the response to disk.
  6. If the response contains image-compatible data, it may be incorporated into a mockup and uploaded to Odoo through the workflow’s normal upload path.

Impact Assessment

...[truncated 580 chars]

Remediation
View remediation

Remediation Suggestions

  • Permit only the https scheme for externally supplied image URLs.
  • Maintain an allowlist of approved vendor and CDN hostnames where operationally practical.
  • Resolve the destination hostname before connecting and reject loopback, link-local, private, multicast, reserved, and other non-global address ranges for both IPv4 and IPv6.
  • Disable automatic redirects with allow_redirects=False, or manually follow redirects while applying the complete URL and resolved-address validation policy to every hop.
  • Revalidate the connected peer address to reduce DNS-rebinding and time-of-check/time-of-use risks.
  • Apply strict response size limits and image decoding validation before persisting response data.
  • Route external image retrieval through a dedicated egress proxy that enforces destination restrictions.
  • Add regression tests covering direct private addresses, IPv6 local addresses, alternate numeric IP representations, DNS rebinding scenarios, and public URLs redirecting to internal services.
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (40)

Tainted flow: 'body' from os.environ.get (line 296, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/vision_review.py (reported line 307)May include surrounding context.

python
{"role": "user", "content": content}],
    }
    try:
        resp = requests.post(f"{base_url}/chat/completions", json=body, timeout=timeout,
                             headers={"Authorization": f"Bearer {api_key}"})
        data = resp.json()
    except Exception as exc:  # noqa: BLE001

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The skill bundles multiple powerful workflows beyond the declared decoration-production role, including scheduled storefront image generation, job management, and blank-photo refresh behavior. Combining these broader automation capabilities with mutable state, network access, and uploads under a benign 'graphic artist' label increases the chance of over-privileged execution and unintended business-data changes.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The skill bundles multiple powerful workflows beyond the declared decoration-production role, including scheduled storefront image generation, job management, and blank-photo refresh behavior. Combining these broader automation capabilities with mutable state, network access, and uploads under a benign 'graphic artist' label increases the chance of over-privileged execution and unintended business-data changes.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The skill bundles multiple powerful workflows beyond the declared decoration-production role, including scheduled storefront image generation, job management, and blank-photo refresh behavior. Combining these broader automation capabilities with mutable state, network access, and uploads under a benign 'graphic artist' label increases the chance of over-privileged execution and unintended business-data changes.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
canonical placement diagram at `assets/decoration_guide.png`). That's the

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
(built from the official spec sheet, `references/decoration_spec_sheet.pdf`) as

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
**Full step-by-step procedure: [`references/production_ready.md`](references/production_ready.md).**

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

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

md
> ~38% of the image (the interior field). Correct call (a one-color black print
> where the garment shows through), but big enough to eyeball before uploading.

#### The thumbnail's background is not a print instruction

A decoration has two separate image artifacts — don't let one contaminate the
other:

os.system() or os exec-family call

High
Category
Dangerous Code Execution
Confidence
85% confidence
Finding

os.system() and os exec-family calls run shell commands with the process's full privileges, enabling arbitrary command execution.

Content

Scanner excerpt · scripts/_bootstrap.py (reported line 125)May include surrounding context.

python
# Re-run the exact same command, now under the venv interpreter. On that
    # second entry `ensure()` finds the modules present and returns immediately.
    os.execv(str(py), [str(py), *sys.argv])

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · scripts/compose_mockup.py (reported line 92)May include surrounding context.

python
mine = rules.setdefault(cat, {})
                for placement, rule in bucket.items():
                    mine.setdefault(placement, rule)
    return rules


# LEFT/RIGHT IN A PLACEMENT NAME ARE THE WEARER'S. Blanks are flat FRONT photos,

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · scripts/edit_placement_rule.py (reported line 110)May include surrounding context.

python
mine = rules.setdefault(cat, {})
                for placement, rule in bucket.items():
                    mine.setdefault(placement, rule)
    return rules


# LEFT/RIGHT IN A PLACEMENT NAME ARE THE WEARER'S. Blanks are flat FRONT photos,

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · scripts/compose_mockup.py (reported line 110)May include surrounding context.

python
side = placement.split("_", 1)[0]
    want = _WEARER_SIDE_IMAGE_HALF.get(side)
    if not want or "back" in placement:
        return rule, None
    x = float(rule["x_center_ratio"])
    wrong = (want == "right" and x < 0.5) or (want == "left" and x > 0.5)
    if not wrong:

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · scripts/compose_mockup.py (reported line 114)May include surrounding context.

python
side = placement.split("_", 1)[0]
    want = _WEARER_SIDE_IMAGE_HALF.get(side)
    if not want or "back" in placement:
        return rule, None
    x = float(rule["x_center_ratio"])
    wrong = (want == "right" and x < 0.5) or (want == "left" and x > 0.5)
    if not wrong:

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · scripts/edit_placement_rule.py (reported line 146)May include surrounding context.

python
side = placement.split("_", 1)[0]
    want = _WEARER_SIDE_IMAGE_HALF.get(side)
    if not want or "back" in placement:
        return rule, None
    x = float(rule["x_center_ratio"])
    wrong = (want == "right" and x < 0.5) or (want == "left" and x > 0.5)
    if not wrong:

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · scripts/edit_placement_rule.py (reported line 183)May include surrounding context.

python
side = placement.split("_", 1)[0]
    want = _WEARER_SIDE_IMAGE_HALF.get(side)
    if not want or "back" in placement:
        return rule, None
    x = float(rule["x_center_ratio"])
    wrong = (want == "right" and x < 0.5) or (want == "left" and x > 0.5)
    if not wrong:

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill declares broad operational capabilities including shell execution, filesystem reads/writes, environment-variable access, and network use, but does not constrain them with an explicit tool scope. In an agent setting, that increases blast radius: image-processing tasks can silently expand into package installation, persistent file mutation, remote HTTP calls, and uploads without policy-level guardrails.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
84% confidence
Finding

The skill is explicitly designed to persist outputs and state transitions: it seeds editable copies in a data directory, stores rendered artifacts, and drives decoration records toward 'done'. Persistent cross-session state is not inherently malicious, but in an agent environment it can create unauthorized durable changes, data retention issues, and hard-to-audit side effects if invoked without strong scoping and operator awareness.

Content

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

md
---
name: drivethru-graphic-artist
description: Graphic-artist tasks for Bacon & Co decorations — (1) generate product mockups by compositing a decoration (logo/graphic) onto a blank product photo (deterministic; no model-generated pixels; self-reviewed), (2) make a DTF decoration "production-ready" / "drop the art" — take the real thumbnail, size it to the decoration location, render at 300 DPI, upload the DTF production file, set size + colors, and create a print sample, driving the decoration toward the 'done' state via the drivethru_mcp decoration_* tools, and (3) clean up degraded / AI-generated flat art before production — deterministically snap it back to its true inks, rebuild faded/broken/jagged outlines, and re-render crisp at print size (fixes the "looks fine as a thumbnail, falls apart at 13 inches" problem). Use whenever the user wants to see a logo on a garment, place artwork on a blank, remove an image background (knock a solid color out of flat art, or segment a photographic subject), tune a print's size/position, clean up / fix / "drop for production" a low-quality or AI-generated logo (ghosting, haze, jagged or fading outlines, soft edges), OR make a decoration production-ready / drop art / get a DTF decoration to done.
version: 0.18.1
emoji: 🎨
metadata:

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This markdown file describes user feedback such as "bigger," "move it up," and "rotate it" as inputs to be translated into command deltas. These phrases are common everyday speech and the document does not define when they should be treated as skill-invocation feedback versus ordinary conversation, increasing the risk of unintended activation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

These instructions direct the agent to persistently modify catalog defaults via a local Python command, but they do not require an explicit warning that this changes shared configuration beyond the current task. In an agent setting, that can cause unintended long-lived state changes, allowing a casual approval like 'save that as default' to alter future behavior for other users or later jobs.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The file instructs the agent to add new categories or placements to persistent catalog data without warning the user that this creates durable configuration entries. That introduces a state-integrity risk: an ambiguous or mistaken request can expand shared production rules, potentially affecting later compositions and downstream production workflows.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
80% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · references/mockup_routine.md (reported line 105)May include surrounding context.

md
**When it's ambiguous — skip.** If you see two candidates for either role
and can't confidently pick, record `skipped: ambiguous_inputs` and move on;
a human will label them. **Don't guess and don't ask the user mid-run** —
the routine fires unattended.

**When either role has no candidate — skip.** Record

Unbounded Resource Access

Medium
Category
Excessive Agency
Confidence
75% confidence
Finding

Skill allows unbounded resource consumption (API calls, storage, compute). Without rate limits or quotas, a compromised or misbehaving agent can cause denial-of-service or cost overruns.

Content

Scanner excerpt · references/self_review.md (reported line 85)May include surrounding context.

md
it's clearly off. Don't stack more than two or three deltas in one attempt —
fix the biggest problem first.

## Stop conditions (don't loop forever)

- **Accept early.** "Good enough for a customer to approve" is the bar, not
  pixel perfection. If attempt 1 already looks right, return it — don't burn

Unbounded Resource Access

Medium
Category
Excessive Agency
Confidence
75% confidence
Finding

Skill allows unbounded resource consumption (API calls, storage, compute). Without rate limits or quotas, a compromised or misbehaving agent can cause denial-of-service or cost overruns.

Content

Scanner excerpt · scripts/_bootstrap.py (reported line 93)May include surrounding context.

python
it's clearly off. Don't stack more than two or three deltas in one attempt —
fix the biggest problem first.

## Stop conditions (don't loop forever)

- **Accept early.** "Good enough for a customer to approve" is the bar, not
  pixel perfection. If attempt 1 already looks right, return it — don't burn

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The routine depends on an external vision API to review generated mockups, but that capability is not clearly declared in the skill purpose. This can cause unexpected exfiltration of product imagery or derived commercial assets to a third party, and operators may not realize that external processing is part of the workflow.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
93% confidence
Finding

Using nohup ... & creates a detached process that persists beyond the active session and can continue making writes to external systems without active supervision. In an agent context, this weakens containment and accountability because execution can survive interruption, making it harder to stop, audit, or correlate with the original user request.

Content

Scanner excerpt · references/web_image_routine.md (reported line 80)May include surrounding context.

nothing until it ends. So start it in the background and poll it:

bash
nohup python3 scripts/web_mockup_job.py run --site-id <id> --limit 10 \
    > /dev/null 2>&1 &
# or specific products:  … run --product-tmpl-ids 24921,24920 …

Static analysis

No suspicious patterns detected.