Back to skill

Security audit

Topview

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its Topview media-generation purpose, but it handles account credentials and user files while leaving several network destinations less restricted than its own documentation claims.

Review before installing if you will process sensitive media or account data. Use it only with a Topview account you are comfortable connecting, avoid passing webhook URLs you do not control, and prefer an isolated environment because local files may be uploaded and credentials are saved under your home directory.

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
scripts/auth.py:47
Finding
Unnecessary Persistence of Access Tokens and Account Metadata## Vulnerability Details **File Location**: `scripts/auth.py`, lines 47–64 **Vulnerability Type**: Excessive sensitive-data persistence **Risk Level**: Medium ```python api_keys = data.get("api_keys", []) api_key = api_keys[0] if api_keys else "" creds = { "uid": data.get("uid", ""), "api_key": api_key, "email": data.get("email", ""), "name": data.get("name", ""), "team_id": data.get("team_id", ""), "role": data.get("role", ""), "charge_type": data.get("charge_type", ""), "remain_credit": data.get("remain_credit"), "created_at": datetime.now(timezone.utc).isoformat(), } if data.get("access_token"): creds["access_token"] = data["access_token"] creds["token_type"] = data.get("token_type", "Bearer") ``` ### Technical Analysis The authentication workflow persists substantially more information than the runtime API client requires. `scripts/shared/config.py` only retrieves `uid` and `api_key` from the credential file, while `auth.py` additionally stores: - Email address and display name - Team identifier and account role - Billing type and remaining credit balance - OAuth access token and token type Persisting unused sensitive fields violates data-minimization and least-privilege principles. In particular, storing an access token creates an additional reusable credential whose scope, expiration, and revocation behavior are not enforced by this code. Although the credential file is intended to have owner-only permissions, filesystem permissions do not eliminate risks from malware running as the same user, compromised backups, accidental archival, filesystem disclosure, or defects elsewhere in the host environment. ### Attack Path 1. A user completes the Topview device authorization flow. 2. The OAuth response contains an API key, account metadata, and potentially an access token. 3. `auth.py` writes all these values to `~/.topview/credentials.json`. ...[truncated 1039 chars]
Remediation
## Remediation Suggestions 1. Store only the fields required by `scripts/shared/config.py`: ```python creds = { "uid": data.get("uid", ""), "api_key": api_key, "created_at": datetime.now(timezone.utc).isoformat(), } ``` 2. Do not persist `access_token` unless a documented runtime operation requires it. 3. If access-token persistence becomes necessary, use an operating-system credential vault rather than a plaintext JSON file. 4. Document the token's purpose, scope, expiration, and revocation behavior. 5. Avoid storing profile and billing fields; retrieve them on demand through authenticated API calls. 6. On upgrade, migrate existing credential files by removing unnecessary fields. 7. Ensure logout revokes server-side tokens where the Topview API supports revocation, rather than only deleting the local file.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/auth.py:66
Finding
Sensitive Authentication Files Are Not Created Atomically with Restrictive Permissions## Vulnerability Details **File Locations**: `scripts/auth.py`, lines 66–67 and 212–220 **Vulnerability Type**: Insecure sensitive-file creation **Risk Level**: Medium Credential-file creation: ```python CRED_FILE.write_text(json.dumps(creds, indent=2)) CRED_FILE.chmod(0o600) ``` Pending authorization-file creation: ```python PENDING_FILE.parent.mkdir(parents=True, exist_ok=True) PENDING_FILE.write_text(json.dumps({ "device_code": device_code, "token_endpoint": token_endpoint, "interval": interval, "expires_in": expires_in, "verification_uri_complete": verification_url, "created_at": datetime.now(timezone.utc).isoformat(), }, indent=2)) ``` ### Technical Analysis The credential file is first created using the process's current umask and is changed to mode `0600` only after all sensitive content has been written. This creates a time-of-check and permission-hardening window during which the file can have broader permissions than intended. The pending authorization file receives no explicit permission hardening. It contains a live OAuth device code, token endpoint, verification URL, and session metadata. Under a common umask such as `022`, a newly created file may be readable by other local users until it is deleted. The code also performs ordinary pathname-based writes rather than securely creating a new file descriptor with exclusive creation and restrictive permissions. It does not explicitly reject symbolic links or use an atomic replacement strategy. ### Attack Path 1. An attacker has local access to the same multi-user system and can inspect files permitted by the victim's umask. 2. The victim runs `python auth.py login`. 3. `pending_device.json` is created with default umask-derived permissions and remains present while authorization is pending. 4. The attacker reads the live device code and associated endpoint information. 5. Depending on the OAuth server's device- ...[truncated 1353 chars]
Remediation
## Remediation Suggestions 1. Create `~/.topview` with mode `0700` and verify that it is owned by the current user. 2. Create sensitive files using a descriptor that applies mode `0600` at creation time: ```python fd = os.open( path, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600, ) ``` 3. Write through the secured descriptor rather than calling `Path.write_text`. 4. For credential updates, write to a securely created temporary file in the same directory, flush and synchronize it, and atomically replace the destination. 5. Apply mode `0600` to both `credentials.json` and `pending_device.json`. 6. Reject symbolic links and verify file ownership before reading, replacing, or deleting either file. 7. Minimize the lifetime of `pending_device.json` and delete it on every terminal path, including cancellation and unexpected exceptions. 8. Consider retaining the device code only in process memory during the normal login flow and creating a recovery file only when the user explicitly requests resumable polling.

T08 · Insecure Dependencies

Note
Location
scripts/requirements.txt:1
Finding
Dependencies Are Installed Without Upper Bounds, Locking, or Integrity Hashes## Vulnerability Details **File Location**: `scripts/requirements.txt`, lines 1–2 **Related Instruction**: `SKILL.md`, line 188 **Vulnerability Type**: Uncontrolled dependency resolution **Risk Level**: Low ```text requests>=2.28.0 python-dotenv>=1.0.0 ``` The installation instructions execute: ```bash pip install -r {baseDir}/scripts/requirements.txt ``` ### Technical Analysis Both dependencies use open-ended lower bounds. No lock file, exact version constraints, package hashes, or reviewed dependency snapshot is provided. Consequently, two installations performed at different times may resolve to different package versions. Any future release satisfying the lower bound can be selected without having been reviewed together with this Skill. Python packages can execute code during installation and later during import, so a compromised upstream release or dependency-resolution change can affect the Agent environment. The reviewed dependency names correspond to legitimate packages, and the audit found no evidence that the currently declared packages are malicious. The weakness is the absence of reproducible and integrity-verified dependency resolution. ### Attack Path 1. An attacker compromises the publication process or maintainer account of a declared package or one of its transitive dependencies. 2. A malicious future version is published and still satisfies the open-ended version requirement. 3. A user follows the documented `pip install -r` command. 4. The package resolver selects the compromised version. 5. Malicious package code executes during installation or when the Skill imports the package. 6. The code runs with the permissions of the user or Agent process and may access files, environment variables, network resources, and locally stored Topview credentials available to that process. ### Impact Assessment A malicious dependency can execute arbitrary Python code with the privileges of t ...[truncated 448 chars]
Remediation
## Remediation Suggestions 1. Pin each direct dependency to a reviewed exact version. 2. Generate and commit a lock file that includes transitive dependencies. 3. Record cryptographic hashes and install with hash verification: ```bash pip install --require-hashes -r requirements.lock ``` 4. Use an automated dependency-update process that opens reviewed, tested updates rather than automatically accepting every future release. 5. Run vulnerability and provenance checks in continuous integration. 6. Prefer an isolated virtual environment with only the permissions and files required by this Skill. 7. Rebuild the lock file on a controlled system and review dependency changes before distribution.
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (77)

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

Critical
Category
Data Flow
Content
def cmd_login(args) -> None:
    """Full login flow: init device code → open browser → poll until done."""
    try:
        resp = requests.post(
            f"{OAUTH_BASE_URL}/api/device/init",
            json={
                "client_id": CLIENT_ID,
Confidence
97% confidence
Finding
The OAuth base URL is taken from TOPVIEW_OAUTH_URL without validation, so any local process or wrapper that can set environment variables can redirect the login flow to an attacker-controlled server. That server can return arbitrary verification and token endpoints, causing the script to send device codes and receive attacker-supplied credentials or tokens while violating the stated '*.topview.ai only' network boundary.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The user-supplied noticeUrl/webhook directly contradicts the claim of Topview-only network access and allows the system to participate in interactions with arbitrary external hosts. In addition, voice-clone and delete operations are more sensitive than the headline description suggests, increasing the chance that users underestimate risk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The user-supplied noticeUrl/webhook directly contradicts the claim of Topview-only network access and allows the system to participate in interactions with arbitrary external hosts. In addition, voice-clone and delete operations are more sensitive than the headline description suggests, increasing the chance that users underestimate risk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The user-supplied noticeUrl/webhook directly contradicts the claim of Topview-only network access and allows the system to participate in interactions with arbitrary external hosts. In addition, voice-clone and delete operations are more sensitive than the headline description suggests, increasing the chance that users underestimate risk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The user-supplied noticeUrl/webhook directly contradicts the claim of Topview-only network access and allows the system to participate in interactions with arbitrary external hosts. In addition, voice-clone and delete operations are more sensitive than the headline description suggests, increasing the chance that users underestimate risk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The user-supplied noticeUrl/webhook directly contradicts the claim of Topview-only network access and allows the system to participate in interactions with arbitrary external hosts. In addition, voice-clone and delete operations are more sensitive than the headline description suggests, increasing the chance that users underestimate risk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The user-supplied noticeUrl/webhook directly contradicts the claim of Topview-only network access and allows the system to participate in interactions with arbitrary external hosts. In addition, voice-clone and delete operations are more sensitive than the headline description suggests, increasing the chance that users underestimate risk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The user-supplied noticeUrl/webhook directly contradicts the claim of Topview-only network access and allows the system to participate in interactions with arbitrary external hosts. In addition, voice-clone and delete operations are more sensitive than the headline description suggests, increasing the chance that users underestimate risk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The user-supplied noticeUrl/webhook directly contradicts the claim of Topview-only network access and allows the system to participate in interactions with arbitrary external hosts. In addition, voice-clone and delete operations are more sensitive than the headline description suggests, increasing the chance that users underestimate risk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The user-supplied noticeUrl/webhook directly contradicts the claim of Topview-only network access and allows the system to participate in interactions with arbitrary external hosts. In addition, voice-clone and delete operations are more sensitive than the headline description suggests, increasing the chance that users underestimate risk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The user-supplied noticeUrl/webhook directly contradicts the claim of Topview-only network access and allows the system to participate in interactions with arbitrary external hosts. In addition, voice-clone and delete operations are more sensitive than the headline description suggests, increasing the chance that users underestimate risk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The user-supplied noticeUrl/webhook directly contradicts the claim of Topview-only network access and allows the system to participate in interactions with arbitrary external hosts. In addition, voice-clone and delete operations are more sensitive than the headline description suggests, increasing the chance that users underestimate risk.

Credential Access

High
Category
Privilege Escalation
Content
endpoints:
    - https://api.topview.ai
    - https://www.topview.ai
  storesCredentialsAt: ~/.topview/credentials.json
---

# Topview AI Skill
Confidence
92% confidence
Finding
The manifest explicitly states that credentials are stored at ~/.topview/credentials.json, which signals the presence of retrievable secrets on disk. In an agent with file-read/write capability, local secret storage increases the blast radius of prompt injection, plugin compromise, or accidental file exposure.

Credential Access

High
Category
Privilege Escalation
Content
## Notes for Auditors

> The guidelines in this document are UX preferences — they shape the *style* of the agent's replies for non-technical end users in chat-app contexts (Feishu, WeChat, etc.). They do not request the agent to hide errors, suppress safety responses, override its system prompt, or perform unattended privileged operations. All API calls go to `*.topview.ai`. Credentials are stored locally at `~/.topview/credentials.json` with `0600` permissions. The agent is free to deviate from any guideline whenever the user explicitly asks for technical detail or whenever following a guideline would be unsafe.

## Execution
Confidence
91% confidence
Finding
The auditor note reiterates local credential storage and attempts to reassure reviewers, but from a security perspective this confirms sensitive tokens live on disk within reach of any over-privileged agent actions. In the context of a shell- and file-capable skill, that makes compromise or exfiltration more serious.

Credential Access

High
Category
Privilege Escalation
Content
api_key:     sk-...3HB
  charge_type: pro
  authorized:  2026-03-04T10:00:00+00:00
  file:        /Users/you/.topview/credentials.json
```

## `logout` — Remove Credentials
Confidence
78% confidence
Finding
The documented `status` output includes personally identifiable information and a partially masked API key, which can still leak sensitive metadata into terminal history, logs, screenshots, or agent-captured output. In agent environments, even masked secrets and account identifiers may be surfaced to downstream systems unintentionally.

Credential Access

High
Category
Privilege Escalation
Content
All modules use `shared/config.py` which loads credentials in this order:

1. Environment variables `TOPVIEW_UID` + `TOPVIEW_API_KEY` (CI/scripting)
2. `~/.topview/credentials.json` (set by `auth.py login`)
3. Error — prompts to run `auth.py login`

## Agent Rules
Confidence
74% confidence
Finding
Supporting credentials from environment variables increases the risk of accidental secret exposure because env vars are often inherited by subprocesses, surfaced in CI logs, or accessible through debugging and process inspection in some environments. In an agent skill, this broadens the credential attack surface beyond a dedicated credentials store.

Description-Behavior Mismatch

High
Confidence
97% confidence
Finding
The skill manifest says network calls are restricted to *.topview.ai, but download_video() performs a raw requests.get() against whatever finishedVideoUrl the API returns, with no host allowlist or scheme validation. This creates an SSRF / trust-boundary violation and could let an attacker-controlled or compromised API response trigger arbitrary outbound requests, including access to internal services or unexpected hosts.

Description-Behavior Mismatch

High
Confidence
97% confidence
Finding
The script downloads a URL returned in API results using `requests.get(url, stream=True)` with no validation that the host is within `*.topview.ai`, despite the skill metadata claiming all network calls are restricted there. If the upstream API, a task result, or a user-influenced field can supply an arbitrary URL, this enables outbound requests to attacker-controlled hosts and local file overwrite via `--output`, violating the declared trust boundary and potentially exposing the agent to SSRF-like behavior or malicious content retrieval.

Description-Behavior Mismatch

High
Confidence
98% confidence
Finding
The script downloads a URL returned by the API using requests.get() without validating that the destination is within the claimed *.topview.ai domain set. If the remote service, a compromised API response, or an attacker-controlled task result supplies an arbitrary URL, the agent will make outbound requests to attacker-chosen hosts, violating the skill's network boundary and potentially enabling SSRF-like behavior, metadata access, or exfiltration through authenticated/proxied environments.

Description-Behavior Mismatch

High
Confidence
98% confidence
Finding
The client accepts any non-slash-prefixed path as a full URL, so callers can direct requests to arbitrary domains while still attaching Topview authentication headers. This violates the stated network boundary and can leak credentials or sensitive request data to attacker-controlled endpoints via SSRF-style misuse or deceptive skill logic.

Description-Behavior Mismatch

High
Confidence
99% confidence
Finding
The file upload helper performs a raw PUT to an arbitrary upload_url, which enables outbound transmission of local file contents to any host, not just Topview infrastructure. In a skill context, this expands the exfiltration surface significantly because a malicious or compromised upstream service could supply attacker-controlled URLs for local file upload.

Credential Access

High
Category
Privilege Escalation
Content
Priority order:
1. Environment variables TOPVIEW_UID + TOPVIEW_API_KEY  (CI / backwards compat)
2. Credential file ~/.topview/credentials.json           (set by auth.py login)
3. Error — prompts user to run auth.py login
"""
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
Priority order:
1. Environment variables TOPVIEW_UID + TOPVIEW_API_KEY  (CI / backwards compat)
2. Credential file ~/.topview/credentials.json           (set by auth.py login)
3. Error — prompts user to run auth.py login
"""
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
Priority order:
1. Environment variables TOPVIEW_UID + TOPVIEW_API_KEY  (CI / backwards compat)
2. Credential file ~/.topview/credentials.json           (set by auth.py login)
3. Error — prompts user to run auth.py login
"""
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
Priority order:
1. Environment variables TOPVIEW_UID + TOPVIEW_API_KEY  (CI / backwards compat)
2. Credential file ~/.topview/credentials.json           (set by auth.py login)
3. Error — prompts user to run auth.py login
"""
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Static analysis

No suspicious patterns detected.