Back to skill

Security audit

Videoinu

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a real Videoinu integration, but it needs Review because its scripts can expose the user's access token to untrusted destinations and can blanket-approve remote agent actions.

Install only after reviewing and preferably fixing the credential-handling paths. Avoid --auto-approve except in isolated test accounts, do not set VIDEOINU_API_BASE to untrusted or plaintext endpoints, do not use download_file.py --urls with untrusted URLs, and consider using short-lived or least-privilege Videoinu tokens rather than saving a long-lived token on disk.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/download_file.py:31
Finding

Videoinu Access Token Disclosed to Arbitrary Download URLs

Content
View full analysis
str: """Download a single URL. Returns local path.""" # Extract extension from URL parsed_path = urllib.parse.urlparse(url).path ext = os.path.splitext(parsed_path)[1] or ".bin" filename = f"{prefix}_{index:03d}{ext}" if prefix else os.path.basename(parsed_path) local_path = os.path.join(output_dir, filename) req = urllib.request.Request(url, headers={"Cookie": _cookie_header()}) with urllib.request.urlopen(req, timeout=120) as resp: with open(local_path, "wb") as f: while True: chunk = resp.read(65536) if not chunk: break f.write(chunk) return local_path ``` ```python parser.add_argument("graph_id", nargs="?", help="Graph ID to download files from") parser.add_argument("--urls", nargs="+", help="Direct URLs to download") parser.add_argument("--output-dir", default=DEFAULT_OUTPUT_DIR, help="Output directory") parser.add_argument("--type", choices=["image", "video", "audio", "all"], default="all", help="Filter by asset type (default: all)") parser.add_argument("--prefix", default="", help="File name prefix") parser.add_argument("--workers", type=int, default=5, help="Parallel download workers") args = parser.parse_args() if not args.urls and not args.graph_id: parser.error("Either GRAPH_ID or --urls is required") require_access_key() os.makedirs(args.output_dir, exist_ok=True) urls = [] if args.urls: urls = args.urls else: # Fetch graph and extract URLs from asset core nodes data = api_get(f"/graph/{args.graph_id}") ``` ### Technical Analysis The download function adds the account au ...[truncated 1845 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/_common.py:25
Finding

Configurable API Base Can Redirect Authentication Credentials to an Untrusted Host

Content
View full analysis
credentials file _CREDENTIALS_PATH = os.path.join(os.path.expanduser("~"), ".videoinu", "credentials.json") def _load_access_key() -> str: # 1. Environment variable (highest priority) env_key = os.environ.get("VIDEOINU_ACCESS_KEY", "") if env_key: return env_key # 2. Credentials file if os.path.isfile(_CREDENTIALS_PATH): try: with open(_CREDENTIALS_PATH) as f: return json.load(f).get("access_key", "") except (json.JSONDecodeError, OSError): pass return "" ACCESS_KEY = _load_access_key() # Derived GO_API_PREFIX = f"{BASE_URL}/api/backend" AGENT_API_PREFIX = f"{BASE_URL}/api/agent" ``` ```python def _cookie_header() -> str: return f"token={ACCESS_KEY}" def _base_headers() -> dict: return { "Cookie": _cookie_header(), "Content-Type": "application/json", "Accept": "application/json", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", } def api_get(path: str, base: str | None = None, params: dict | None = None) -> dict: """GET request. Returns the `data` field from the standard response envelope.""" url = f"{base or GO_API_PREFIX}{path}" if params: url += "?" + urllib.parse.urlencode(params) req = urllib.request.Request(url, headers=_base_headers(), method="GET") return _do_request(req) def api_post(path: str, body: dict | None = None, base: str | None = None) -> dict: """POST request. Returns the `data` field from the standard response envelope.""" url = f"{base or GO_API_PRE ...[truncated 3204 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/agent_chat.py:204
Finding

Agent Tool Requests Can Be Approved Without Scope or Intent Validation

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (27)

Tainted flow: 'req' from os.environ.get (line 111, credential/environment) → urllib.request.urlopen (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/_common.py (reported line 117)May include surrounding context.

python
def _do_request(req: urllib.request.Request, timeout: int = 30) -> dict:
    try:
        with urllib.request.urlopen(req, timeout=timeout) as resp:
            body = json.loads(resp.read().decode())
    except urllib.error.HTTPError as e:
        error_body = e.read().decode() if e.fp else ""

Tainted flow: 'req' from os.environ.get (line 111, credential/environment) → urllib.request.urlopen (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/_common.py (reported line 149)May include surrounding context.

python
def _do_request(req: urllib.request.Request, timeout: int = 30) -> dict:
    try:
        with urllib.request.urlopen(req, timeout=timeout) as resp:
            body = json.loads(resp.read().decode())
    except urllib.error.HTTPError as e:
        error_body = e.read().decode() if e.fp else ""

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The manifest presents the skill mainly as a Videoinu project-management integration, but the documentation also includes local credential storage, logout/removal, and token verification behaviors. This mismatch can mislead users and security controls about the real privilege and data-handling footprint of the skill.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
86% confidence
Finding

The skill instructs scripts to automatically read tokens from ~/.videoinu/credentials.json, which is credential access to persistent authentication material. Automatic token discovery increases blast radius if the skill or associated scripts are invoked unexpectedly or in the wrong context.

Content

Scanner excerpt · SKILL.md (reported line 23)May include surrounding context.

md
**You MUST use the Python scripts provided by this skill to interact with Videoinu. Do NOT use mcporter, MCP, curl, or any other method to call the API directly.**

All scripts are located in the `scripts/` directory of this skill. Tokens are stored in `~/.videoinu/credentials.json` and scripts read them automatically.

Example: to list projects, run `python3 <skill_scripts_dir>/list_graphs.py` — do not construct HTTP requests manually.

Credential Access

High
Category
Privilege Escalation
Confidence
89% confidence
Finding

Recommending local storage of the access key in a predictable file path creates a persistent credential target on disk. Even with owner-only permissions, disk persistence increases exposure to local compromise, accidental backup leakage, or misuse by other automation.

Content

Scanner excerpt · SKILL.md (reported line 58)May include surrounding context.

Option A: Save locally with auth.py (recommended)

bash
python3 auth.py save "your-access-key"
# Token saved to ~/.videoinu/credentials.json (owner read/write only)
# All scripts will auto-read it — no environment variable needed

Credential Access

High
Category
Privilege Escalation
Confidence
83% confidence
Finding

Documenting token resolution priority that silently prefers environment variables or a default credential file encourages broad automatic credential consumption. This can cause the skill to operate under credentials the user did not intend to use in the current task.

Content

Scanner excerpt · SKILL.md (reported line 67)May include surrounding context.

export VIDEOINU_ACCESS_KEY="your-access-key"

text

Token resolution priority: environment variable > `~/.videoinu/credentials.json`

Verify and manage:
```bash

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · scripts/_common.py (reported line 28)May include surrounding context.

python
"""
Save or verify Videoinu access key.

The token is stored at ~/.videoinu/credentials.json so scripts
can read it without needing environment variables.

Usage:

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · scripts/auth.py (reported line 5)May include surrounding context.

python
"""
Save or verify Videoinu access key.

The token is stored at ~/.videoinu/credentials.json so scripts
can read it without needing environment variables.

Usage:

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · scripts/auth.py (reported line 22)May include surrounding context.

python
"""
Save or verify Videoinu access key.

The token is stored at ~/.videoinu/credentials.json so scripts
can read it without needing environment variables.

Usage:

Credential Access

High
Category
Privilege Escalation
Confidence
81% confidence
Finding

The script persists a long-lived access key in plaintext under ~/.videoinu/credentials.json for later automatic reuse. Although the file is chmod'd to owner read/write, the code does not set restrictive permissions on the containing directory and does not use secure OS-backed secret storage, so local compromise, backup exposure, or misconfigured home-directory permissions could disclose the credential. In the context of a skill that can manage projects, files, agent chats, and workflows, theft of this token could enable significant account misuse.

Content

Scanner excerpt · scripts/auth.py (reported line 32)May include surrounding context.

python
import stat

CREDENTIALS_DIR = os.path.expanduser("~/.videoinu")
CREDENTIALS_PATH = os.path.join(CREDENTIALS_DIR, "credentials.json")


def save_token(token: str):

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill exposes significant capabilities including shell, network, filesystem, environment, and MCP access but does not declare any explicit tool scope or permission boundaries. This increases the chance of overbroad execution and makes it harder for users or orchestrators to understand and constrain what the skill may do.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The invocation guidance is broad enough that the skill may trigger on generic mentions of Videoinu or common actions like upload, download, chat, or workflows. Overbroad activation can cause unintended use of a skill with network and file-transfer capabilities in contexts where the user did not intend that behavior.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill describes uploading local files to a remote platform and downloading remote content to local storage, but it does not prominently warn users about data transfer, persistence, destination, and sensitivity implications at the point of use. This can lead to accidental exfiltration of local files or unsafe retrieval of remote data.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · SKILL.md (reported line 33)May include surrounding context.

md
1. **Graph Management** — Create, list, and view Graphs (project canvases) along with their ViewNodes / CoreNodes
2. **File Upload/Download** — Upload local files to the platform (creating CoreNodes) or download files from a Graph
3. **Agent Chat** — Create Agent sessions and chat with AI Agents via WebSocket
4. **Workflow Execution** — Run Workflow definitions and query execution status

### Requirements

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
93% confidence
Finding

The same --auto-approve behavior represents autonomous decision-making that bypasses human oversight for downstream agent operations. Given the skill's ability to manipulate platform state and process uploaded content, this can amplify mistakes or abuse originating from prompts or agent behavior.

Content

Scanner excerpt · SKILL.md (reported line 185)May include surrounding context.

→ session_id = "sess456"

3. Ask the Agent to process the file

python3 agent_chat.py sess456 "Please edit this video {{@core_node:abc123:video.mp4}}" --auto-approve

text

### Scenario 5: Run a Workflow

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
93% confidence
Finding

The same --auto-approve behavior represents autonomous decision-making that bypasses human oversight for downstream agent operations. Given the skill's ability to manipulate platform state and process uploaded content, this can amplify mistakes or abuse originating from prompts or agent behavior.

Content

Scanner excerpt · SKILL.md (reported line 185)May include surrounding context.

→ session_id = "sess456"

3. Ask the Agent to process the file

python3 agent_chat.py sess456 "Please edit this video {{@core_node:abc123:video.mp4}}" --auto-approve

text

### Scenario 5: Run a Workflow

Ssd 3

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The instruction to pass user requests to the downstream agent unchanged encourages blind forwarding of potentially sensitive, regulated, or prompt-injection-laden content. In this skill, that is more dangerous because agent chat sends data to a remote AI service that may also invoke tools against graph content.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The documentation enumerates a DELETE endpoint for graphs, but this destructive capability is omitted from the manifest description. Hidden destructive actions are risky because users may invoke the skill without realizing it can remove remote resources.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
91% confidence
Finding

The presence of the --auto-approve switch is itself a security-significant autonomous-decision feature because it allows operator approval to be delegated wholesale to the script. Given this skill's environment—agent chat plus tool and workflow access—that delegation increases the blast radius of malicious prompts or model mistakes.

Content

Scanner excerpt · scripts/agent_chat.py (reported line 59)May include surrounding context.

python
parser.add_argument("message", help="Message to send")
    parser.add_argument("--timeout", type=int, default=TIMEOUT_SECONDS,
                        help=f"Timeout in seconds (default {TIMEOUT_SECONDS})")
    parser.add_argument("--auto-approve", action="store_true",
                        help="Automatically approve all tool execution requests")
    args = parser.parse_args()

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
91% confidence
Finding

The presence of the --auto-approve switch is itself a security-significant autonomous-decision feature because it allows operator approval to be delegated wholesale to the script. Given this skill's environment—agent chat plus tool and workflow access—that delegation increases the blast radius of malicious prompts or model mistakes.

Content

Scanner excerpt · scripts/agent_chat.py (reported line 59)May include surrounding context.

python
parser.add_argument("message", help="Message to send")
    parser.add_argument("--timeout", type=int, default=TIMEOUT_SECONDS,
                        help=f"Timeout in seconds (default {TIMEOUT_SECONDS})")
    parser.add_argument("--auto-approve", action="store_true",
                        help="Automatically approve all tool execution requests")
    args = parser.parse_args()

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The script exposes a --auto-approve option that automatically approves every ApprovalRequest from the remote agent session without scoping, confirmation, or policy checks. In a skill whose purpose is to chat with AI agents and run workflows, this can silently grant the agent authority to execute actions beyond passive messaging, including potentially sensitive tool operations, making prompt injection or agent misbehavior materially more dangerous.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The CLI help text presents --auto-approve as a convenience feature but does not clearly warn that it may authorize arbitrary agent-requested tool executions. Because this script is part of an agent-chat skill, weak user-facing signaling increases the chance that operators enable the flag without understanding that they are delegating approval authority to an AI-controlled workflow.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
97% confidence
Finding

When an ApprovalRequest event is received, the code immediately sends an approval response if args.auto_approve is set, without validating the requested action, origin, risk level, or expected tool. This creates a direct trust boundary failure: any approval-guarded capability exposed through the session can be granted automatically, potentially enabling unwanted file access, workflow execution, or other privileged actions.

Content

Scanner excerpt · scripts/agent_chat.py (reported line 207)May include surrounding context.

python
elif event_type == "ApprovalRequest":
            payload = params.get("payload", {})
            rpc_id = msg.get("id", payload.get("id"))
            if args.auto_approve:
                approval_resp = {
                    "jsonrpc": "2.0",
                    "id": rpc_id,

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
85% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

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

python
# Report the approval request and let the caller decide
                text_parts.append(
                    f"\n[Approval Required: {payload.get('action', '')} - {payload.get('description', '')}]\n"
                    f"Re-run with --auto-approve to auto-approve, or use respond_approval.py"
                )
                finished = True
                break

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
65% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

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

python
# Report the approval request and let the caller decide
                text_parts.append(
                    f"\n[Approval Required: {payload.get('action', '')} - {payload.get('description', '')}]\n"
                    f"Re-run with --auto-approve to auto-approve, or use respond_approval.py"
                )
                finished = True
                break

Static analysis

No suspicious patterns detected.