Back to skill

Security audit

Seedream 5.0 — AI Image Generation & Editing by ByteDance

Security checks for vulnerabilities and agentic risk

Overview

This image skill is purpose-adjacent but should go to Review because its broad activation, generic model control, paid external API use, and unrestricted local-file upload are not tightly scoped.

Install only if you intentionally want Atlas Cloud handling your image prompts and photos and understand API usage may bill your account. Avoid using it with confidential prompts, private images, or arbitrary local paths unless you have reviewed the exact file and destination; prefer sandboxed output directories and explicit user confirmation for uploads, batch edits, and non-Seedream model choices.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/generate_image.py:184
Finding
Unrestricted Local File Upload to External Service<![CDATA[ ## Vulnerability Details **File Location**: `scripts/generate_image.py`, lines 184–218 **Vulnerability Type**: Missing file-type, size, and path validation before external upload **Risk Level**: Medium ### Vulnerable Code ```python def upload_file(file_path): if not os.path.exists(file_path): print(f"Error: File not found: {file_path}", file=sys.stderr) sys.exit(1) url = f"{API_BASE}/model/uploadMedia" filename = os.path.basename(file_path) boundary = f"----AtlasCloudBoundary{int(time.time() * 1000)}" with open(file_path, "rb") as f: file_data = f.read() body = b"" body += f"--{boundary}\r\n".encode() body += f'Content-Disposition: form-data; name="file"; filename="{filename}"\r\n'.encode() body += b"Content-Type: application/octet-stream\r\n\r\n" body += file_data body += f"\r\n--{boundary}--\r\n".encode() headers = { "Authorization": f"Bearer {get_api_key()}", "Content-Type": f"multipart/form-data; boundary={boundary}", "User-Agent": "AtlasCloud-Skill/1.0", } req = urllib.request.Request(url, data=body, headers=headers, method="POST") try: with urllib.request.urlopen(req, timeout=120) as resp: result = json.loads(resp.read().decode("utf-8")) ``` ### Technical Analysis The `upload` command is intended to upload a local image for image editing. However, `upload_file()` accepts any existing filesystem path and does not verify that the path refers to a regular image file. The implementation lacks: - Image file-signature validation. - An allowlist of supported image formats. - A maximum upload size. - Rejection of symbolic links or non-regular files. - Restriction to an approved working directory. - Explicit confirmation identifying the file and external destination. - Streaming upload behavior. The supplied file is read completely into memory and transmitted to `https://api.atlascloud.ai/api/v1/model/uploadMedia`. La ...[truncated 1626 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Resolve the supplied path to a canonical path and require it to be inside an explicitly approved input directory. 2. Require a regular file and reject directories, devices, FIFOs, and symbolic links: ```python resolved = os.path.realpath(file_path) if not os.path.isfile(resolved) or os.path.islink(file_path): raise ValueError("Only regular, non-symbolic-link image files are allowed") ``` 3. Enforce a conservative maximum file size before reading or uploading the file. 4. Validate supported image formats using file signatures rather than trusting extensions. 5. Decode the image with a maintained image parser where available to ensure that it is structurally valid. 6. Use the detected image MIME type instead of unconditional `application/octet-stream`. 7. Display the canonical path, file size, and destination and require explicit user approval before transmission. 8. Stream the multipart body in bounded chunks instead of loading the entire file into memory. 9. Document the provider's retention and access behavior for uploaded image bytes and filenames. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/generate_image.py:162
Finding
Unvalidated API-Controlled Output URL Download<![CDATA[ ## Vulnerability Details **File Location**: `scripts/generate_image.py`, lines 162–181; download invocation at lines 308–309 **Vulnerability Type**: Unrestricted URL retrieval and unbounded file download **Risk Level**: Medium ### Vulnerable Code ```python def download(url, output_dir="."): parsed = urllib.parse.urlparse(url) filename = os.path.basename(parsed.path) if not filename or "." not in filename: filename = f"output_{int(time.time())}.png" output_path = os.path.join(output_dir, filename) base, ext = os.path.splitext(output_path) counter = 1 while os.path.exists(output_path): output_path = f"{base}_{counter}{ext}" counter += 1 print(f"Downloading: {filename}") urllib.request.urlretrieve(url, output_path) size_kb = os.path.getsize(output_path) / 1024 print(f"Saved: {output_path} ({size_kb:.1f} KB)") return output_path ``` The function is called for every URL returned in the API response: ```python saved = [] for url in outputs: saved.append(download(url, args.output)) ``` ### Technical Analysis The authenticated Atlas Cloud prediction response controls the entries in `data.outputs`. Each entry is passed directly to `urllib.request.urlretrieve()` without validating its scheme, hostname, port, redirect destination, response size, content type, or actual file format. Consequently, the client trusts the remote service to select subsequent network destinations. The function also lacks an explicit timeout and reads the response into a local file without enforcing a maximum size. A URL-derived filename extension is treated as sufficient even though it does not prove that the content is an image. Normal image generation necessarily requires downloading generated output. Nevertheless, unrestricted URL retrieval is broader than necessary and creates a trust-boundary flaw if the service, service account, response path, or upstream infrastructure is compromised. ### Attac ...[truncated 1615 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Parse each output URL and permit only the `https` scheme. 2. Reject embedded credentials, unexpected ports, malformed hosts, and non-public destinations. 3. Maintain an allowlist of documented Atlas Cloud output or CDN hosts. If hosts are dynamic, obtain and validate an authoritative host policy from the provider. 4. Disable automatic redirects or validate the scheme and destination again after every redirect. 5. Replace `urlretrieve()` with a streamed request using an explicit connection/read timeout. 6. Check `Content-Length` when present and enforce a hard byte limit while streaming, regardless of whether that header exists. 7. Write to a temporary partial file and atomically rename it only after successful validation. 8. Verify response MIME type and image magic bytes before retaining the file. 9. Optionally decode the image and enforce maximum pixel dimensions to mitigate decompression-bomb risks. 10. Delete partial files when validation, timeout, or size checks fail. 11. Generate local filenames independently rather than trusting names or extensions derived from remote URLs. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (10)

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding
The documented behavior materially overstates and misstates what the skill actually does, including claimed Seedream-specific constraints while apparently permitting arbitrary model selection, uploads, and other undeclared behavior. Security-relevant mismatches like these are dangerous because operators and users may trust the skill with data under false assumptions about destination, scope, pricing, model restrictions, and processing behavior.

Vague Triggers

High
Confidence
95% confidence
Finding
The trigger text is extremely broad and is designed to activate for a wide range of common creative or marketing requests, not just explicit Seedream use. In a skill that sends prompts and image URLs to an external paid API using a bearer key, overbroad invocation increases the risk of accidental activation, unnecessary disclosure of user content to a third party, and unintended billing.

Lp3

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding
The skill declares access to an API key and documents network calls, but does not define an explicit tool scope such as permissions or allowed-tools. That creates an authorization/containment gap where a skill that can send prompts, image URLs, and bearer-authenticated requests externally is not constrained by least-privilege policy, increasing the chance of unintended data exfiltration or misuse.

External Transmission

Medium
Category
Data Exfiltration
Content
```bash
# Step 1: Submit
curl -s -X POST "https://api.atlascloud.ai/api/v1/model/generateImage" \
  -H "Authorization: Bearer $ATLASCLOUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
Confidence
95% confidence
Finding
This skill explicitly transmits user prompts and authenticated requests to an external service, and the surrounding documentation states that image URLs may also be sent. External transmission is expected for this type of skill, but it is still security-relevant because sensitive prompts, private image references, and account-linked API usage leave the local trust boundary.

External Transmission

Medium
Category
Data Exfiltration
Content
```bash
# Step 1: Submit
curl -s -X POST "https://api.atlascloud.ai/api/v1/model/generateImage" \
  -H "Authorization: Bearer $ATLASCLOUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
Confidence
95% confidence
Finding
This skill explicitly transmits user prompts and authenticated requests to an external service, and the surrounding documentation states that image URLs may also be sent. External transmission is expected for this type of skill, but it is still security-relevant because sensitive prompts, private image references, and account-linked API usage leave the local trust boundary.

External Transmission

Medium
Category
Data Exfiltration
Content
### Image Editing Example (v5.0 Lite)

```bash
curl -s -X POST "https://api.atlascloud.ai/api/v1/model/generateImage" \
  -H "Authorization: Bearer $ATLASCLOUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
Confidence
94% confidence
Finding
The image-editing example sends image references to a third-party API, which is more sensitive than text-only generation because source images may contain personal, proprietary, or confidential content. In this skill context, editing user-supplied photos materially increases privacy and data-governance risk, especially because uploads/local image handling are also described elsewhere.

External Transmission

Medium
Category
Data Exfiltration
Content
### Batch Sequential Editing Example

```bash
curl -s -X POST "https://api.atlascloud.ai/api/v1/model/generateImage" \
  -H "Authorization: Bearer $ATLASCLOUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
Confidence
90% confidence
Finding
Batch sequential editing combines two risk amplifiers: transmission of user images to a third party and the ability to process multiple images in one request. That raises the potential volume of sensitive data exposed in a single action and can magnify both privacy impact and unintended paid usage if triggered incorrectly.

External Transmission

Medium
Category
Data Exfiltration
Content
import urllib.error
import urllib.parse

API_BASE = "https://api.atlascloud.ai/api/v1"


def get_api_key():
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
import urllib.error
import urllib.parse

API_BASE = "https://api.atlascloud.ai/api/v1"


def get_api_key():
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
import urllib.error
import urllib.parse

API_BASE = "https://api.atlascloud.ai/api/v1"


def get_api_key():
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Static analysis

No suspicious patterns detected.