Back to skill

Security audit

OpenStoryline Use

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches an OpenStoryline editing workflow, but its Feishu helper can upload any readable local file using local Feishu credentials without strong scoping or confirmation.

Review this skill before installing if you plan to use Feishu delivery. Only run the sender on generated video files you have checked, confirm the recipient, and avoid giving the agent arbitrary file paths or broad access to sensitive project directories. The core local OpenStoryline workflow is disclosed, but the file-sending helper needs tighter limits to be low-risk.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/feishu_file_sender.py:116
Finding
Unrestricted Local File Upload to Feishu## Vulnerability Details **File Location**: `scripts/feishu_file_sender.py`, lines 116–133 and 195–224 **Vulnerability Type**: Arbitrary local file disclosure through insufficient path validation **Risk Level**: Medium ### Vulnerable Code ```python def upload_file(token: str, file_path: Path, file_type: str) -> str: headers = {"Authorization": f"Bearer {token}"} with file_path.open("rb") as f: files = {"file": (file_path.name, f)} data = { "file_type": file_type, "file_name": file_path.name, } resp = requests.post( FEISHU_UPLOAD_URL, headers=headers, data=data, files=files, timeout=30, ) resp.raise_for_status() data = resp.json() if data.get("code") != 0: raise RuntimeError(f"Upload failed: {data}") return data["data"]["file_key"] ``` ```python def parse_args() -> argparse.Namespace: parser = argparse.ArgumentParser(description="Upload file to Feishu and send") parser.add_argument("--file", required=True, help="Local file path") parser.add_argument("--receive-id", default=None, help="chat_id or open_id") parser.add_argument( "--receive-id-type", default=None, help="chat_id / open_id / user_id (auto-detect if omitted)", ) parser.add_argument( "--file-type", default="stream", help="file_type for upload, default stream", ) return parser.parse_args() def main() -> None: args = parse_args() file_path = Path(args.file) if not file_path.exists(): raise FileNotFoundError(f"File not found: {file_path}") config = load_openclaw_config() app_id, app_secret = resolve_feishu_account(config) receive_id = resolve_receive_id(args.receive_id) receive_id_type = infer_receive_id_type(receive_id, args.receive ...[truncated 2755 chars]
Remediation
## Remediation Suggestions 1. Resolve the requested path using `Path.resolve(strict=True)` before opening it. 2. Restrict uploads to approved OpenStoryline output roots, such as the current session's render directory. 3. Use `Path.relative_to()` against a trusted canonical output root and reject paths outside that root. 4. Require `Path.is_file()` and reject symbolic links or resolve them before containment validation. 5. Allow only expected video extensions such as `.mp4`, and validate the actual media format rather than relying solely on the filename. 6. Associate the file with the active `session_id` and require it to match a generated `output_*.mp4` artifact. 7. Display the canonical file path, size, and Feishu recipient and require explicit user confirmation before upload. 8. Validate `receive_id_type` against a fixed allowlist and ensure the recipient matches the active conversation where possible. 9. Avoid logging access tokens, application secrets, or complete API responses that could contain sensitive metadata.

T08 · Insecure Dependencies

Note
Location
SKILL.md:298
Finding
Unpinned Runtime Installation of a Third-Party Dependency## Vulnerability Details **File Location**: `SKILL.md`, lines 298–302 **Vulnerability Type**: Unpinned dependency installation **Risk Level**: Low ### Vulnerable Code ```bash python3 -m pip install requests ``` ### Technical Analysis The skill documentation instructs the agent to install `requests` without specifying a reviewed version, integrity hash, lockfile, or trusted package index. Dependency resolution therefore occurs at execution time and may install a different release as the package index changes. Although `requests` is a well-known package and no evidence of typosquatting or an intentionally malicious dependency was found, the instruction provides weaker supply-chain reproducibility and integrity than a pinned dependency declaration. It may also introduce an incompatible future version into the active environment. ### Attack Path 1. The agent follows the documented setup instruction. 2. `pip` contacts the package index configured in the user's environment. 3. The resolver selects whichever `requests` release currently satisfies the unbounded requirement. 4. A compromised package-index response, compromised release, unsafe configured mirror, or incompatible future release is downloaded and installed. 5. The installed package executes Python code when imported or during package installation, within the privileges of the invoking account. 6. `feishu_file_sender.py` imports and uses that package for credential-bearing network requests. Exploitation depends on compromise or manipulation of the configured dependency source or package release; the audited project itself does not retrieve a custom malicious package. ### Impact Assessment A compromised dependency could execute code with the permissions of the Python environment's user, access files available to that account, intercept Feishu credentials and uploaded content, or alter network destinations. An incompatible release could instead cause availabilit ...[truncated 275 chars]
Remediation
## Remediation Suggestions 1. Declare the dependency in a reviewed requirements or lock file. 2. Pin an explicitly tested version, for example with an exact `requests==X.Y.Z` constraint. 3. Use package hashes through `pip --require-hashes` where practical. 4. Install only from an explicitly trusted package index. 5. Prefer an isolated virtual environment rather than modifying a shared Python environment. 6. Periodically update the pinned version after vulnerability review and compatibility testing. 7. Document the expected dependency version alongside the supported Python versions.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (15)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The manifest frames this as a local OpenStoryline usage skill, but the body introduces unrelated external file-transfer behavior via Feishu, including reading local credentials and sending rendered videos to external recipients. This mismatch is dangerous because users may authorize a local editing workflow without realizing the skill can exfiltrate files and use separate third-party messaging APIs.

Context-Inappropriate Capability

High
Confidence
99% confidence
Finding
These instructions add the capability to read Feishu credentials from local OpenClaw configuration and send files to external chat/user recipients. Accessing local credentials and using them to transmit files off-host materially increases the risk of secret misuse, unauthorized messaging, and exfiltration of private video content.

Description-Behavior Mismatch

High
Confidence
98% confidence
Finding
This script provides Feishu file upload and messaging capabilities that are unrelated to the stated OpenStoryline purpose of starting local services and editing video sessions. In a skill package, unrelated outbound transfer functionality is dangerous because it can be used to move arbitrary local files off-host under the guise of a benign media-editing tool.

Context-Inappropriate Capability

High
Confidence
99% confidence
Finding
The code obtains Feishu credentials, uploads a local file, and sends a message containing that file to an external service. Because the skill context is OpenStoryline local session/editing, this external messaging capability materially increases exfiltration risk and is not justified by the declared purpose.

Lp3

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding
The skill requests capabilities implied by its instructions—environment access, file reads, MCP/process control, and network use—but does not declare any explicit tool scope or allowlist. That makes review and enforcement harder and increases the chance the agent can invoke more powerful operations than users expect, especially because the document includes process launching, config editing, and network interactions.

External Transmission

Medium
Category
Data Exfiltration
Content
```bash
# minimax
cd <repo-root> && source .venv/bin/activate && python scripts/update_config.py --config ./config.toml --set generate_voiceover.providers.minimax.base_url=https://api.minimax.chat/v1/t2a_v2
cd <repo-root> && source .venv/bin/activate && python scripts/update_config.py --config ./config.toml --set generate_voiceover.providers.minimax.api_key=REPLACE_WITH_MINIMAX_KEY

# bytedance
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Natural-Language Policy Violations

Medium
Confidence
87% confidence
Finding
The markdown states that the `lang` parameter currently only supports `zh / en`, which imposes a language/locale constraint in the skill's operating instructions. The file does not present this as a user choice with fallback handling for other languages, nor does it justify the restriction as region-specific compliance.

Description-Behavior Mismatch

Medium
Confidence
97% confidence
Finding
The documentation instructs the agent to send rendered videos to Feishu, which extends beyond the stated local OpenStoryline workflow. That creates a data-transfer path for potentially sensitive user media to leave the local machine or trusted local service boundary without being part of the advertised scope.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
This code creates a remote session and sends the user's prompt to an external service via HTTP and WebSocket, but the script provides no confirmation prompt or user-facing warning that input text will be transmitted off-process. For a code file, network transmission of user data should have some visible disclosure unless the warning exists elsewhere, and no such disclosure is present in this file.

External Transmission

Medium
Category
Data Exfiltration
Content
def get_tenant_access_token(app_id: str, app_secret: str) -> str:
    resp = requests.post(
        FEISHU_TOKEN_URL,
        json={"app_id": app_id, "app_secret": app_secret},
        timeout=15,
Confidence
80% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

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

Medium
Category
Data Flow
Content
"file_type": file_type,
            "file_name": file_path.name,
        }
        resp = requests.post(
            FEISHU_UPLOAD_URL,
            headers=headers,
            data=data,
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.

External Transmission

Medium
Category
Data Exfiltration
Content
"msg_type": "file",
        "content": json.dumps({"file_key": file_key}),
    }
    resp = requests.post(
        FEISHU_SEND_MSG_URL,
        headers=headers,
        params=params,
Confidence
95% confidence
Finding
This request sends a file message to an external Feishu recipient, completing an outbound data-transfer path from local disk to a remote chat or user. In the context of a skill that is supposed to operate on local OpenStoryline sessions, this materially increases the chance of covert or accidental exfiltration.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The script uploads the specified local file and sends it via Feishu immediately, with no user-facing warning, dry run, or confirmation step. In an agent skill context, silent transmission of local content is dangerous because it can surprise users and facilitate accidental or unauthorized disclosure of sensitive project files.

Natural-Language Policy Violations

Low
Confidence
81% confidence
Finding
The CLI constrains language override choices to only "zh" and "en", which hard-codes a narrow locale policy in natural-language-facing behavior. The file does not document a justified regional constraint or offer broader locale choice, so this may conflict with language/locale policy requirements.

Missing User Warnings

Low
Confidence
85% confidence
Finding
The script reads appId/appSecret from the user's OpenClaw configuration and uses them in an HTTP request to obtain an access token, but there is no comment, prompt, or user-facing notice that locally stored service credentials will be accessed and used. This matches the missing-warning criterion for access to sensitive credentials in code files.

Static analysis

No suspicious patterns detected.