T09 · Insecure Skill Coding Practices
- Location
scripts/generate_image.py:203- Finding
Unvalidated API-Controlled Image Output URLs Permit Client-Side SSRF
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This is a real Atlas Cloud API helper, but it broadly routes AI prompts and media to third-party services and its scripts trust remote output URLs too much.
Install only if you intend to use Atlas Cloud for AI generation and are comfortable sending prompts, media, and chat messages to that service. Avoid using it with secrets, regulated data, or private project context unless you have reviewed Atlas Cloud's data handling. Pin any MCP package version before use, and treat generated output downloads cautiously because the included scripts do not validate returned URLs.
scripts/generate_image.py:203Unvalidated API-Controlled Image Output URLs Permit Client-Side SSRF
scripts/generate_video.py:163Unvalidated API-Controlled Video Output URLs Permit Client-Side SSRF
references/image-gen.md:31Image Integration Template Fetches an Untrusted Dynamic Schema URL
references/models.md:101Model Reference Template Fetches API-Supplied Schema URLs Without Validation
The declared description presents a broad skill for image generation, video generation, and LLM chat through one unified Atlas Cloud API covering many providers and integration scenarios. The supplied code chunk only implements image-related functionality: listing Atlas image models, submitting/polling Atlas image generation jobs, uploading media to Atlas Cloud, and calling Google AI Studio's Gemini image generation endpoint. There is no video generation logic, no chat/LLM API logic, no general API integration layer, and no pricing comparison features beyond printing model prices in the image model list. The code's primary purpose is materially narrower than the description, so this is a mismatch.
The description claims a broad, multi-capability Atlas Cloud skill covering image generation, video generation, and LLM chat across many named model families/providers through one API. The actual code chunk implements only video-related operations against Atlas Cloud's own API endpoints. It can list models, upload local media, submit generateVideo requests, poll predictions, and download outputs. There is no code for image generation, image editing, LLM chat, OpenAI-compatible chat formatting, provider comparison, or broad API integration logic. While the video-generation portion is consistent with the declaration, the supplied code materially underdelivers relative to the declared scope, so the description does not accurately represent what this specific code chunk actually does.
The invocation guidance is extremely broad and tells the agent to consider this skill for many generic AI-related requests, even when Atlas Cloud is not mentioned. That raises the likelihood of over-triggering a networked skill that sends prompts and media to a third-party service, causing unnecessary data disclosure or steering users toward a commercial provider without explicit intent.
The atlas_chat MCP tool is described as sending chat completion requests, which creates a direct context-leakage path if the agent forwards conversation history, hidden instructions, or sensitive user data to the external provider. Given the skill's broad invocation guidance, this becomes more dangerous because the tool may be selected for generic requests where external transmission is not clearly intended.
| `atlas_get_model_info` | Get detailed API docs and schema for a model |
| `atlas_generate_image` | Submit image generation task |
| `atlas_generate_video` | Submit video generation task |
| `atlas_chat` | Send chat completion request |
| `atlas_get_prediction` | Check generation status and get results |
| `atlas_quick_generate` | One-step: auto-find model + generate |
The skill declares access to an environment secret and clearly instructs network use, but it does not define any explicit tool/permission scope to constrain those capabilities. In agent environments, this increases the chance that the skill can be invoked with broader-than-necessary access, including use of API secrets and outbound requests without clear guardrails.
This duplicated finding points to the concrete image-generation request example, which transmits prompt data and uses a secret-bearing authorization header. In a skill that may be auto-invoked, that can expose user content to an external processor and create privacy/compliance issues.
# Submit task
curl -s -X POST "https://api.atlascloud.ai/api/v1/model/generateImage" \
-H "Authorization: Bearer $ATLASCLOUD_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "bytedance/seedream-v5.0-lite", "prompt": "A cherry blossom garden", "size": "2048*2048"}'
This duplicated finding points to the concrete image-generation request example, which transmits prompt data and uses a secret-bearing authorization header. In a skill that may be auto-invoked, that can expose user content to an external processor and create privacy/compliance issues.
# Submit task
curl -s -X POST "https://api.atlascloud.ai/api/v1/model/generateImage" \
-H "Authorization: Bearer $ATLASCLOUD_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "bytedance/seedream-v5.0-lite", "prompt": "A cherry blossom garden", "size": "2048*2048"}'
Polling the prediction endpoint is part of the same external workflow and continues use of the API credential while retrieving hosted outputs. The danger is not the poll itself, but that it operationalizes third-party processing and access to externally hosted artifacts.
curl -s "https://api.atlascloud.ai/api/v1/model/prediction/{prediction_id}"
-H "Authorization: Bearer $ATLASCLOUD_API_KEY"
The video generation example sends user prompts to an external service and may result in externally hosted media artifacts. Because video prompts or source images can be sensitive, this creates a meaningful data-transfer and privacy risk if invoked without informed consent.
curl -s -X POST "https://api.atlascloud.ai/api/v1/model/generateVideo" \
-H "Authorization: Bearer $ATLASCLOUD_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "kwaivgi/kling-v3.0-std/text-to-video", "prompt": "A rocket launching", "duration": 5, "aspect_ratio": "16:9"}'
The OpenAI-compatible example directs chat content to Atlas Cloud by changing the SDK base URL, which can cause users to send conversational or proprietary content to a third party. In an agent setting, this is sensitive because chat payloads may include hidden context or user data if not carefully bounded.
client = OpenAI(
api_key="your-atlascloud-api-key",
base_url="https://api.atlascloud.ai/v1",
)
response = client.chat.completions.create(
model="qwen/qwen3.5-397b-a17b",
Referencing an MCP server via unpinned npx atlascloud-mcp allows whatever the latest published package version is at execution time. This creates a supply-chain risk where a compromised or malicious update could execute unexpected code or exfiltrate data in the host environment.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
"""
# Step 1: Submit generation task
payload = {"model": model, "prompt": prompt, **kwargs}
resp = requests.post(f"{BASE_URL}/model/generateImage", json=payload, headers=HEADERS, timeout=50)
resp.raise_for_status()
data = resp.json()
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
# Step 1: Submit generation task
The documentation provides complete examples for sending prompts and conversation messages to a third-party cloud API but never warns that user inputs, system prompts, and possibly sensitive business data are transmitted off-host. In an agent skill context, this omission can cause downstream developers or agents to forward secrets, PII, or confidential prompts to an external provider without informed consent or appropriate data handling controls.
The endpoint declaration alone establishes that the skill directs traffic to an external cloud API, which is relevant from a data flow and privacy perspective. On its own this line is lower impact than executable examples, but in context it contributes to undocumented third-party data transmission behavior.
## API Flow
LLM chat is **synchronous** (no polling needed):
- **Endpoint**: `POST https://api.atlascloud.ai/v1/chat/completions`
- Supports streaming via SSE (`"stream": true`)
## Parameters
The OpenAI SDK example configures a third-party base URL and then sends messages through it, enabling external processing of prompt data. Because the example is presented as recommended usage, the lack of security caveats makes accidental disclosure of sensitive content more likely.
client = OpenAI(
api_key=os.environ.get("ATLASCLOUD_API_KEY"),
base_url="https://api.atlascloud.ai/v1",
)
response = client.chat.completions.create(
The raw HTTP example serializes the full messages array into JSON and sends it to a remote endpoint with bearer authentication. This is not inherently malicious, but as documented it normalizes external transmission of arbitrary prompt content without any mention of privacy boundaries or restrictions on what may be sent.
ATLAS_API_KEY = os.environ.get("ATLASCLOUD_API_KEY")
response = requests.post(
"https://api.atlascloud.ai/v1/chat/completions",
headers={
"Authorization": f"Bearer {ATLAS_API_KEY}",
The raw HTTP example serializes the full messages array into JSON and sends it to a remote endpoint with bearer authentication. This is not inherently malicious, but as documented it normalizes external transmission of arbitrary prompt content without any mention of privacy boundaries or restrictions on what may be sent.
ATLAS_API_KEY = os.environ.get("ATLASCLOUD_API_KEY")
response = requests.post(
"https://api.atlascloud.ai/v1/chat/completions",
headers={
"Authorization": f"Bearer {ATLAS_API_KEY}",
This line is the concrete remote URL used for the POST request, confirming third-party transmission of the chat payload. In an agent skill, the danger is contextual: prompts may include system instructions, retrieved documents, or user secrets that should not be sent externally by default.
ATLAS_API_KEY = os.environ.get("ATLASCLOUD_API_KEY")
response = requests.post(
"https://api.atlascloud.ai/v1/chat/completions",
headers={
"Authorization": f"Bearer {ATLAS_API_KEY}",
"Content-Type": "application/json",
The Node/OpenAI client is explicitly pointed at Atlas Cloud, so any subsequent completion call routes conversation data to an external provider. This is expected functionality, but without any boundary warning it can mislead integrators into treating the service like a local library rather than a remote processor.
const client = new OpenAI({
apiKey: process.env.ATLASCLOUD_API_KEY,
baseURL: 'https://api.atlascloud.ai/v1',
});
const response = await client.chat.completions.create({
The fetch call at this location establishes direct outbound transmission of model input to a third-party domain. Because the file is a cookbook of copy-paste snippets, such examples can operationalize data egress without any accompanying privacy or compliance guardrails.
const response = await fetch('https://api.atlascloud.ai/v1/chat/completions', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.ATLASCLOUD_API_KEY}`,
The fetch call at this location establishes direct outbound transmission of model input to a third-party domain. Because the file is a cookbook of copy-paste snippets, such examples can operationalize data egress without any accompanying privacy or compliance guardrails.
const response = await fetch('https://api.atlascloud.ai/v1/chat/completions', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.ATLASCLOUD_API_KEY}`,
The streaming fetch snippet again transmits prompts externally, here in a pattern that developers may quickly embed into live applications. The risk is not the network call itself but the absent warning and controls around sending potentially sensitive conversation content to a cloud provider.
const response = await fetch('https://api.atlascloud.ai/v1/chat/completions', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.ATLASCLOUD_API_KEY}`,
The streaming fetch snippet again transmits prompts externally, here in a pattern that developers may quickly embed into live applications. The risk is not the network call itself but the absent warning and controls around sending potentially sensitive conversation content to a cloud provider.
const response = await fetch('https://api.atlascloud.ai/v1/chat/completions', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.ATLASCLOUD_API_KEY}`,
The cURL example is a ready-to-run external transmission template that encourages sending prompts directly to a cloud service from the command line. This is risky in practice because shell history, logs, and copied examples can expose both API usage patterns and sensitive prompt contents to systems outside the user's control.
---
## cURL
### Basic Request
No suspicious patterns detected.