Back to skill

Security audit

Byted Byteplus Vod Precision Erasure

Security checks for vulnerabilities and agentic risk

Overview

The skill does what it says, but its local upload and endpoint controls are broad enough that users should review it before installation.

Install only if you trust the workspace and environment configuration. Use narrowly scoped BytePlus credentials, avoid setting VOD_HOST unless necessary, keep upload inputs to known media files, and be aware that local files are transmitted to BytePlus/TOS and erasure creates processed media in the VOD account.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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)

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/upload.py:73
Finding

Overly Broad Temporary-Directory Access Allows Unintended File Uploads

Content
View full analysis
list[str]: global _ALLOWED_PREFIXES if _ALLOWED_PREFIXES is not None: return _ALLOWED_PREFIXES prefixes: list[str] = [] # 1) WORKSPACE (or cwd) — the project the agent is operating in ws = os.environ.get("WORKSPACE", os.getcwd()) prefixes.append(os.path.realpath(ws)) # 2) sibling userdata/ directory (Cursor sandbox convention) ud = os.path.join(os.path.dirname(ws), "userdata") if ws else "" if ud: prefixes.append(os.path.realpath(ud)) # 3) /tmp — commonly used for scratch files prefixes.append("/tmp") # 4) VOD_UPLOAD_ALLOWED_DIRS — comma-separated extra directories extra = os.environ.get("VOD_UPLOAD_ALLOWED_DIRS", "") for d in extra.split(","): d = d.strip() if d: prefixes.append(os.path.realpath(d)) _ALLOWED_PREFIXES = prefixes return _ALLOWED_PREFIXES def _validate_local_path(file_path: str) -> None: """Ensure the resolved path falls under an allowed prefix (symlink-safe).""" real = os.path.realpath(file_path) for prefix in _get_allowed_prefixes(): if real == prefix or real.startswith(prefix + os.sep): return ``` ### Technical Analysis The path validation explicitly permits every path beneath the system-wide `/tmp` directory. Although `os.path.realpath` prevents a straightforward symlink escape from an allowed directory, it does not mitigate the excessive scope of the allowed directory itself. The subsequent validation only requires a filename extension and does not verify that the selected file is media through an extension allowlist, MIME inspection, or content signature. Consequently, readable logs, archives, text files, credentials, session artifacts, or tempo ...[truncated 1580 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/vod_client.py:56
Finding

Insufficient Destination Validation Can Expose Signed Credentials and Uploaded Media

Content
View full analysis
dict: body_str = json.dumps(body, ensure_ascii=False) url, headers = self._sign("POST", action, version, {}, body_str) r = requests.post(url, headers=headers, data=body_str.encode(), timeout=_HTTP_TIMEOUT) self._check(r) return r.json() def get(self, action: str, version: str, params: dict) -> dict: url, headers = self._sign("GET", action, version, params or {}, "") r = requests.get(url, headers=headers, timeout=_HTTP_TIMEOUT) self._check(r) return r.json() def _sign(self, method: str, action: str, version: str, query_extra: dict, body_str: str) -> tuple[str, dict]: qp = {"Action": action, "Version": version} qp.update(query_extra) canonical_query = urlencode(sorted(qp.items()), quote_via=quote, safe="-_.~") url = f"https://{_VOD_HOST}/?{canonical_query}" ts = datetime.now(timezone.utc).strftime("%Y%m%dT%H%M%SZ") body_hash = hashlib.sha256(body_str.encode()).hexdigest() h = { "content-type": "application/json; charset=utf-8", "host": _VOD_HOST, "x-content-sha256": body_hash, "x-date": ts, } signed_keys = sorted(h.keys()) canonical_headers = "".join(f"{k}:{h[k]}\n" for k in signed_keys) signed_headers_str = ...[truncated 5526 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (19)

Tainted flow: 'url' from os.environ.get (line 111, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/vod_client.py (reported line 96)May include surrounding context.

python
def post(self, action: str, version: str, body: dict) -> dict:
        body_str = json.dumps(body, ensure_ascii=False)
        url, headers = self._sign("POST", action, version, {}, body_str)
        r = requests.post(url, headers=headers, data=body_str.encode(), timeout=_HTTP_TIMEOUT)
        self._check(r)
        return r.json()

Tainted flow: 'url' from os.environ.get (line 111, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/vod_client.py (reported line 102)May include surrounding context.

python
def get(self, action: str, version: str, params: dict) -> dict:
        url, headers = self._sign("GET", action, version, params or {}, "")
        r = requests.get(url, headers=headers, timeout=_HTTP_TIMEOUT)
        self._check(r)
        return r.json()

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The skill advertises precision-erasure-specific controls such as OCR text modes, ClipFilter behavior, NewVid handling, and WithEraseInfo, but the analysis indicates those features may be absent. Exposing nonexistent security- or privacy-relevant controls is risky because users may believe sensitive media is transformed or isolated in a particular way when the code does not enforce that behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The skill advertises precision-erasure-specific controls such as OCR text modes, ClipFilter behavior, NewVid handling, and WithEraseInfo, but the analysis indicates those features may be absent. Exposing nonexistent security- or privacy-relevant controls is risky because users may believe sensitive media is transformed or isolated in a particular way when the code does not enforce that behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The skill advertises precision-erasure-specific controls such as OCR text modes, ClipFilter behavior, NewVid handling, and WithEraseInfo, but the analysis indicates those features may be absent. Exposing nonexistent security- or privacy-relevant controls is risky because users may believe sensitive media is transformed or isolated in a particular way when the code does not enforce that behavior.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/vod_client.py (reported line 43)May include surrounding context.

python
import requests
from dotenv import load_dotenv

# ── .env loading ───────────────────────────────────────────────────────────
# Look for .env in the current working directory first, then in the script's
# own directory (so the skill still works when invoked from elsewhere).
_SCRIPT_DIR = Path(__file__).resolve().parent

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/vod_client.py (reported line 44)May include surrounding context.

python
import requests
from dotenv import load_dotenv

# ── .env loading ───────────────────────────────────────────────────────────
# Look for .env in the current working directory first, then in the script's
# own directory (so the skill still works when invoked from elsewhere).
_SCRIPT_DIR = Path(__file__).resolve().parent

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/vod_client.py (reported line 48)May include surrounding context.

python
# own directory (so the skill still works when invoked from elsewhere).
_SCRIPT_DIR = Path(__file__).resolve().parent
for _base in (Path.cwd(), _SCRIPT_DIR):
    _env = _base / ".env"
    if _env.is_file():
        load_dotenv(_env, override=False)
        break

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill documents use of environment secrets, local file inputs, and outbound network access, but it does not declare any explicit tool scope such as permissions or allowed-tools. That creates an over-broad execution surface where an agent may grant more capability than users expect, increasing the risk of unintended secret exposure, arbitrary file access, or external data transfer.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The documentation describes an operation that performs destructive media modification but does not clearly warn users about the irreversible nature of the erasure workflow or that it produces a newly processed asset. This increases the likelihood of operator misunderstanding, accidental data handling mistakes, and unsafe use in production pipelines where users may assume a reversible preview/edit operation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This script performs a content-erasure job and polls until completion, which is a safety-critical, potentially irreversible operation. Although the purpose is visible in the docstring and logs, there is no explicit warning, confirmation prompt, or cautionary message informing the user about destructive effects before submission.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This code file performs HTTP PUT uploads of file data to remote TOS endpoints, which transmits user data over the network. While the module docstring describes upload mechanics, the active upload functions themselves provide no confirmation prompt or user-facing notice before sending file contents, and several paths execute silently.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The manifest describes a combined skill that uploads media and also submits precision erasure jobs (StartExecution / Operation.Task.Erase, WithEraseInfo, subtitle/full-text options). This script's documented behavior and code implement only local/URL upload and playback URL generation; there is no erasure-job submission logic anywhere in the file.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

This code sends authenticated HTTP requests to an external VOD API, and the credentials are obtained from environment variables defined elsewhere in the file. While the module documents which environment variables are used, there is no user-facing prompt or warning that data in request bodies, query parameters, and authentication headers will be transmitted over the network.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The playback helper automatically changes remote media state by publishing assets before fetching playback URLs. In the stated skill context, which emphasizes upload, erasure submission, and returning references, silently publishing content expands behavior and can unintentionally expose media that should remain unpublished or access-controlled.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The function changes media publish status automatically without confirmation, which can make previously non-public assets playable. In a media-processing skill, that side effect is more dangerous because users may expect reference retrieval only, not a visibility or distribution-state change on remote content.

Content

No source excerpt is available for this finding.

Unverifiable Dependency: requests has 16 known advisory(ies) (CVE-2014-1830 (Exposure of Sensitive Information to an Unauthorized Actor in Requests); CVE-2024-47081 (Requests vulnerable to .netrc credentials leak via malicious URLs); CVE-2024-35195 (Requests `Session` object does not verify requests after making first request wi) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
92% confidence
Finding

The dependency is only lower-bounded (requests>=2.31.0) rather than pinned to a specific known-safe version, so builds may resolve to different releases across environments. Because requests has multiple historical advisories, this creates supply-chain uncertainty and could expose the skill to a vulnerable version if dependency resolution selects one.

Content

No source excerpt is available for this finding.

Unverifiable Dependency: python-dotenv has 2 known advisory(ies) (CVE-2026-28684 (python-dotenv: Symlink following in set_key allows arbitrary file overwrite via ); CVE-2026-28684 (python-dotenv reads key-value pairs from a .env file and can set them as environ)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
88% confidence
Finding

The manifest specifies python-dotenv>=1.0.0 without an exact pin, so the installed package version is not reproducible or provably free of known issues. Given published advisories affecting python-dotenv, leaving the version unconstrained beyond a minimum can allow vulnerable or unexpected releases to be installed in some environments.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The function reads access key and secret key values from environment variables, including from a .env file path described earlier in the module. Although the code names the variables clearly, it does not include any warning to users that sensitive credentials must be present and will be used for authenticated API operations.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.