T09 · Insecure Skill Coding Practices
- Location
scripts/ima_video_create.py:174- Finding
API Credential Exposed in URL Query Parameters
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This appears to be a real IMA video-generation skill, but it needs review because API keys and media can be sent through unsafe or overly configurable network paths.
Install only if you trust the publisher and are comfortable sending prompts, task data, and local images to IMA services. Use a limited-scope IMA API key if available, avoid running with untrusted command arguments or environment variables, do not set --base-url or IMA_IM_BASE_URL outside trusted IMA endpoints, and review local logs/preferences on shared machines.
scripts/ima_video_create.py:174API Credential Exposed in URL Query Parameters
scripts/ima_video_create.py:1688Configurable Endpoints Permit Credential and Media Redirection
scripts/ima_logger.py:35Sensitive Operational Files Lack Explicit Restrictive Permissions
requirements.txt:4Dependency Version Is Open-Ended and Lacks Integrity Pinning
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
f"Please check your creation record at {VIDEO_RECORDS_URL}."
)
resp = requests.post(url, json={"task_id": task_id},
headers=headers, timeout=30)
resp.raise_for_status()
data = resp.json()
This code chunk does not implement the declared media-generation behavior. Instead, it provides infrastructure for logging: creating and rotating log files, emitting console/file logs, and deleting old logs from a local directory. Logging can be a supporting component of a generation skill, but this chunk by itself is materially different from the declared purpose and shows none of the core capabilities described. Therefore, the description does not accurately represent what this supplied code chunk actually does.
The core purpose matches closely: this is an IMA video creation client with the four declared workflows, two exposed Sevio models via aliasing, the same general flow (product list → param resolution → task create → polling), and a reflection-based retry mechanism. The mismatch arises because the description and declared permissions omit materially relevant behaviors: the script persists user preference memory locally, creates local log files, and interacts with an additional upload service domain for local image workflows, explicitly sending the API key to that service and uploading image content. Those are resource/access behaviors not represented in the declaration, so this should be flagged as a description-behavior mismatch.
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
sys.exit(1)
args.model_id = normalized_model_id
# Get API key from args or environment variable
apikey = args.api_key or os.getenv("IMA_API_KEY")
if not apikey:
logger.error("API key is required. Use --api-key or set IMA_API_KEY environment variable")
The skill declares environment access, persistent file writes, and network use in behavior, but does not define an explicit tool scope such as allowed-tools/permissions. That creates an authorization ambiguity where a host may grant broader capabilities than reviewers or users expect, especially given the skill can exfiltrate prompts, media, and API keys to external services.
This file contains substantial user-facing capability descriptions in Chinese, while other sections are in English, and it does not state that the user can choose their preferred language. That creates a language/locale policy concern because the skill appears to default part of its interaction content to a specific language without explicit user opt-in.
The skill sends user prompts, model parameters, task metadata, and an Authorization bearer token to an external service to create generation tasks. External transmission is expected for a cloud generation skill, but it remains security-relevant because sensitive user content and credentials leave the local trust boundary and could be exposed if endpoints, transport, logging, or consent are mishandled.
}],
}
r = requests.post(f"{BASE_URL}/open/v1/tasks/create", headers=HEADERS, json=payload)
r.raise_for_status()
return r.json()["data"]["id"]
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
def poll(task_id: str, interval: int = 8, timeout: int = 600) -> dict:
deadline = time.time() + timeout
while time.time() < deadline:
r = requests.post(f"{BASE_URL}/open/v1/tasks/detail", headers=HEADERS, json={"task_id": task_id})
r.raise_for_status()
task = r.json().get("data", {})
medias = task.get("medias", [])
The script sends prompts, model parameters, image URLs, and potentially uploaded local-image-derived CDN URLs to external services. This is inherent to the skill’s purpose, but it is still a real data-transmission risk because users may provide sensitive prompts or local files, and the code also forwards the API key to a separate upload domain during related workflows.
f"credit={credit}, attribute_id={attribute_id}")
try:
resp = requests.post(url, json=payload, headers=headers, timeout=30)
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.
f"Please check your creation record at {VIDEO_RECORDS_URL}."
)
resp = requests.post(url, json={"task_id": task_id},
headers=headers, timeout=30)
resp.raise_for_status()
data = resp.json()
The metadata description states the skill’s capabilities but does not define clear invocation boundaries, allowed contexts, or trigger constraints. This can cause the agent to invoke a powerful media-generation skill too broadly or in unintended situations, increasing the chance of misuse, cost exposure, or unsafe handling of user-supplied generation requests.
The dependency is specified as requests>=2.25.0, which allows installation of many different versions over time and prevents reproducible builds. This increases supply-chain risk and makes it harder to ensure that a known-safe version is used, especially because some allowed versions may contain disclosed vulnerabilities.
# Python dependencies for ima-video-ai skill
# Install with: pip install -r requirements.txt
requests>=2.25.0
Because the manifest does not pin requests to a specific version, there is no way to verify whether deployments will use a release affected by one of the package's known advisories. In a skill that likely performs outbound API calls using requests, this uncertainty is more relevant because vulnerable HTTP client behavior could affect authentication, redirects, or credential handling depending on runtime usage.
This code performs file deletion via cleanup_old_logs by unlinking matching log files older than the retention window. Although the module docstrings describe retention behavior, there is no runtime disclosure, logging, or confirmation around the destructive deletion step itself.
The header builder hard-codes language="en" and sends x_app_language on requests by default. This imposes a specific language/locale choice unless the caller explicitly overrides it, which is a natural-language locale policy concern.
The script stores per-user model preferences in ~/.openclaw/memory/ima_prefs.json without any mention in the stated skill purpose. While the stored data is limited, persistent local storage can create privacy and multi-user data separation issues, especially on shared systems or agent hosts where different users may access the same filesystem.
No suspicious patterns detected.