Back to skill

Security audit

Doubao Asr

Security checks for vulnerabilities and agentic risk

Overview

This skill performs disclosed cloud-based audio transcription using the user's Volcengine account, with no evidence of hidden exfiltration or persistence.

Install only if you are comfortable sending selected audio to Volcengine for processing. Use a dedicated TOS bucket, keep the Volcengine keys least-privileged, set a lifecycle rule for uploaded recordings, and avoid confidential audio unless Volcengine's retention and compliance terms fit your use case.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (13)

Tainted flow: 'put_url' from os.environ.get (line 257, credential/environment) → requests.put (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/transcribe.py (reported line 264)May include surrounding context.

python
for attempt in range(max_retries):
        try:
            with open(filepath, "rb") as f:
                resp = requests.put(
                    put_url, data=f,
                    headers={"Content-Type": content_type},
                    timeout=120,

Tainted flow: 'headers' from os.environ.get (line 327, 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/transcribe.py (reported line 366)May include surrounding context.

python
max_retries = 3
    for attempt in range(max_retries):
        try:
            resp = requests.post(cfg["submit"], headers=headers, json=body, timeout=30)
            status = resp.headers.get("X-Api-Status-Code", "")
            message = resp.headers.get("X-Api-Message", "")
            if status != "20000000":

Tainted flow: 'headers' from os.environ.get (line 327, 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/transcribe.py (reported line 394)May include surrounding context.

python
max_retries = 3
    for attempt in range(max_retries):
        try:
            resp = requests.post(cfg["recognize"], headers=headers, json=body, timeout=timeout)
            status = resp.headers.get("X-Api-Status-Code", "")
            message = resp.headers.get("X-Api-Message", "")
            if status == "20000003":

Tainted flow: 'headers' from os.environ.get (line 327, 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/transcribe.py (reported line 422)May include surrounding context.

python
max_net_errors = 3
    while elapsed < timeout:
        try:
            resp = requests.post(query_url, headers=headers, json={}, timeout=30)
        except requests.exceptions.RequestException as e:
            net_errors += 1
            if net_errors >= max_net_errors:

Tainted flow: 'headers' from os.environ.get (line 327, 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/transcribe.py (reported line 456)May include surrounding context.

python
cfg = TIERS[tier]
    headers = get_headers(request_id, cfg["resource_id"], sequence=None)
    try:
        resp = requests.post(cfg["query"], headers=headers, json={}, timeout=30)
    except requests.exceptions.RequestException as e:
        sys.exit(f"Query failed: {scrub_secrets(e)}")
    status = resp.headers.get("X-Api-Status-Code", "")

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 · SKILL.md (reported line 329)May include surrounding context.

md
**Error**: `API returned error: invalid API key`
**Cause**: Using old Speech console API key, or key from wrong console page. / 使用了旧版语音控制台的 API Key,或从错误的控制台页面获取。
**Solution**: Get API key from the NEW Doubao Speech console at `https://console.volcengine.com/speech/new/`, NOT `/speech/app`. / 从新版豆包语音控制台 `https://console.volcengine.com/speech/new/` 获取 API Key,不是 `/speech/app`。

**Error**: `Unsupported audio format` or transcription returns empty
**Cause**: Audio file is corrupted, or format not in supported list. / 音频文件损坏,或格式不在支持列表中。

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 · SKILL.md (reported line 337)May include surrounding context.

md
**Error**: `Missing: VOLCENGINE_ACCESS_KEY_ID...` after running `source .env`
**Cause**: `source .env` sets variables in the current shell but does not export them to child processes. The script runs as a subprocess and cannot see unexported variables. / `source .env` 仅在当前 shell 设置变量但不导出,脚本作为子进程无法读取未导出的变量。
**Solution**: Use `set -a && source .env && set +a` to auto-export all variables, or use `export` before each variable in your `.env` file. / 使用 `set -a && source .env && set +a` 自动导出所有变量,或在 `.env` 文件中每行变量前加 `export`。

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

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

Content

Scanner excerpt · scripts/transcribe.py (reported line 610)May include surrounding context.

python
# --format only decides which codec label to send.
        #
        # Previously --format took precedence, so it doubled as an override of
        # the "is this an audio file" check: `transcribe.py ~/.ssh/id_rsa
        # --format mp3` would upload that file to object storage and hand it to
        # a third-party service. A flag that names a codec must not also grant
        # permission to send an arbitrary local file.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README prominently advertises transcription features but does not clearly disclose near the top-level usage flow that local audio files are uploaded to external Volcengine/TOS infrastructure for processing. Users may reasonably assume a local-only transcription workflow and unknowingly transmit sensitive recordings, creating privacy, confidentiality, and compliance risk for meetings, calls, or regulated audio.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
92% confidence
Finding

This skill transmits user-supplied audio URLs and associated transcription metadata to an external third-party speech service. In a skill context, external data transmission is security-relevant because users may not expect local files to be uploaded off-host, and the content can include sensitive audio.

Content

Scanner excerpt · scripts/transcribe.py (reported line 366)May include surrounding context.

python
max_retries = 3
    for attempt in range(max_retries):
        try:
            resp = requests.post(cfg["submit"], headers=headers, json=body, timeout=30)
            status = resp.headers.get("X-Api-Status-Code", "")
            message = resp.headers.get("X-Api-Message", "")
            if status != "20000000":

External Transmission

Medium
Category
Data Exfiltration
Confidence
92% confidence
Finding

The express recognition path sends audio references and request content to a third-party cloud ASR provider. This is dangerous in environments where the tool may be run on confidential recordings, because the skill’s purpose is to export content for remote processing.

Content

Scanner excerpt · scripts/transcribe.py (reported line 394)May include surrounding context.

python
max_retries = 3
    for attempt in range(max_retries):
        try:
            resp = requests.post(cfg["recognize"], headers=headers, json=body, timeout=timeout)
            status = resp.headers.get("X-Api-Status-Code", "")
            message = resp.headers.get("X-Api-Message", "")
            if status == "20000003":

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/transcribe.py (reported line 422)May include surrounding context.

python
max_net_errors = 3
    while elapsed < timeout:
        try:
            resp = requests.post(query_url, headers=headers, json={}, timeout=30)
        except requests.exceptions.RequestException as e:
            net_errors += 1
            if net_errors >= max_net_errors:

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/transcribe.py (reported line 456)May include surrounding context.

python
cfg = TIERS[tier]
    headers = get_headers(request_id, cfg["resource_id"], sequence=None)
    try:
        resp = requests.post(cfg["query"], headers=headers, json={}, timeout=30)
    except requests.exceptions.RequestException as e:
        sys.exit(f"Query failed: {scrub_secrets(e)}")
    status = resp.headers.get("X-Api-Status-Code", "")

Static analysis

No suspicious patterns detected.