Back to skill

Security audit

ncm-cli setup

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly does what it claims, but it can make system-level installs and store API credentials without enough user review or secret-handling guidance.

Review the exact install commands before running this skill. Prefer pinning or verifying the npm package, avoid running the mpv installer on systems where you do not want package-manager changes, confirm any sudo or repository-enabling step manually, and treat the privateKey and login session as sensitive credentials.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T08 · Insecure Dependencies

Warning
Location
SKILL.md:19
Finding

Unpinned Global npm Dependency Installation

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, line 19
Vulnerability Type: Unpinned third-party dependency installed globally
Risk Level: Medium

bash
npm install -g @music163/ncm-cli

Technical Analysis

The Skill instructs users to install the latest available release of @music163/ncm-cli globally without specifying an exact version or verifying package integrity or provenance. Because npm packages can execute lifecycle scripts during installation, the effective code executed by this instruction can change after the Skill has been audited.

Global installation expands the potential impact because the package and its executable are placed in the user's global npm environment. The project provides neither a lockfile nor a reviewed copy of the dependency, so the installed implementation cannot be validated from the audited artifact alone.

This finding represents supply-chain exposure rather than evidence that the current npm package is malicious.

Attack Path

  1. An attacker compromises the npm package, a maintainer account, or a future package release.
  2. The attacker publishes a malicious version under the legitimate package name.
  3. A user follows the Skill instruction and runs the unpinned global installation command.
  4. npm resolves the mutable latest release and may execute attacker-controlled lifecycle scripts during installation.
  5. The installed executable subsequently runs with the user's privileges.
  6. The user follows later instructions to configure an application ID, private key, and login session, potentially exposing those assets to the compromised dependency.

Impact Assessment

Exploitation could permit arbitrary code execution with the privileges of the user running npm. The affected scope may include files and credentials accessible to that user, the global npm environment, and sensitive values later supplied to ncm-cli, including the application private key and auth ...[truncated 256 chars]

Remediation
View remediation

Remediation Suggestions

  1. Pin the dependency to an exact, reviewed version, for example:
    bash
    npm install -g @music163/ncm-cli@X.Y.Z
    
  2. Verify the selected release's npm provenance, publisher identity, and expected integrity before recommending it.
  3. Prefer a project-local installation with a committed lockfile over a global installation where operationally practical.
  4. In automated deployments, use a lockfile-based installation workflow such as npm ci.
  5. Review package lifecycle scripts and consider disabling them with --ignore-scripts if they are not required.
  6. Document the expected package registry and prevent dependency resolution through untrusted registry mirrors.
  7. Re-audit the dependency before changing the pinned version.
  8. Avoid entering private keys or login credentials until the installed binary and its provenance have been verified.
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
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (22)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
97% confidence
Finding

shell=True is a classic dangerous parameter because it routes command execution through the shell, enabling parsing of metacharacters, command chaining, and dependence on shell/PATH behavior. Even with hardcoded strings today, this helper centralizes unsafe execution for all privileged install operations, so the skill context makes the issue more serious than a generic utility script.

Content

Scanner excerpt · scripts/install_mpv.py (reported line 14)May include surrounding context.

python
def run(cmd, check=True):
    result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
    if check and result.returncode != 0:
        print(f"Error: {result.stderr.strip()}", file=sys.stderr)
        sys.exit(1)

Chaining Abuse

High
Category
Tool Misuse
Confidence
93% confidence
Finding

Chaining apt update and apt install with && in a shell command bundles multiple privileged actions into one opaque execution step. This is dangerous because it reduces validation points, complicates error handling and auditing, and depends on shell semantics in a script already using shell=True.

Content

Scanner excerpt · scripts/install_mpv.py (reported line 75)May include surrounding context.

python
if distro in ("ubuntu", "debian", "linuxmint", "pop"):
        print("Installing mpv via apt...")
        run("sudo apt-get update -q && sudo apt-get install -y mpv")
    elif distro in ("fedora",):
        print("Installing mpv via dnf...")
        run("sudo dnf install -y mpv")

Chaining Abuse

High
Category
Tool Misuse
Confidence
94% confidence
Finding

This shell chain first enables EPEL and then installs mpv, combining repository modification and package installation in one privileged command. The chaining increases risk because repository changes have system-wide trust implications, and shell-based combination makes the operation less transparent and harder to constrain safely.

Content

Scanner excerpt · scripts/install_mpv.py (reported line 81)May include surrounding context.

python
run("sudo dnf install -y mpv")
    elif distro in ("centos", "rhel", "rocky", "almalinux"):
        print("Installing mpv via yum (requires EPEL)...")
        run("sudo yum install -y epel-release && sudo yum install -y mpv")
    elif distro in ("arch", "manjaro", "endeavouros"):
        print("Installing mpv via pacman...")
        run("sudo pacman -S --noconfirm mpv")

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
88% confidence
Finding

The use of --noconfirm is a dangerous tool parameter because it suppresses an important human checkpoint before a privileged package operation. In this skill, the command is intended for installation, but the non-interactive flag makes erroneous or unexpected execution more harmful and less observable.

Content

Scanner excerpt · scripts/install_mpv.py (reported line 84)May include surrounding context.

python
run("sudo yum install -y epel-release && sudo yum install -y mpv")
    elif distro in ("arch", "manjaro", "endeavouros"):
        print("Installing mpv via pacman...")
        run("sudo pacman -S --noconfirm mpv")
    elif distro in ("opensuse", "opensuse-leap", "opensuse-tumbleweed", "sles"):
        print("Installing mpv via zypper...")
        run("sudo zypper install -y mpv")

Chaining Abuse

High
Category
Tool Misuse
Confidence
93% confidence
Finding

The fallback apt path chains update and install under sudo in one shell call, which increases the scope of any mistaken or unintended execution. In an automated skill, chaining is more dangerous because it minimizes opportunities for the operator to inspect or stop the process before the next privileged step runs.

Content

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

python
run("sudo zypper install -y mpv")
    elif shutil.which("apt-get"):
        print("Detected apt-based system. Installing mpv via apt...")
        run("sudo apt-get update -q && sudo apt-get install -y mpv")
    elif shutil.which("dnf"):
        print("Detected dnf. Installing mpv via dnf...")
        run("sudo dnf install -y mpv")

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
88% confidence
Finding

The fallback pacman install also uses the dangerous --noconfirm parameter, eliminating review before privileged execution. Because this path is chosen through package-manager detection logic, suppressing prompts increases the risk of autonomous misexecution.

Content

Scanner excerpt · scripts/install_mpv.py (reported line 96)May include surrounding context.

python
run("sudo dnf install -y mpv")
    elif shutil.which("pacman"):
        print("Detected pacman. Installing mpv via pacman...")
        run("sudo pacman -S --noconfirm mpv")
    else:
        print("ERROR: Could not detect package manager.")
        print("Please install mpv manually: https://mpv.io/installation/")

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill instructs the agent to run shell commands such as global npm installs, Python scripts, and login/setup commands, but it does not declare any explicit tool scope or allowed-tools boundary. This increases the chance of unintended command execution and makes the skill harder to constrain or review safely, especially because installation scripts can modify the host system.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The activation description is broad enough to trigger on generic install, configuration, or troubleshooting requests, which can cause the skill to engage in situations outside its safest intended scope. In practice, that broad trigger surface can lead to over-application of shell-based setup steps and increase the likelihood of unnecessary or risky system changes.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The document tells users to set a privateKey directly in CLI configuration without warning that this is a sensitive credential that may be exposed through shell history, terminal logging, screenshots, or insecure local config storage. Because the key likely authorizes access to the associated API account, disclosure could enable unauthorized use or abuse of the user's developer credentials.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
96% confidence
Finding

The helper executes shell commands with shell=True, which expands the attack surface to shell parsing, PATH hijacking, shell metacharacters, and command chaining. In this file the current command strings are hardcoded, so direct user-controlled injection is not evident, but because the script performs privileged package installation, shell-based execution materially increases the risk if the environment is compromised or the function is later reused with variable input.

Content

Scanner excerpt · scripts/install_mpv.py (reported line 14)May include surrounding context.

python
def run(cmd, check=True):
    result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
    if check and result.returncode != 0:
        print(f"Error: {result.stderr.strip()}", file=sys.stderr)
        sys.exit(1)

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/install_mpv.py (reported line 53)May include surrounding context.

python
run("brew install mpv")
    elif shutil.which("port"):
        print("Installing mpv via MacPorts...")
        run("sudo port install mpv")
    else:
        print("ERROR: Neither Homebrew nor MacPorts found.")
        print("Install Homebrew first: https://brew.sh")

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/install_mpv.py (reported line 78)May include surrounding context.

python
run("brew install mpv")
    elif shutil.which("port"):
        print("Installing mpv via MacPorts...")
        run("sudo port install mpv")
    else:
        print("ERROR: Neither Homebrew nor MacPorts found.")
        print("Install Homebrew first: https://brew.sh")

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/install_mpv.py (reported line 87)May include surrounding context.

python
run("brew install mpv")
    elif shutil.which("port"):
        print("Installing mpv via MacPorts...")
        run("sudo port install mpv")
    else:
        print("ERROR: Neither Homebrew nor MacPorts found.")
        print("Install Homebrew first: https://brew.sh")

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/install_mpv.py (reported line 93)May include surrounding context.

python
run("brew install mpv")
    elif shutil.which("port"):
        print("Installing mpv via MacPorts...")
        run("sudo port install mpv")
    else:
        print("ERROR: Neither Homebrew nor MacPorts found.")
        print("Install Homebrew first: https://brew.sh")

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
89% confidence
Finding

This performs two privileged package-management actions in one shell invocation: apt update and apt install. In the context of an agent skill, automatically running chained sudo commands magnifies the blast radius of mistakes and combines repository refresh with installation under shell execution, leaving little opportunity for user review.

Content

Scanner excerpt · scripts/install_mpv.py (reported line 75)May include surrounding context.

python
if distro in ("ubuntu", "debian", "linuxmint", "pop"):
        print("Installing mpv via apt...")
        run("sudo apt-get update -q && sudo apt-get install -y mpv")
    elif distro in ("fedora",):
        print("Installing mpv via dnf...")
        run("sudo dnf install -y mpv")

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
88% confidence
Finding

This line chains privileged installation of epel-release and mpv in one shell command. Because adding EPEL changes the trusted software sources on the system, doing so automatically under sudo is more sensitive than a simple package install and can have broader system impact if run on the wrong host or under a manipulated environment.

Content

Scanner excerpt · scripts/install_mpv.py (reported line 81)May include surrounding context.

python
run("sudo dnf install -y mpv")
    elif distro in ("centos", "rhel", "rocky", "almalinux"):
        print("Installing mpv via yum (requires EPEL)...")
        run("sudo yum install -y epel-release && sudo yum install -y mpv")
    elif distro in ("arch", "manjaro", "endeavouros"):
        print("Installing mpv via pacman...")
        run("sudo pacman -S --noconfirm mpv")

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
90% confidence
Finding

Using pacman's --noconfirm causes unattended installation without requiring the operator to review package actions or prompts. In a skill that autonomously installs software with sudo, suppressing confirmation makes unintended package changes more likely and reduces a user's chance to catch misdetection or repository issues before privileged execution.

Content

Scanner excerpt · scripts/install_mpv.py (reported line 84)May include surrounding context.

python
run("sudo yum install -y epel-release && sudo yum install -y mpv")
    elif distro in ("arch", "manjaro", "endeavouros"):
        print("Installing mpv via pacman...")
        run("sudo pacman -S --noconfirm mpv")
    elif distro in ("opensuse", "opensuse-leap", "opensuse-tumbleweed", "sles"):
        print("Installing mpv via zypper...")
        run("sudo zypper install -y mpv")

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
87% confidence
Finding

This line uses sudo for package installation together with --noconfirm, allowing unattended privileged changes. While installing mpv is the intended task, combining elevation with suppressed prompts makes accidental or undesired execution harder for a user to interrupt.

Content

Scanner excerpt · scripts/install_mpv.py (reported line 84)May include surrounding context.

python
run("sudo yum install -y epel-release && sudo yum install -y mpv")
    elif distro in ("arch", "manjaro", "endeavouros"):
        print("Installing mpv via pacman...")
        run("sudo pacman -S --noconfirm mpv")
    elif distro in ("opensuse", "opensuse-leap", "opensuse-tumbleweed", "sles"):
        print("Installing mpv via zypper...")
        run("sudo zypper install -y mpv")

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
89% confidence
Finding

The fallback apt path automatically performs sudo apt-get update followed by install in a single shell command after package-manager detection. In an agent context, fallback logic plus privileged shell chaining can trigger significant system modification based on heuristic detection rather than explicit user choice.

Content

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

python
run("sudo zypper install -y mpv")
    elif shutil.which("apt-get"):
        print("Detected apt-based system. Installing mpv via apt...")
        run("sudo apt-get update -q && sudo apt-get install -y mpv")
    elif shutil.which("dnf"):
        print("Detected dnf. Installing mpv via dnf...")
        run("sudo dnf install -y mpv")

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
90% confidence
Finding

This fallback pacman path also uses --noconfirm, enabling privileged package installation with no final user approval. In the context of an installer skill, that increases operational risk because a broad package-manager probe can pick a manager and proceed automatically under sudo.

Content

Scanner excerpt · scripts/install_mpv.py (reported line 96)May include surrounding context.

python
run("sudo dnf install -y mpv")
    elif shutil.which("pacman"):
        print("Detected pacman. Installing mpv via pacman...")
        run("sudo pacman -S --noconfirm mpv")
    else:
        print("ERROR: Could not detect package manager.")
        print("Please install mpv manually: https://mpv.io/installation/")

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
87% confidence
Finding

This fallback command combines sudo with pacman's --noconfirm, enabling silent privileged package changes once a package manager is heuristically detected. In an installer skill, that reduces operator control and can make mistakes or environmental tampering more damaging.

Content

Scanner excerpt · scripts/install_mpv.py (reported line 96)May include surrounding context.

python
run("sudo dnf install -y mpv")
    elif shutil.which("pacman"):
        print("Detected pacman. Installing mpv via pacman...")
        run("sudo pacman -S --noconfirm mpv")
    else:
        print("ERROR: Could not detect package manager.")
        print("Please install mpv manually: https://mpv.io/installation/")

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

L03 的描述整体以中文固定呈现,文件中也未说明可根据用户偏好切换语言。按照语言/locale 政策,若技能对语言有隐性强制,应提供用户选择或明确的合理限定。

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.