Back to skill

Security audit

九马AI免费图生视频

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly a coherent Jiuma image-to-video integration, but it persists an account API key in a predictable plaintext local file without enforcing private permissions.

Install only if you are comfortable sending images and prompts to Jiuma and storing a Jiuma API key locally. Prefer running it in a private workspace, avoid private images, restrict permissions on the .jiuma credential file yourself, and delete or rotate the key if the workspace is shared, backed up, or exposed.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (3)

T09 · Insecure Skill Coding Practices

Warning
Location
utils.py:82
Finding

API Key Stored Without Enforced Restrictive File Permissions

Content
View full analysis

Vulnerability Details

File Location: utils.py:6-8 and utils.py:82-84
Vulnerability Type: Plaintext credential storage with unsafe default permissions
Risk Level: Medium

Vulnerable Code

python
JIUMA_API_KEY_SAVE_DIR = f"{os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))}/.jiuma"
os.makedirs(JIUMA_API_KEY_SAVE_DIR, exist_ok=True)
JIUMA_API_KEY_SAVE_PATH = f"{JIUMA_API_KEY_SAVE_DIR}/jiuma_api_key"
python
def save_jiuma_api_key(api_key):
    with open(JIUMA_API_KEY_SAVE_PATH, "w") as f:
        f.write(api_key)

Technical Analysis

The Skill stores the Jiuma API key as plaintext in a predictable file but does not explicitly restrict the permissions of either the containing directory or the credential file. The effective permissions therefore depend on the process umask.

With common default settings, the directory may be created with mode 0755 and the file with mode 0644. On a multi-user system, this can make the API key readable by other local accounts. This also conflicts with the documentation's assertion that only the current user can read the key.

The code additionally opens a predictable path without explicitly rejecting symbolic links or using an atomic, exclusive file creation operation. If an attacker can modify the containing directory, this may permit redirection of the credential write.

Attack Path

  1. A user completes the Jiuma QR-code login process.
  2. login.py receives the user's secret_key and passes it to save_jiuma_api_key.
  3. utils.py writes the key to .jiuma/jiuma_api_key using permissions derived from the current umask.
  4. Another local user or compromised process locates the predictable credential file.
  5. If the resulting permissions allow access, the attacker reads the plaintext API key.
  6. The attacker submits authenticated requests to Jiuma using the stolen X-Secret-Key value.

Exploitation require ...[truncated 623 chars]

Remediation
View remediation

Remediation Suggestions

  • Create the credential directory with mode 0700.
  • Create the credential file atomically with mode 0600, rather than relying on the process umask.
  • Apply restrictive permissions to existing directories and files during migration.
  • Reject symbolic links and other unexpected file types before reading or writing the credential.
  • Use atomic replacement to avoid partially written credential files.
  • Prefer an operating-system credential store or keyring instead of a plaintext file where available.
  • Avoid suppressing all credential-read exceptions; distinguish missing files from permission and integrity failures.
  • Ensure the documented storage path and permission guarantees match the implementation.

Example hardening pattern:

python
os.makedirs(JIUMA_API_KEY_SAVE_DIR, mode=0o700, exist_ok=True)
os.chmod(JIUMA_API_KEY_SAVE_DIR, 0o700)

flags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC
if hasattr(os, "O_NOFOLLOW"):
    flags |= os.O_NOFOLLOW

fd = os.open(JIUMA_API_KEY_SAVE_PATH, flags, 0o600)
try:
    os.fchmod(fd, 0o600)
    with os.fdopen(fd, "w") as f:
        f.write(api_key)
except Exception:
    os.close(fd)
    raise

T09 · Insecure Skill Coding Practices

Note
Location
login.py:25
Finding

Temporary Login Token Exposed Through URL Query String and Command-Line Arguments

Content
View full analysis

Vulnerability Details

File Location: login.py:25-29; documented invocation at SKILL.md:13-15, SKILL.md:257-267, and LOGIN.md:24-28
Vulnerability Type: Sensitive authentication token exposure
Risk Level: Low

Vulnerable Code

python
def check_login_status(access_token):
    data, message = jiuma_request(f"{CHECK_API}?rand_string={access_token}")
    if not data:
        return
    save_jiuma_api_key(data["secret_key"])

The documented invocation also supplies the token as a command-line argument:

bash
python3 login.py --check --access_token "<your_token>"

Technical Analysis

The temporary login token is supplied on the command line and then interpolated into the query string of an HTTPS URL.

Command-line arguments may be exposed through shell history, process inspection, monitoring agents, crash reports, terminal logs, or automation logs. Query-string values may be retained by HTTP server access logs, reverse proxies, observability systems, and diagnostic tooling even when HTTPS protects the request in transit.

The token is security-sensitive because the corresponding status endpoint returns secret_key, which the client immediately stores as the user's API key. The exact exploitability depends on server-side controls that are not present in the audited project, including token expiration, single-use enforcement, and binding to the initiating client or login session.

Attack Path

  1. A user runs the documented command with the temporary login token in --access_token.
  2. The token is retained in shell history, exposed in a process listing, or captured by local monitoring.
  3. The client also sends the token as rand_string in the URL query string.
  4. A reverse proxy, application server, or telemetry platform records the complete URL.
  5. An attacker with access to one of these local or server-side records obtains the token before it expires.
  6. The attacker s ...[truncated 737 chars]
Remediation
View remediation

Remediation Suggestions

  • Do not place authentication tokens in URL query strings.
  • Send the token in the HTTPS POST body or an authorization header.
  • Avoid accepting secrets directly as command-line arguments.
  • Read the token from protected standard input, an interactive secret prompt, or another channel that does not expose it in process listings.
  • Configure shell examples so that users are not encouraged to persist tokens in command history.
  • Make login tokens short-lived, cryptographically random, single-use, and bound to the initiating login session.
  • Invalidate a token immediately after the API key is retrieved.
  • Redact query strings, authentication headers, and login tokens from application, proxy, and observability logs.
  • Return the API key only after strict server-side verification of the completed login session.

T08 · Insecure Dependencies

Note
Location
LOGIN.md:12
Finding

Unpinned Dependency Installation and Unverified Mutable Update Source

Content
View full analysis

Vulnerability Details

File Location: LOGIN.md:12-16, SKILL.md:197-200, and SKILL.md:364-372
Vulnerability Type: Insecure dependency and update process
Risk Level: Low

Vulnerable Instructions

bash
pip install requests

The update instructions direct users to retrieve the latest executable source from a mutable URL:

text
https://clawhub.ai/dddcn1/jiuma-free-image2video

Technical Analysis

The installation instructions do not pin requests to a reviewed version and do not provide package hashes. As a result, different installations may resolve different dependency versions, making builds non-reproducible and preventing users from verifying that they installed the audited dependency artifact.

The update procedure similarly instructs users to replace executable Python code from a mutable latest-version source without requiring a version identifier, checksum, signature, or signed manifest. A compromise of the package index, publishing account, distribution site, or artifact could therefore cause users to execute code that differs from the reviewed project.

The repository does not itself automatically download and execute a remote payload. The risk arises from the documented installation and update procedure, so this is classified as an insecure supply-chain practice rather than confirmed remote payload execution.

Attack Path

  1. An attacker compromises a dependency-distribution channel, publishing account, or Skill update source.
  2. The attacker replaces a future dependency or Skill release with a modified artifact.
  3. A user follows the documentation and installs the unpinned package or downloads the mutable latest version.
  4. No hash or signature verification detects the substitution.
  5. The modified Python code executes with the user's operating-system permissions.
  6. The malicious update could access local files available to that user, including the stored Jiuma API ...[truncated 660 chars]
Remediation
View remediation

Remediation Suggestions

  • Pin requests to a reviewed, supported version.
  • Provide a lock file or requirements file containing cryptographic hashes.
  • Install dependencies with hash verification enabled, such as pip install --require-hashes.
  • Publish immutable, versioned Skill releases rather than directing users to an unspecified latest artifact.
  • Publish a SHA-256 digest or signed manifest for each release.
  • Verify the artifact signature or digest before replacing executable files.
  • Document the expected release version and provenance.
  • Protect publishing accounts with strong multi-factor authentication and restricted release permissions.
  • Re-audit code changes before recommending an updated release.
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 (14)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The skill is presented as an image-to-video generator, but the documentation also instructs the agent to perform QR-based login, poll authentication status, retrieve access tokens, and save API credentials locally. That is a material expansion of behavior into authentication and secret handling, which can expose users to credential misuse, unexpected account linkage, and unsafe secret storage if the agent executes these flows without clear consent and isolation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The file forces a specific language for all instructions and warnings, which can violate a language/locale policy when no user opt-in or explicit regional limitation is provided. There is no indication that this skill is intended only for Chinese-speaking users or a China-specific compliance context.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill documentation describes capabilities that include local file access, saving API keys locally, and network communication, but it does not declare any tool scope or permission boundaries. In an agent environment, missing explicit permissions increases the risk of overbroad execution and makes it harder to constrain or audit sensitive operations such as reading images, writing credentials, or calling external services.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The activation condition says the skill should be used whenever a user wants to convert images into video, which is broad for a skill that also performs external API calls, optional remote URL handling, and login/API-key acquisition. Overbroad routing can cause the agent to invoke this skill in situations where a safer local or non-authenticated option would be more appropriate, increasing the chance of unintended data disclosure or credential-related side effects.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
92% confidence
Finding

The skill is explicitly configured to transmit data to an external domain, and that transmission includes prompts and potentially local image files. In this skill context, that is expected functionality, but it still creates a real privacy and data-handling risk if users are not clearly informed that their content leaves the local environment.

Content

Scanner excerpt · agent.py (reported line 11)May include surrounding context.

python
from pathlib import Path
from utils import get_jiuma_api_key, jiuma_request, output_result

SUBMIT_API = "https://api.jiuma.com/api/imageVideo/add"
CHECK_STATUS_API = "https://api.jiuma.com/api/imageVideo/status"

MIME_MAP = {

External Transmission

Medium
Category
Data Exfiltration
Confidence
92% confidence
Finding

The status-check endpoint is also an external transmission path to the same third-party service. Although lower sensitivity than image upload, it still reveals task identifiers and usage metadata to an outside system and reinforces that the skill depends on remote processing.

Content

Scanner excerpt · agent.py (reported line 12)May include surrounding context.

python
from utils import get_jiuma_api_key, jiuma_request, output_result

SUBMIT_API = "https://api.jiuma.com/api/imageVideo/add"
CHECK_STATUS_API = "https://api.jiuma.com/api/imageVideo/status"

MIME_MAP = {
    # 图片

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill sends user-provided prompt text and image content to a third-party API, which may expose sensitive user data if the user believes processing is local. In an agent-skill context, this is more dangerous because users may supply private images or confidential prompts without realizing they will be transmitted off-platform.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · login.py (reported line 5)May include surrounding context.

python
from utils import jiuma_request, output_result, save_jiuma_api_key

LOGIN_API = "https://api.jiuma.com/user/getLoginQrcode"
CHECK_API = "https://api.jiuma.com/user/checkLoginStatus"

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · login.py (reported line 6)May include surrounding context.

python
from utils import jiuma_request, output_result, save_jiuma_api_key

LOGIN_API = "https://api.jiuma.com/user/getLoginQrcode"
CHECK_API = "https://api.jiuma.com/user/checkLoginStatus"

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The manifest describes a skill for generating videos from images via the Jiuma AI API, but this file implements user login, login-status polling, and retrieval/persistence of an API key. Authentication may support the broader integration, but it is not part of the user-facing purpose described in the manifest and represents materially different behavior.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The code saves the returned secret_key via save_jiuma_api_key() immediately after checking login status, without any explicit user confirmation, warning about persistence, or indication of where/how the credential will be stored. Persisting API credentials silently increases the risk of unintended long-term access, credential exposure through local storage, or user surprise about retained authentication state.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The code persists the Jiuma API key in plaintext to a predictable path under the project directory with no access control, encryption, or user disclosure. On multi-user systems, shared workspaces, container volumes, or when the skill directory is copied, backed up, or logged, this can expose the credential and allow unauthorized use of the external API.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The script retrieves an API secret via get_jiuma_api_key() and uses it in request headers, but there is no visible comment, docstring, or user-facing note explaining that the skill depends on and will use credentials. For safety auditing, credential access should be disclosed somewhere in the code or skill documentation.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
97% confidence
Finding

The help text states '生成的图片URL可以直接在浏览器中打开下载' and earlier error text says 'API未返回图片URL', which contradicts the implemented behavior of this skill: it submits image-to-video jobs and returns video_url on success. This is an intent/documentation mismatch that could mislead users about the artifact being produced.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.