other
- Location
scripts/image_gen_compare.py:40- Finding
Generated Images Are Silently Written to Cloud-Synchronized Storage
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This image-comparison skill mostly does what it says, but it can silently save generated images to a Proton Drive-synced folder and uses a 1Password service-token fallback that is broader than the user-facing instructions make clear.
Review before installing. Use it only with prompts and generated images you are comfortable sending to OpenAI and potentially storing in a synced Proton Drive folder. Prefer setting OPENAI_API_KEY directly, avoid running it in an environment full of unrelated secrets, and inspect or change the output directory before using confidential creative work.
scripts/image_gen_compare.py:40Generated Images Are Silently Written to Cloud-Synchronized Storage
scripts/image_gen_compare.py:61Security-Sensitive Credential Helper Inherits the Entire Process Environment
scripts/image_gen_compare.py:145Unpinned Python Dependencies and Mutable Runtime Model Downloads
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
print(f"\n🎨 DALL-E 3 ({quality}, {DALLE_W}×{DALLE_H}, ~${cost:.2f})...")
start = time.monotonic()
resp = requests.post(
"https://api.openai.com/v1/images/generations",
headers={"Authorization": f"Bearer {key}", "Content-Type": "application/json"},
json={
The documented behavior does not fully match the skill's effective capabilities: it can access a 1Password service-account token to retrieve secrets and may write outputs into a synced storage location, neither of which are clearly disclosed in the primary description. This creates a trust and review gap where users may authorize a seemingly simple image-comparison skill without realizing it can handle secrets and persist generated content to broader storage destinations.
The code intentionally writes generated images to a Proton Drive-synced directory when present, causing automatic replication of user prompts' outputs outside the local workspace. In the context of a model-comparison utility, this is an unnecessary externalization channel that can leak sensitive or proprietary generated content.
Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.
return key
try:
token_path = Path.home() / ".config/openclaw/.op-service-token"
env = os.environ.copy()
env["OP_SERVICE_ACCOUNT_TOKEN"] = token_path.read_text().strip()
result = subprocess.run(
["op", "read", "op://OpenClaw/OpenAI API Key/credential"],
The skill declares significant capabilities in metadata and usage patterns—environment variable access, network access, shell execution, and file read/write—but does not define an explicit tool scope such as permissions or allowed-tools. This weakens the security boundary by making it harder for reviewers and enforcement systems to verify that the skill only uses the minimum necessary privileges.
The script documentation says outputs are saved under the workspace, but the code may instead write generated images to a Proton Drive-synced path outside the workspace. This hidden data egress/storage behavior increases the risk of unintentionally exposing prompts and generated artifacts to synced cloud storage.
The skill reaches beyond simple image generation by reading a local service-account token file and invoking the 1Password CLI to retrieve a secret. That secret access pattern expands the skill's privilege footprint and is not obvious from the high-level description, increasing the risk of unintended credential use in automated environments.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
token_path = Path.home() / ".config/openclaw/.op-service-token"
env = os.environ.copy()
env["OP_SERVICE_ACCOUNT_TOKEN"] = token_path.read_text().strip()
result = subprocess.run(
["op", "read", "op://OpenClaw/OpenAI API Key/credential"],
capture_output=True, text=True, env=env, timeout=10,
)
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
print(f"\n🎨 DALL-E 3 ({quality}, {DALLE_W}×{DALLE_H}, ~${cost:.2f})...")
start = time.monotonic()
resp = requests.post(
"https://api.openai.com/v1/images/generations",
headers={"Authorization": f"Bearer {key}", "Content-Type": "application/json"},
json={
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
print(f"\n🎨 DALL-E 3 ({quality}, {DALLE_W}×{DALLE_H}, ~${cost:.2f})...")
start = time.monotonic()
resp = requests.post(
"https://api.openai.com/v1/images/generations",
headers={"Authorization": f"Bearer {key}", "Content-Type": "application/json"},
json={
User-supplied prompt text is sent to OpenAI, but the script does not provide an explicit runtime warning or consent mechanism about external data sharing. In a comparison tool that may be used with proprietary creative briefs or internal prompts, this omission increases the risk of accidental disclosure.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
start = time.monotonic()
resp = requests.post(
"https://api.openai.com/v1/images/generations",
headers={"Authorization": f"Bearer {key}", "Content-Type": "application/json"},
json={
"model": "dall-e-3",
The code performs a second network fetch against a URL returned by a remote service without validating the hostname, scheme, or content type. If the upstream response were compromised or unexpectedly changed, this could enable unintended outbound requests (SSRF-like behavior) or download of untrusted content into local/cloud-synced storage.
filename = f"dalle3_{quality}_{ts}.png"
dest = OUTPUT_DIR / filename
img_resp = requests.get(image_url, timeout=30)
dest.write_bytes(img_resp.content)
result = {
The manifest description frames the skill around comparing specific paid and local models, explicitly naming DALL-E 3, FLUX.1-schnell, Gemini Imagen, and others. In the code, an additional SDXL generator is implemented, while no Gemini Imagen integration exists anywhere in the file, so the actual supported model set diverges from the stated description.
The skill description says it logs metadata and stores run history, but does not clearly warn users that generated images and associated metadata will be retained. In this context, prompts and outputs may contain sensitive or proprietary material, so undisclosed persistence increases privacy and data-handling risk.
No suspicious patterns detected.