Back to skill

Security audit

Lyric Sense

Security checks for vulnerabilities and agentic risk

Overview

This lyric skill should go to Review because its bundled local API exposes broad file, database, network, and media-writing capabilities with weak defaults and incomplete disclosure.

Install only after reviewing the local API exposure. Prefer not to run the bundled LrcApi on a public interface; if self-hosting, bind to localhost, require strong authentication, avoid latest Docker tags, and do not mount sensitive directories. Be aware that online searches send artist and song title data to api.lrc.cx and, in the included HTML UI, also to corsproxy.io.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/LrcApi/api/source.py:65
Finding

Unauthenticated Arbitrary Local File Disclosure

Content
View full analysis
', endpoint='file_viewer_endpoint') @v1_bp.route('/file/', endpoint='file_viewer_endpoint') @require_auth_decorator(permission='r') def file_viewer(filename): ALLOWED_EXTENSIONS = ('.mp3', '.flac', '.wav', '.ape', '.ogg', '.m4a', '.aac', '.wma', '.mp4', '.m4p', '.m4b', 'txt', 'lrc', 'webp', 'jpg', 'jpeg', 'png', 'bmp', 'gif', 'webp', 'svg', 'ico', 'mp4', 'webm', 'mkv', 'avi', 'mov', 'wmv', 'flv', 'f4v', 'f4p', 'f4a', 'f4b', 'm4v', 'm4r', 'm4p', 'm4b',) if filename.lower().endswith(ALLOWED_EXTENSIONS): try: return send_from_directory(os.path.dirname(filename), os.path.basename(filename)) except FileNotFoundError: abort(404) ``` The relevant authentication behavior is: ```python if not args("auth"): if permission == 'r': return 1 ``` The default configuration sets authentication to an empty value: ```python DEFAULT_DATA = { "server": { "ip": "*", "port": 28883 }, "auth": "", ``` ### Technical Analysis The route accepts a complete filesystem path from the URL and splits it into an attacker-controlled directory and basename. `send_from_directory()` prevents traversal outside the directory supplied to it, but that protection is ineffective because the directory itself is attacker-controlled. The extension check is not a safe authorization boundary. It permits numerous extensions, including `txt`, `lrc`, images, video, and audio formats. It also omits leading periods from several entries, ...[truncated 1307 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/LrcApi/api/lyrics.py:30
Finding

Unauthenticated Filesystem Probing and Local Lyrics Disclosure

Content
View full analysis
0: return lrc_in except: pass ``` Authentication is bypassed for read operations when no key is configured: ```python if not args("auth"): if permission == 'r': return 1 ``` ### Technical Analysis The public lyrics endpoint accepts a caller-supplied `path`. It derives an adjacent `.lrc` path, checks whether that path exists, reads it, and returns its content. It also attempts to open the caller-selected media file and extract embedded lyrics from its metadata. No fixed media root, canonical-path validation, or path authorization is applied. Under the default empty-authentication configuration, the route is available without credentials. Behavioral differences can also reveal whether targeted files exist or contain supported metadata, enabling filesystem probing even when useful lyrics are not returned. ### Attack Path 1. The LrcApi server is started without an auth ...[truncated 771 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/LrcApi/api/file.py:14
Finding

Arbitrary Network Request and Filesystem Write Endpoint

Content
View full analysis
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/LrcApi/mod/auth/authentication.py:36
Finding

Broken Role Authorization Grants Every Permission to Any Valid Role

Content
View full analysis
str: if not name: return '' auth_dict: dict = args("auth") if isinstance(auth_dict, dict): return auth_dict.get(name, '') elif name == args("auth"): return "all" def has_permission(supply: str, require: str) -> bool: if not supply: return False elif supply == "all": return True else: #supply_set, require_set = set(supply), set(require) #return require_set.issubset(supply_set) return True ``` ### Technical Analysis `get_permission()` supports dictionary-based credentials associated with permission strings. However, `has_permission()` returns `True` for every nonempty permission value, irrespective of the permission required by the endpoint. The intended subset check is present but commented out. As a result, a credential intended to grant only read access is treated as sufficient for routes requiring write or delete permissions. This affects all routes that rely on `require_auth_decorator()` and specify permissions such as `rw` or `rwd`. ### Attack Path 1. An administrator configures multiple credentials or roles, including a low-privilege read-only role. 2. An attacker obtains or legitimately holds that read-only credential. 3. The attacker invokes a route requiring `rw` or `rwd`. 4. `get_permission()` returns a nonempty permission string. 5. `has_permission()` reaches its final branch and unconditionally returns `True`. 6. The privileged endpoint executes despite the caller lacking the required role. ### Impact Assessment Any valid configured role is effectively an all-powerful role. A nominally read-only caller can potentially: - Modify media tags through write routes. - Invoke file u ...[truncated 356 chars]
Remediation
View remediation
bool: if not supply: return False if supply == "all": return True return set(require).issubset(set(supply)) ``` Additional hardening should include: 1. Define a documented permission model rather than relying on arbitrary characters. 2. Reject unknown permission values during configuration loading. 3. Use constant endpoint-specific roles for sensitive file and database operations. 4. Add negative tests proving that read-only credentials cannot invoke `rw`, `rwd`, or delete operations. 5. Deny access on permission parsing errors. 6. Log authorization failures without logging credential values. ]]>

other

Warning
Location
index.html:371
Finding

Undisclosed Third-Party Relay of User Search Queries

Content
View full analysis
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
SKILL.md:61
Finding

Mutable Container Image and Broad Host Exposure in Deployment Instructions

Content
View full analysis
Remediation
View remediation
`. 2. Document the source commit and build process corresponding to that digest. 3. Publish the port only on loopback unless remote access is explicitly needed: ```bash docker run -d -p 127.0.0.1:8080:8080 repository@sha256: ``` 4. Run the container as a non-root user. 5. Use a read-only root filesystem and drop unnecessary Linux capabilities. 6. Avoid mounting sensitive host directories. 7. Require authentication before permitting non-loopback deployment. 8. Add image signature verification and a software bill of materials to the release process. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (136)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
修改 `index.html` 中的 API 地址:

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The endpoint accepts caller-supplied SQL and executes it directly against the application's SQLite database with no allowlist, parameterization, or read-only restriction. Although authentication is required, any holder of 'rw' access can run arbitrary destructive or exfiltrating statements, making this effectively a built-in arbitrary database access primitive.

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/LrcApi/api/waf.py (reported line 89)May include surrounding context.

python
DATAS = [
        "/../../",  # 目录穿越
        "/proc/self/maps",  # 读取系统信息
        "/etc/passwd",  # 读取密码文件
        "/etc/shadow",  # 读取密码文件
        "php://input",  # PHP流协议
        "SELECT * FROM",  # SQL注入

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

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

Content

Scanner excerpt · scripts/LrcApi/api/waf.py (reported line 90)May include surrounding context.

python
"/../../",  # 目录穿越
        "/proc/self/maps",  # 读取系统信息
        "/etc/passwd",  # 读取密码文件
        "/etc/shadow",  # 读取密码文件
        "php://input",  # PHP流协议
        "SELECT * FROM",  # SQL注入
        "DROP TABLE",  # SQL注入

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
97% confidence
Finding

This is a true tool abuse risk because the script delegates dependency installation to an external tool in a way that can execute untrusted package code. In the context of an agent skill or automated build pipeline, auto-installing from requirements.txt makes the environment especially vulnerable to malicious or tampered dependencies.

Content

Scanner excerpt · scripts/LrcApi/buildup.py (reported line 10)May include surrounding context.

python
# 安装Pyinstaller及主程序依赖
# 必须在import项目中的模块之前执行,否则会出现找不到模块的错误
print("Installing dependencies...")
subprocess.run("pip install -r requirements.txt", shell=True)
subprocess.run("pip install pyinstaller", shell=True)

from mod.args import args

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% confidence
Finding

Installing pyinstaller on the fly is another instance of externally controlled tool execution that can introduce unreviewed code into the environment. The risk is somewhat lower than a whole requirements file, but still meaningful due to package-manager execution and supply-chain exposure.

Content

Scanner excerpt · scripts/LrcApi/buildup.py (reported line 11)May include surrounding context.

python
# 必须在import项目中的模块之前执行,否则会出现找不到模块的错误
print("Installing dependencies...")
subprocess.run("pip install -r requirements.txt", shell=True)
subprocess.run("pip install pyinstaller", shell=True)

from mod.args import args

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
98% confidence
Finding

This is a strong tool parameter abuse finding because a command string is assembled from potentially attacker-influenced values and executed through a shell. A malicious version argument or crafted path could alter the intended PyInstaller invocation and run arbitrary OS commands.

Content

Scanner excerpt · scripts/LrcApi/buildup.py (reported line 42)May include surrounding context.

python
options = generate_add_data_options("src")
command = f"pyinstaller -F -i logo.png {options} app.py -n {PACK_NAME}"
subprocess.run(command, shell=True)

Instruction Override

High
Category
Prompt Injection
Confidence
70% confidence
Finding

This pattern attempts to override system instructions or ignore safety constraints. Without LLM analysis, manual review is recommended.

Content

Scanner excerpt · scripts/LrcApi/mod/args/__init__.py (reported line 14)May include surrounding context.

python
# 添加一个 `--port` 参数,默认值28883
parser.add_argument('--port', type=int, default=28883, help='应用的运行端口,默认28883')
parser.add_argument('--auth', type=str, default='', help='用于验证Header.Authentication字段,建议纯ASCII字符')
parser.add_argument("--debug", action="store_true", help="Enable debug mode")
parser.add_argument('--ip', type=str, default='*', help='服务器监听IP,默认*')
parser.add_argument('--token', type=str, default='', help='锂API接口的Token')
parser.add_argument('--ai-type', type=str, default='openai', help='AI类型,默认openai')

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The permission-check helper is effectively bypassed because any non-empty supplied permission returns True unless it is empty. That means a user with any recognized token or permission string can satisfy any required permission, including write or administrative actions, resulting in privilege escalation and broken authorization across the API.

Content

No source excerpt is available for this finding.

eval() call detected

High
Category
Dangerous Code Execution
Confidence
99% confidence
Finding

The code calls eval() on ASF tag data when the WM/Picture value is not already bytes. Tag metadata is attacker-controlled if a user opens or scans an untrusted media file, so this can lead to arbitrary Python code execution during metadata parsing.

Content

Scanner excerpt · scripts/LrcApi/mod/music_tag/asf.py (reported line 28)May include surrounding context.

python
if "WM/Picture" in afile.mfile.tags:
        p = afile.mfile.tags["WM/Picture"][0].value
        if not isinstance(p, bytes):
            p = eval(p)
        try:
            artwork = Artwork(p)
        except OSError:

Missing User Warnings

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

This finding refers to the same unsafe behavior as AST2: eval() is used on metadata read from the file. In this context, the lack of any warning is secondary; the real issue is that parsing a crafted media tag can execute arbitrary code when the library processes the file.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The natural-language content throughout the README is presented in Chinese, and there is no indication that users may choose another language or that the skill is intentionally limited to a Chinese-speaking region. Under the stated policy, forcing a specific language without user opt-in is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding

The README instructs users to pull a Docker image using the floating latest tag, which makes builds non-reproducible and allows the image contents to change without notice. If the upstream image is replaced, compromised, or updated incompatibly, users may run unreviewed code from a different image than expected.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
91% confidence
Finding

The README includes client-side fetch examples to https://api.lrc.cx/lyrics, which causes user-supplied song and artist queries to be transmitted to a third-party endpoint. In context this is expected functionality, but it still creates data egress, dependency, and trust risks if users are not clearly informed or if the remote API is compromised or unavailable.

Content

Scanner excerpt · README.md (reported line 87)May include surrounding context.

javascript
// 获取歌词
fetch('https://api.lrc.cx/lyrics?artist=颜人中&title=晚安')

// 获取封面
fetch('https://api.lrc.cx/cover?artist=颜人中&title=晚安')

External Transmission

Medium
Category
Data Exfiltration
Confidence
91% confidence
Finding

The fetch example to https://api.lrc.cx/cover similarly transmits user song/artist data to an external service and relies on an untrusted remote response for cover retrieval. In this skill's context that behavior is functional rather than overtly malicious, but it is still a genuine external transmission risk that should be disclosed and optionally avoidable.

Content

Scanner excerpt · README.md (reported line 90)May include surrounding context.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger phrases are broad everyday music terms such as '歌词', '播放音乐', and 'lyrics', which can cause accidental invocation during normal conversation. In an agent ecosystem, overly broad triggers increase the chance of unintended network requests or UI actions, especially because this skill can contact an external API by default.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill defaults to a public API and explicitly encourages its use without warning that song titles and artist queries will be transmitted to a third-party service. Even if the data is not highly sensitive, user media preferences, listening habits, and timing metadata can still be privacy-relevant, and omission of notice prevents informed consent.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
94% confidence
Finding

The skill documentation directs the agent to send user-supplied artist and song title data to an external public endpoint (api.lrc.cx). This creates a real external data transmission path to a third party, with privacy implications and dependency on an external service outside the user's control.

Content

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

使用免费公开 API,无需部署:

text
歌词: https://api.lrc.cx/lyrics?artist={歌手}&title={歌名}
封面: https://api.lrc.cx/cover?artist={歌手}&title={歌名}

External Transmission

Medium
Category
Data Exfiltration
Confidence
94% confidence
Finding

The cover-art endpoint also sends artist and title query data to the same public third-party service, creating an additional external transmission channel. Even though the transmitted values are limited, the default behavior still exposes user requests and usage patterns to an external operator.

Content

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

text
歌词: https://api.lrc.cx/lyrics?artist={歌手}&title={歌名}
封面: https://api.lrc.cx/cover?artist={歌手}&title={歌名}

本地部署 (推荐)

Rp1

Medium
Category
MCP Rug Pull
Confidence
75% confidence
Finding

Docker image references without a specific tag (:latest is implicit) or digest (@sha256:...) can be silently replaced by a malicious image.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
75% confidence
Finding

Docker image references without a specific tag (:latest is implicit) or digest (@sha256:...) can be silently replaced by a malicious image.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
75% confidence
Finding

Docker image references without a specific tag (:latest is implicit) or digest (@sha256:...) can be silently replaced by a malicious image.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
75% confidence
Finding

Docker image references without a specific tag (:latest is implicit) or digest (@sha256:...) can be silently replaced by a malicious image.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
75% confidence
Finding

Docker image references without a specific tag (:latest is implicit) or digest (@sha256:...) can be silently replaced by a malicious image.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
75% confidence
Finding

Docker image references without a specific tag (:latest is implicit) or digest (@sha256:...) can be silently replaced by a malicious image.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.dynamic_code_execution, suspicious.exposed_secret_literal

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
scripts/LrcApi/mod/music_tag/asf.py:28

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
scripts/LrcApi/mod/args/__init__.py:134

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
scripts/LrcApi/mod/auth/webui.py:35