Back to skill

Security audit

Bona Movie Production

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its image and video generation purpose, but its client can send API keys, bearer tokens, prompts, and media references to arbitrary overridden endpoints.

Install only if you trust this publisher and the Bona service with your prompts, media links, and API credentials. Do not use --base-url or --login-url unless they are restricted to a trusted HTTPS Bona endpoint, and avoid submitting confidential production media until the credential and data-transmission disclosures are tightened.

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

Error
Location
scripts/bona_movie_production.py:189
Finding

Credential Disclosure Through Unrestricted API Endpoint Overrides

Content
View full analysis
str: if not self.api_key: raise RuntimeError("api_key is required for login") response = requests.post( self.login_url, headers={"Content-Type": "application/json"}, json={"accessKey": self.api_key}, timeout=self.timeout, ) payload = self._parse_response(response) data = payload.get("data") if isinstance(payload, dict) else None access_token = data.get("access_token") if isinstance(data, dict) else None if not access_token: raise RuntimeError( f"login response missing access_token: {json.dumps(payload, ensure_ascii=False, indent=2)}") return str(access_token) def _get_access_token(self) -> str: if not self._access_token: self._access_token = self._login() return self._access_token @property def headers(self) -> Dict[str, str]: return { "Content-Type": "application/json", "Authorization": f"Bearer {self._get_access_token()}", "Clientid": "e5cd7e4891bf95d1d19206ce24a7b32e", } def create_image_task(self, payload: Dict[str, Any]) -> Dict[str, Any]: response = requests.post(f"{self.base_url}/image", headers=self.headers, json=payload, timeout=self.timeout) return self._parse_response(response) def create_video_task(self, payload: Dict[str, Any]) -> Dict[str, Any]: response = requests.post(f"{self.base_url}/video", headers=self.headers, json=payload, timeout=self.timeout) return self._parse_response(response) def query_task( self, task_id: str, thread_id: Optional[str] = None, model_name: Optional[str] = None, ) -> Dict[str, Any]: params: Dict[str, str] = {} if thread_id: params["thread_id"] = th ...[truncated 3310 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
scripts/bona_movie_production.py:17
Finding

Incorrect Task Status Mapping Causes Premature Completion and Polling Denial of Service

Content
View full analysis
Dict[str, Any]: deadline = time.time() + max_wait last: Optional[Dict[str, Any]] = None while time.time() <= deadline: last = self.query_task( task_id=task_id, thread_id=thread_id, model_name=model_name, ) status = extract_status(last) if status in SUCCESS_STATUSES or status in FAILED_STATUSES: return last time.sleep(poll_interval) raise TimeoutError( f"task {task_id} did not finish within {max_wait} seconds" ) ``` The documented API contract states: ```text status = 1: processing status = 9: completed status = -1: failed ``` ### Technical Analysis The implementation contradicts the task-state contract documented by the Skill. It classifies numeric status `1` as success, although the documentation defines it as processing. It also omits the documented terminal statuses `9` and `-1`. As a result: - A processing response with status `1` is returned immediately as though it were terminal. - A completed response with status `9` is not recognized as success. - A failed response with status `-1` is not recognized as failure. - Completed or failed tasks can continue to be queried un ...[truncated 1362 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (11)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill declares required environment variables and clearly depends on outbound network access, but it does not declare any explicit tool scope such as permissions or allowed-tools. That weakens least-privilege controls and makes it harder for users or the platform to understand and constrain what the skill can access before execution.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

This skill is designed to send user prompts and user-supplied images, videos, and audio references to external Bona/Tencent-backed generation services, but the description does not warn users that their content will leave the local environment. That creates a meaningful privacy and consent risk, especially for sensitive or proprietary media.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Multiple sections instruct that prompts 'must be in English', which imposes a language policy on users. The file does not offer opt-in, alternatives, or a documented justification for this restriction, so it appears to violate the language/locale policy criteria.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The client reads BONA_API_KEY and BONA_ACCESS_TOKEN from environment variables and, when needed, sends the API key to the login endpoint to obtain an access token. The file lacks any user-facing notice, confirmation, or explanatory comment warning that credentials from the environment are being consumed and used in outbound authentication requests.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% 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 · scripts/bona_movie_production.py (reported line 189)May include surrounding context.

python
def _login(self) -> str:
        if not self.api_key:
            raise RuntimeError("api_key is required for login")
        response = requests.post(
            self.login_url,
            headers={"Content-Type": "application/json"},
            json={"accessKey": self.api_key},

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This code sends user-supplied prompts, thread identifiers, and referenced image/video/audio URLs to remote Bona API endpoints via HTTP requests. Although network transmission is central to the skill's purpose, the file provides no print/log message, confirmation, or explicit comment/docstring warning that user content will be sent to an external service.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% 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 · scripts/bona_movie_production.py (reported line 217)May include surrounding context.

python
}

    def create_image_task(self, payload: Dict[str, Any]) -> Dict[str, Any]:
        response = requests.post(f"{self.base_url}/image", headers=self.headers, json=payload, timeout=self.timeout)
        return self._parse_response(response)

    def create_video_task(self, payload: Dict[str, Any]) -> Dict[str, Any]:

Tainted flow: 'payload' from requests.post (line 195, network input) → requests.post (network output)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/bona_movie_production.py (reported line 217)May include surrounding context.

python
}

    def create_image_task(self, payload: Dict[str, Any]) -> Dict[str, Any]:
        response = requests.post(f"{self.base_url}/image", headers=self.headers, json=payload, timeout=self.timeout)
        return self._parse_response(response)

    def create_video_task(self, payload: Dict[str, Any]) -> Dict[str, Any]:

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% 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 · scripts/bona_movie_production.py (reported line 221)May include surrounding context.

python
return self._parse_response(response)

    def create_video_task(self, payload: Dict[str, Any]) -> Dict[str, Any]:
        response = requests.post(f"{self.base_url}/video", headers=self.headers, json=payload, timeout=self.timeout)
        return self._parse_response(response)

    def query_task(self, task_id: str, thread_id: Optional[str] = None, model_name: Optional[str] = None) -> Dict[

Tainted flow: 'payload' from requests.post (line 195, network input) → requests.post (network output)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/bona_movie_production.py (reported line 221)May include surrounding context.

python
return self._parse_response(response)

    def create_video_task(self, payload: Dict[str, Any]) -> Dict[str, Any]:
        response = requests.post(f"{self.base_url}/video", headers=self.headers, json=payload, timeout=self.timeout)
        return self._parse_response(response)

    def query_task(self, task_id: str, thread_id: Optional[str] = None, model_name: Optional[str] = None) -> Dict[

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
96% confidence
Finding

Several user-facing strings, including subcommand help text and the final error message, are hardcoded in Chinese. This imposes a specific language on all users without any locale selection, opt-in, or documented region-specific constraint.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.