Back to skill

Security audit

Tingwu ASR

Security checks for vulnerabilities and agentic risk

Overview

This cloud transcription skill is mostly purpose-aligned, but it needs review because it stores broad Alibaba session cookies and plaintext login credentials locally and can fetch arbitrary URLs for upload to cloud transcription.

Install only if you are comfortable giving the skill access to Alibaba Tingwu account credentials, reusable session cookies, selected recordings, and any URL-sourced media it downloads. Use a dedicated account if possible, avoid sensitive or regulated recordings unless cloud processing is approved, keep config/.env and config/cookies.json private, do not pass cookies on the command line, avoid scheduled check-ins unless you explicitly want them, and treat arbitrary URL transcription as risky on machines with access to private networks.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/login_pw.py:234
Finding
Alibaba session cookies are over-collected, flattened across domains, and stored without restrictive permissions<![CDATA[ ## Vulnerability Details **File Location**: `scripts/login_pw.py:234-263`; related cookie replay occurs at `scripts/tingwu.py:52-62` **Vulnerability Type**: Excessive credential collection and insecure plaintext credential storage **Risk Level**: High ### Vulnerable Code ```python raw = ctx.cookies() names = {c["name"] for c in raw} critical = ("login_aliyunid_ticket", "login_aliyunid", "XSRF-TOKEN", "JSESSIONID", "atpsida", "isg") missing = [k for k in critical if k not in names] if missing: print(f"!! 关键 cookie 缺失: {missing}") print(" 听悟 API 将判 [CMN.NotLogin] 并拒绝转录。请:") print(" 1) 重新运行本脚本登录;") print(" 2) 检查浏览器是否被广告拦截/隐私插件劫持 cookie。") browser.close() sys.exit(4) cookie_map = {} for c in raw: d = c.get("domain", "") if "aliyun.com" in d or "taobao.com" in d or "alicdn.com" in d: cookie_map[c["name"]] = c["value"] data = { "saved_at": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()), "cookies": cookie_map, "verified_critical_cookies": list(critical), } COOKIE_PATH.write_text(json.dumps(data, ensure_ascii=False, indent=2), encoding="utf-8") ``` The flattened cookies are subsequently reassigned to the Alibaba domain: ```python def _load_cookies(self): if not self.cookie_path.exists(): raise FileNotFoundError( f"Cookie 文件不存在: {self.cookie_path}\n" "请先运行: python3 scripts/login.py" ) with open(self.cookie_path) as f: data = json.load(f) cookies = data.get("cookies", data) for name, value in cookies.items(): self.session.cookies.set(name, value, domain=".aliyun.com") ``` ### Technical Analysis The login script captures every browser-context cookie whose domain string contains `aliyun.com`, `taobao.com`, or `alicdn.com`. This exceeds the minimum credentials needed to authenticate to the Tingwu API. Cookies are then flattened into a name-to-value map, losing their original domain, path, expiry, `Secure`, `HttpOn ...[truncated 2233 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Capture only an explicit allowlist of cookies verified as necessary for Tingwu: - `login_aliyunid_ticket` - `login_aliyunid` - `XSRF-TOKEN` - `JSESSIONID` - Any additional cookie demonstrated to be required by the API 2. Reject cookies whose original domain is outside the exact approved Alibaba/Tingwu domains. 3. Preserve each cookie's original domain and path instead of flattening it into a map. 4. Never reassign Taobao or Alicdn cookies to `.aliyun.com`. 5. Create the credential file atomically with mode `0600`, for example using `os.open()` with `O_CREAT | O_EXCL` and permission `0o600`. 6. Verify and repair permissions on an existing cookie file before writing. 7. Prefer an operating-system credential store or encrypted secret storage over a project-local JSON file. 8. Delete cookies on logout and document a session-revocation procedure. 9. Add automated tests proving that unrelated-domain cookies are neither saved nor transmitted. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/login.py:20
Finding
Cookie import through command-line arguments exposes authentication secrets<![CDATA[ ## Vulnerability Details **File Location**: `scripts/login.py:20-45` **Vulnerability Type**: Sensitive information exposure through process arguments and plaintext files **Risk Level**: Medium ### Vulnerable Code ```python def save_cookies(cookie_map): """保存 cookie 字典到文件""" if isinstance(cookie_map, str): cookie_map = json.loads(cookie_map) data = { "saved_at": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()), "cookies": cookie_map, } COOKIE_PATH.parent.mkdir(parents=True, exist_ok=True) COOKIE_PATH.write_text(json.dumps(data, ensure_ascii=False, indent=2), encoding="utf-8") print(f"已保存 {len(cookie_map)} 个 Cookie 到 {COOKIE_PATH}") def main(): import argparse parser = argparse.ArgumentParser(description="通义听悟 Cookie 管理") parser.add_argument("--save-cookies", help="直接传入 cookie JSON 字符串") parser.add_argument("--cookie-file", help="从文件读取 cookie JSON") args = parser.parse_args() if args.save_cookies: save_cookies(args.save_cookies) elif args.cookie_file: with open(args.cookie_file, encoding="utf-8") as f: save_cookies(json.load(f)) ``` ### Technical Analysis The `--save-cookies` option accepts the complete authentication cookie set directly in the process argument vector. Command-line arguments may be visible to same-host users through process inspection facilities and are commonly retained in shell history, terminal logs, agent tool transcripts, or process-monitoring systems. The documentation explicitly recommends this invocation form, making accidental disclosure likely. The destination file is also written without explicitly enforcing owner-only permissions. ### Attack Path 1. A user or agent invokes `login.py --save-cookies '{"login_aliyunid_ticket":"..."}'`. 2. While the process is running, another local user or monitoring process reads the argument vector. 3. The command may remain in shell history or an agent execution log after c ...[truncated 373 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the `--save-cookies` command-line option. 2. Accept sensitive JSON through standard input, an already protected file descriptor, or a credential-store API. 3. If file import remains supported, require that the source is a regular file owned by the current user and has no group or world permissions. 4. Write `cookies.json` atomically with mode `0600`. 5. Update `SKILL.md` so examples never place credentials in command-line arguments. 6. Warn users to revoke and recreate sessions if cookies have appeared in shell history or agent logs. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/transcribe.py:55
Finding
Unrestricted URL transcription can access private network resources and upload them to Alibaba Cloud<![CDATA[ ## Vulnerability Details **File Location**: `scripts/transcribe.py:55-74` **Vulnerability Type**: Server-side request forgery and unintended data exfiltration **Risk Level**: High ### Vulnerable Code ```python def _is_url(s): return isinstance(s, str) and s.startswith(("http://", "https://")) def _download_url(url, verbose=True): """用 yt-dlp 下载链接背后的音视频到临时目录,返回下载到的本地文件路径列表。 支持小宇宙 episode、YouTube、B站等 yt-dlp 能解析的源。 下载到 URL_DOWNLOAD_DIR,文件保留(用户可手动清理)。 """ URL_DOWNLOAD_DIR.mkdir(parents=True, exist_ok=True) if verbose: print(f"下载链接(yt-dlp): {url}") before = set(URL_DOWNLOAD_DIR.iterdir()) cmd = [ "yt-dlp", "--no-playlist", "-x", "--audio-format", "m4a", "-o", str(URL_DOWNLOAD_DIR / "%(title)s.%(ext)s"), url, ] result = subprocess.run(cmd, capture_output=True, text=True) ``` Downloaded files are subsequently supplied to `TingwuClient.transcribe()`, which uploads them to Alibaba OSS. ### Technical Analysis The only URL validation is a check for the `http://` or `https://` prefix. There is no restriction on loopback, link-local, private, reserved, or internal DNS destinations. Redirect targets are not validated either. `yt-dlp` supports direct media URLs and multiple extractor types, so a supplied URL may cause the host running the Skill to access resources unavailable to the external requester. If the response is recognized as media, the normal workflow then uploads it to Alibaba OSS for cloud transcription. This turns a network access flaw into a potential confidentiality breach. This behavior exceeds the minimum privilege required to transcribe public podcast and video URLs. ### Attack Path 1. An attacker provides the agent with a URL resolving to a loopback, private-network, link-local, or internal DNS address. 2. The Skill accepts it because it starts with `http://` or `https://`. 3. `yt-dlp` requests the target using the agent host's network access. 4. The target retu ...[truncated 618 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Default to a strict allowlist of supported public media domains. 2. Resolve hostnames before each request and reject: - Loopback addresses - RFC 1918 private addresses - Link-local addresses - Unique-local IPv6 addresses - Multicast, reserved, and unspecified addresses 3. Revalidate every redirect destination and protect against DNS rebinding. 4. Reject URLs containing embedded credentials or nonstandard schemes. 5. Run URL downloads in a sandbox with no access to loopback, metadata services, or private networks. 6. Require explicit user confirmation before uploading URL-derived content to Alibaba Cloud. 7. Log the final resolved public destination without logging credentials or signed query parameters. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/transcribe.py:59
Finding
Predictable shared temporary directory permits media disclosure and task poisoning<![CDATA[ ## Vulnerability Details **File Location**: `scripts/transcribe.py:13-14,59-87` **Vulnerability Type**: Unsafe temporary-file handling **Risk Level**: Medium ### Vulnerable Code ```python # URL 下载的音频临时存放目录 URL_DOWNLOAD_DIR = Path(tempfile.gettempdir()) / "tingwu_downloads" ``` ```python def _download_url(url, verbose=True): """用 yt-dlp 下载链接背后的音视频到临时目录,返回下载到的本地文件路径列表。 支持小宇宙 episode、YouTube、B站等 yt-dlp 能解析的源。 下载到 URL_DOWNLOAD_DIR,文件保留(用户可手动清理)。 """ URL_DOWNLOAD_DIR.mkdir(parents=True, exist_ok=True) if verbose: print(f"下载链接(yt-dlp): {url}") before = set(URL_DOWNLOAD_DIR.iterdir()) cmd = [ "yt-dlp", "--no-playlist", "-x", "--audio-format", "m4a", "-o", str(URL_DOWNLOAD_DIR / "%(title)s.%(ext)s"), url, ] result = subprocess.run(cmd, capture_output=True, text=True) if result.returncode != 0: raise RuntimeError(f"yt-dlp 下载失败: {result.stderr.strip()[:200] or result.stdout.strip()[:200]}") new_files = [f for f in (set(URL_DOWNLOAD_DIR.iterdir()) - before) if f.suffix.lower() in AUDIO_EXTS] if not new_files: # 兜底:取目录里最新的音视频文件 new_files = sorted( [f for f in URL_DOWNLOAD_DIR.iterdir() if f.suffix.lower() in AUDIO_EXTS], key=lambda f: f.stat().st_mtime, reverse=True, )[:1] if not new_files: raise RuntimeError(f"yt-dlp 未下载到音视频文件: {url}") ``` ### Technical Analysis All runs and users share the predictable path `/tmp/tingwu_downloads`. The directory is created without explicitly restrictive permissions, files are intentionally retained, and filenames are derived from remote media titles. The fallback behavior selects the newest supported file already present in that shared directory whenever no newly created directory entry is detected. This can happen when a download overwrites or reuses an existing output name. A local attacker can pre-populate or manipulate the shared directory so that unrel ...[truncated 1013 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Create a unique per-run directory with `tempfile.TemporaryDirectory()`. 2. Ensure the directory is owner-only (`0700`) and downloaded files are owner-only (`0600`). 3. Pass a unique identifier in the `yt-dlp` output template. 4. Determine downloaded output through `yt-dlp`'s structured output rather than directory-difference or newest-file heuristics. 5. Reject symlinks and verify that the selected result is a regular file inside the expected temporary directory. 6. Delete the temporary directory automatically after upload, including on exceptions. 7. Add explicit size and duration limits before downloading and before cloud upload. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/watch_active.sh:85
Finding
Task identifier injection permits arbitrary AppleScript execution<![CDATA[ ## Vulnerability Details **File Location**: `scripts/watch_active.sh:16,85-90,103-106` **Vulnerability Type**: AppleScript command injection **Risk Level**: Medium ### Vulnerable Code ```bash TASK_ID="${1:?用法: $0 <task_id> [--interval N] [--timeout N] [--no-notify]}" ``` ```bash if echo "$OUTPUT" | grep -qE '正在生成输出'; then log "✅ 任务已完成,开始生成输出文件..." FINAL_OUTPUT="$(python3 "$SCRIPT_DIR/poll_tasks.py" --once --task-id "$TASK_ID" 2>&1 || true)" log " 最终输出: $(echo "$FINAL_OUTPUT" | grep -E '转录完成|AI 总结' | head -3 | tr '\n' ' ')" if [[ $NOTIFY -eq 1 ]] && command -v osascript >/dev/null 2>&1; then osascript -e "display notification \"任务 ${TASK_ID:0:12}… 已完成\" with title \"通义听悟\" subtitle \"转录完成\"" 2>/dev/null || true fi ``` The failure branch contains the same pattern: ```bash if [[ $NOTIFY -eq 1 ]] && command -v osascript >/dev/null 2>&1; then osascript -e "display notification \"任务 ${TASK_ID:0:12}… 转录失败\" with title \"通义听悟\"" 2>/dev/null || true fi ``` ### Technical Analysis `TASK_ID` is taken directly from the first command-line argument and interpolated into AppleScript source code. Shell quoting prevents ordinary shell expansion of characters inside the value, but it does not escape the value for the AppleScript grammar. A crafted task identifier containing a quote and additional AppleScript statements can terminate the notification string and append commands such as `do shell script`. The injected AppleScript executes with the privileges of the user running the watcher. The same identifier is also used in the log filename, so path separators can alter the intended output path where the referenced parent directories already exist. ### Attack Path 1. An attacker causes an agent or user to invoke `watch_active.sh` with a crafted task identifier. 2. The watcher reaches either its completion or failure notification branch. 3. The crafted identifier is concatenated into the argument passed to `osascript -e`. 4. AppleScript parses t ...[truncated 585 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Strictly validate task identifiers against the actual service format, such as `^[A-Za-z0-9_-]{1,128}$`. 2. Do not concatenate untrusted values into AppleScript source. 3. Pass notification data through a mechanism that treats it purely as data, or escape it with a dedicated AppleScript-safe encoder. 4. Disable notifications by default in unattended agent workflows. 5. Derive log filenames from a cryptographic hash of the task ID rather than the raw value. 6. Verify that the resolved log path remains within the configured log directory. 7. Update or remove the helper's unsupported `poll_tasks.py --once --task-id` arguments, because the audited Python parser does not define them. ]]>

T08 · Insecure Dependencies

Warning
Location
config/requirements.txt:1
Finding
Dependencies use open-ended version ranges without hashes or a lock file<![CDATA[ ## Vulnerability Details **File Location**: `config/requirements.txt:1-6` **Vulnerability Type**: Non-reproducible and insufficiently constrained dependencies **Risk Level**: Medium ### Vulnerable Code ```text requests>=2.28.0 oss2>=2.18.0 # yt-dlp 用于"给链接自动下载"(小宇宙/YouTube/B站等);也可用 brew install yt-dlp yt-dlp>=2024.0.0 # playwright 用于内置登录脚本 login_pw.py;装完还需: playwright install chromium playwright>=1.40.0 ``` ### Technical Analysis Every dependency has only a lower bound. Installation may therefore select any future release available from the configured package index. No lock file or package hashes are provided, and Playwright additionally downloads a browser binary through a separate installation step. This makes the reviewed source insufficient to determine the code that will actually execute after installation. A compromised maintainer release, package-index account, mirror, or future malicious update would be accepted automatically. These packages operate in sensitive contexts: Playwright receives the Alibaba username and password, `requests` and `oss2` process authentication material and uploads, and `yt-dlp` handles attacker-influenced URLs and downloaded files. ### Attack Path 1. A dependency account, package-index entry, mirror, or future release is compromised. 2. A malicious version satisfying the broad `>=` constraint is published. 3. A user runs `pip install -r config/requirements.txt`. 4. The resolver installs the malicious version because it satisfies the declared lower bound. 5. Package installation or runtime imports execute attacker-controlled code. 6. The malicious component reads credentials, cookies, local media, or transcripts and transmits them externally. ### Impact Assessment A compromised dependency executes with the full privileges of the Skill process. It can access Alibaba credentials, authenticated cookies, all selected media files, transcript archives, and network resources reachable from the host. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin exact, reviewed versions for all direct dependencies. 2. Generate and commit a lock file containing transitive dependencies. 3. Require hashes during installation, for example with a hash-locked requirements file and `pip --require-hashes`. 4. Use a trusted package index and disable unexpected extra indexes. 5. Pin and verify the Playwright browser revision and its download source. 6. Add automated dependency vulnerability and provenance scanning. 7. Test upgrades in isolation and update pins only after review. ]]>
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
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (30)

Lp3

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding
The skill exercises sensitive capabilities including filesystem access, shell execution, and network operations, but does not declare them explicitly. This reduces informed consent and makes it easier for an agent or user to invoke behavior with broader access than expected, especially because the skill also handles credentials, cookies, and uploads local media to third-party services.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The stated purpose is cloud transcription, but the documented behavior goes significantly beyond that: automated login, credential ingestion from .env, cookie extraction and persistence, quota tracking, URL downloading via yt-dlp, asynchronous task management, deletion of cloud tasks, and calling external summarization tooling. This mismatch increases the risk that users authorize a seemingly narrow transcription skill that in practice performs account automation, persistent secret handling, and broad local/network side effects.

Context-Inappropriate Capability

Medium
Confidence
91% confidence
Finding
The daily check-in feature automates account activity to claim service quota, which is outside the core transcription function. In an agent context, scheduled execution of account actions increases risk of unintended policy violations, unnecessary credential exposure, and background activity users may not realize is occurring.

Context-Inappropriate Capability

Medium
Confidence
94% confidence
Finding
The script reads a username and password from a local .env file and then uses them to automate login to a third-party account service. In the context of an ASR skill, handling long-lived account credentials and converting them into reusable authenticated session state exceeds the narrowly justified need to transcribe media and increases the blast radius if the host or skill files are accessed by another process or user.

Context-Inappropriate Capability

High
Confidence
98% confidence
Finding
The script persists a broad cookie set from multiple Alibaba-related domains (aliyun.com, taobao.com, alicdn.com) to disk, creating a reusable authenticated session outside the browser. Those cookies may grant access beyond the transcription feature, enabling session hijacking or lateral use against related services if the file is copied, read by another local process, or accidentally committed.

Context-Inappropriate Capability

Medium
Confidence
83% confidence
Finding
This polling script for cloud ASR completion automatically invokes an unrelated external summarization script from a sibling skill directory. That creates an unexpected code-execution trust boundary: any user who runs polling also runs whatever code exists at that path, which could be modified independently or replaced in a compromised workspace. In skill context, this is more dangerous because the feature is not essential to task polling and may surprise operators who only expected transcription post-processing.

Context-Inappropriate Capability

Medium
Confidence
91% confidence
Finding
The compression path performs destructive local changes: it deletes original PNG files and rewrites Markdown references automatically based on inferred paths. Because these file modifications occur without an explicit confirmation boundary, a user invoking transcription-adjacent functionality could unexpectedly lose originals or alter nearby documentation files.

Description-Behavior Mismatch

Medium
Confidence
91% confidence
Finding
The skill description says it performs cloud transcription, but the implementation additionally accepts arbitrary HTTP/HTTPS URLs and uses yt-dlp to fetch media from many supported sites. This materially expands the capability and trust boundary: the skill can initiate outbound network access to third-party content sources, process untrusted remote media, and persist downloads locally without that behavior being clearly disclosed in the declared skill behavior.

Missing User Warnings

Medium
Confidence
84% confidence
Finding
The changelog documents a workflow that automatically fills credentials from `.env` and persists authenticated cookies to disk, but it does not mention safeguards such as encryption, restricted file permissions, secure storage, or explicit user warnings about handling session secrets. Even though this is documentation rather than executable code, it describes a pattern that can expose reusable authentication material if operators follow it without additional controls.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The documentation says the skill performs cloud transcription but does not prominently warn that user audio/video and related derived content are uploaded to Alibaba Cloud/OSS for processing. This is a meaningful privacy and compliance risk because users may supply sensitive recordings without understanding they leave the local environment and are handled by a third party.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The skill stores credentials in config/.env and persists login cookies to local files, but the description does not present this as a prominent security warning. Local secret material can be exfiltrated by other tools, accidentally backed up, or exposed through weak file permissions, and persisted session cookies may allow account access without re-authentication.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The document instructs use of authentication cookies for `.aliyun.com` and describes uploading local audio/video content to remote cloud APIs, but it provides no privacy, consent, or data-handling warning. In a skill specifically intended for cloud transcription of user media, this omission is dangerous because agents may transmit sensitive recordings and session credentials without making the disclosure risk clear to users.

Missing User Warnings

Low
Confidence
88% confidence
Finding
The reference lists a deletion endpoint without any caution that invoking it can permanently remove transcription records. Even in documentation, omission of that warning can lead an agent or integrator to call a destructive API unintentionally, causing loss of user data or audit history.

Missing User Warnings

Low
Confidence
88% confidence
Finding
The script persists account/quota history, including a full `account` object, to a local JSONL file without any user-facing notice, minimization, or access control. While this is not remote code execution, it can expose account metadata or usage history to other local users, backups, or logs if the host is shared or compromised.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The core workflow uploads local audio/video content to Alibaba Cloud OSS/Tingwu, which may contain sensitive meetings, personal data, or regulated information. Although cloud upload is inherent to the skill's purpose, the code shown does not provide an explicit warning/consent checkpoint before transmission, increasing privacy and compliance risk through accidental disclosure.

Missing User Warnings

Low
Confidence
86% confidence
Finding
The slide download routine fetches remote images and writes them to local directories without a strong user-disclosure boundary. While this is not inherently malicious, it can surprise users by creating files on disk and consuming storage, especially when they expected only a transcript retrieval operation.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The compression routine not only creates replacement files but also deletes original PNGs and edits Markdown references automatically. This combination of destructive changes and inferred file targeting can cause data loss or unintended modification of local project content if run in the wrong directory or on unexpected inputs.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The script uploads local audio/video to a cloud transcription service, downloads derived results, and stores markdown and archives on disk, but there is no explicit runtime consent or warning about data leaving the local system and being retained locally. In a transcription skill, this context is particularly sensitive because inputs may contain private conversations, meetings, or regulated data.

Missing User Warnings

Low
Confidence
90% confidence
Finding
URL-sourced media is downloaded into a temp-directory subfolder and intentionally retained for manual cleanup, but the user is not clearly warned at runtime that remote content will remain on disk. This can expose sensitive or copyrighted media to unintended local persistence, especially on shared systems.

Credential Access

High
Category
Privilege Escalation
Content
## [0.4.0] - 2026-08-17

### Added
- 内置 Playwright 登录脚本 `scripts/login_pw.py`:一条命令完成"开浏览器 → 自动填 .env 凭证 → 等待登录 → cookie 落盘"。经 `context.cookies()` 取含 HttpOnly 的 `login_aliyunid_ticket`(此前的 MCP Playwright `document.cookie` 路径拿不到),cookie 值全程不经过 stdout/对话记录;出现滑块时人工在可见窗口完成即可
- SKILL.md 登录章节重写:内置脚本为方式一(推荐),MCP Playwright 手工流程降为方式二兜底;每日签到流程同步改用 `login_pw.py`
- `requirements.txt` 增加 `playwright`
Confidence
93% confidence
Finding
This entry describes automated credential use from `.env` plus extraction and persistence of HttpOnly authentication cookies such as `login_aliyunid_ticket`. Persisting these tokens creates a credential-access risk because anyone who can read the stored cookie file may be able to hijack the authenticated session and access the user's cloud transcription account.

Credential Access

High
Category
Privilege Escalation
Content
daily_checkin.py    ← 额度检查 + 记录
    check_auth.py       ← 认证检查
  config/
    .env                ← 账号密码凭证(gitignore,不提交)
    .env.example        ← 账号密码模板
    cookies.json        ← 登录 Cookie(gitignore,不提交)
    cookie.example.json ← Cookie 文件模板
Confidence
90% confidence
Finding
The skill explicitly relies on locally stored account credentials and session cookies, which are high-value secrets. In the context of an agent skill with file read/write and shell capabilities, this creates a real credential exposure risk if files are mishandled, permissions are weak, logs leak content, or adjacent tools/processes access the same workspace.

Credential Access

High
Category
Privilege Escalation
Content
且 cookie 值全程不经过 stdout。

用法:
  python3 scripts/login_pw.py            # 从 config/.env 读凭证自动填充
  python3 scripts/login_pw.py --headless # 无头模式(不推荐,滑块验证需人工)

流程:
Confidence
88% confidence
Finding
The documented workflow explicitly instructs users to place credentials in config/.env for automated login. Even though the script avoids printing cookie values, encouraging plaintext credential storage in a skill-managed path materially increases the risk of credential disclosure through local compromise, backups, logs, or source-control mistakes.

Credential Access

High
Category
Privilege Escalation
Content
SKILL_ROOT = Path(__file__).resolve().parent.parent
COOKIE_PATH = SKILL_ROOT / "config" / "cookies.json"
ENV_PATH = SKILL_ROOT / "config" / ".env"

LOGIN_MARKER = "login_aliyunid_ticket"  # HttpOnly,登录态判定的锚点
Confidence
90% confidence
Finding
Defining a fixed path to config/.env inside the skill creates an expectation that sensitive credentials will be stored alongside skill assets. In a plugin/agent setting, colocated secrets are easier to discover, exfiltrate, or accidentally package than credentials held in a dedicated secrets facility.

Credential Access

High
Category
Privilege Escalation
Content
username, password = load_env()
    if not username or not password:
        print("!! config/.env 凭证缺失(TINGWU_USERNAME / TINGWU_PASSWORD)")
        sys.exit(1)
    print(f"[1] 凭证已加载 (用户名 {len(username)} 字符)")
Confidence
86% confidence
Finding
At runtime the script loads credentials from .env and uses them directly for login automation, confirming that the plaintext secret path is not merely documentation but an operational credential-access mechanism. This compounds the risk because compromise of the local file yields immediate account access rather than only configuration metadata.

Unpinned Dependencies

Low
Category
Supply Chain
Content
requests>=2.28.0
oss2>=2.18.0
# yt-dlp 用于"给链接自动下载"(小宇宙/YouTube/B站等);也可用 brew install yt-dlp
yt-dlp>=2024.0.0
Confidence
85% confidence
Finding
Using a lower-bounded but unpinned dependency for requests permits future installs to resolve to different versions, reducing reproducibility and making supply-chain review harder. In a network-facing transcription skill, dependency drift can silently introduce vulnerable or breaking versions into environments over time.

Static analysis

No suspicious patterns detected.