Back to skill

Security audit

license-audit

Security checks for vulnerabilities and agentic risk

Overview

This is a plausible license scanner, but it can automatically run an unverified installer and can expose private repository tokens in logs if users follow its example.

Review before installing. Preinstall Trivy through a trusted, pinned method and avoid invoking this skill in environments where it could auto-install into /usr/local/bin. Do not put repository tokens in URLs; use SSH, a credential helper, or short-lived read-only credentials, and avoid printing full authenticated URLs in logs. Use Feishu output only when you intend to upload dependency inventory to Feishu, preferably with a dedicated low-scope internal app.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • 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
Findings (3)

T03 · Remote Payload Retrieval and Execution

Error
Location
scripts/audit.py:318
Finding

Automatic Execution of an Unpinned Remote Installation Script

Content
View full analysis
str: """Return path to trivy, installing it if not found.""" path = shutil.which("trivy") if path: return path print("⚠️ Trivy not found. Installing...") if sys.platform == "darwin": subprocess.run(["brew", "install", "trivy"], check=True) else: subprocess.run( "curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin", shell=True, check=True, ) return shutil.which("trivy") or "trivy" ``` ### Technical Analysis When Trivy is unavailable on a non-macOS system, the Skill automatically downloads an installation script from the mutable `main` branch of an external GitHub repository and pipes the response directly into `sh`. The downloaded content is not pinned to a release or commit, inspected, checksum-verified, or authenticated with a cryptographic signature. Consequently, the effective code executed by the reviewed Skill can change after publication. Compromise of the upstream repository, GitHub account, release process, or delivery path could cause arbitrary attacker-controlled commands to run during an ordinary audit. Using `shell=True` and a `curl | sh` pipeline eliminates the opportunity to review or validate the downloaded file before execution. Installing into `/usr/local/bin` also exceeds the minimum privilege required to produce a license report. The operation will ordinarily fail without suitable write permission, but it could modify a system-wide executable directory if the Skill is run by a privileged user or in an environment where that directory is writable. ### Attack Path 1. A user invokes `scripts/audit.py` on a non-macOS host. 2. `ensure_trivy()` determines that no `triv ...[truncated 1178 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/audit.py:332
Finding

Private Repository Credentials Exposed Through Command Logging and Process Arguments

Content
View full analysis
dict: if is_repo_url: cmd = ["trivy", "repo", "--scanners", "license", "--format", "json", "--quiet", "--no-progress", target] else: cmd = ["trivy", "fs", "--scanners", "license", "--format", "json", "--quiet", "--no-progress", target] trivy_bin = ensure_trivy() cmd[0] = trivy_bin print(f"🔍 Scanning: {target}") print(f" Command: {' '.join(cmd)}\n") result = subprocess.run(cmd, capture_output=True, text=True, timeout=600) ``` ### Technical Analysis A credential embedded in a URL becomes part of the `target` string. The script prints both the target and the complete constructed command, exposing the token in terminal output and CI logs. The same credential-bearing URL is passed as a command-line argument to Trivy. Depending on the operating system and process isolation, local users or monitoring software may be able to inspect that argument through process-listing interfaces while the scan is running. Although `subprocess.run()` uses an argument list and does not create a shell-injection issue at this call site, that does not protect the confidentiality of the argument. The risk is amplified because the project documentation explicitly encourages this authentication pattern. ### Attack Path 1. A user follows the documented private-reposito ...[truncated 1218 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
SKILL.md:146
Finding

Unpinned Installation of a Credential-Bearing Third-Party CLI

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (21)

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

Executing a remote shell installation script is not justified by the core purpose of license auditing and gives the skill an unnecessary code-execution capability. Because the script is fetched at runtime from the network and immediately executed, any compromise of the source, redirect path, or transport trust chain can lead to full host compromise.

Content

No source excerpt is available for this finding.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
99% confidence
Finding

Using shell=True with a network-fetched install command dramatically increases the blast radius of mistakes or compromise, because the shell interprets the full string and executes downloaded content immediately. Even though the command string is hardcoded, the remote content is attacker-influenceable through supply-chain compromise, making this a real host-compromise risk.

Content

Scanner excerpt · scripts/audit.py (reported line 324)May include surrounding context.

python
if sys.platform == "darwin":
        subprocess.run(["brew", "install", "trivy"], check=True)
    else:
        subprocess.run(
            "curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin",
            shell=True, check=True,
        )

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill documentation describes capabilities that involve shell execution, filesystem access, network access, and writing outputs, but it does not declare any explicit tool scope such as permissions or allowed-tools. In an agent environment, missing scope declarations weakens least-privilege controls and can allow broader-than-expected execution against local paths, remote git URLs, and external services like NuGet or Feishu.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The Quick Start includes a credential-bearing Git URL example (https://user:TOKEN@...) without any warning that embedding secrets in command lines is unsafe. Such tokens can leak through shell history, process lists, logs, screenshots, copied reports, or telemetry, making accidental credential disclosure likely in normal use.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% 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/audit.py (reported line 234)May include surrounding context.

python
Supports both new (licenseExpression) and old (licenseUrl) packages.
    """
    try:
        url = f"https://api.nuget.org/v3/registration5-semver1/{pkg_id.lower()}/index.json"
        req = urllib.request.Request(url, headers={"User-Agent": "license-audit/1.0"})
        with urllib.request.urlopen(req, timeout=10) as resp:
            data = json.loads(resp.read())

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill is presented as an auditing/reporting tool, but it silently installs Trivy and changes the host environment. That violates least surprise and increases attack surface, especially in automation contexts where users may not expect package installation or privileged writes to /usr/local/bin.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The code performs automatic installation and remote script execution without explicit user confirmation. Silent execution of privileged setup steps is dangerous in a skill because it breaks user expectations and can turn a routine scan into arbitrary host modification or compromise.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/audit.py (reported line 322)May include surrounding context.

python
return path
    print("⚠️  Trivy not found. Installing...")
    if sys.platform == "darwin":
        subprocess.run(["brew", "install", "trivy"], check=True)
    else:
        subprocess.run(
            "curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin",

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
99% confidence
Finding

This call downloads a remote script and pipes it directly into sh with shell=True, causing arbitrary code from the network to execute on the host. In an audit/reporting skill, that is especially dangerous because the capability exceeds the expected trust boundary and can compromise the machine if the fetched script or delivery path is tampered with.

Content

Scanner excerpt · scripts/audit.py (reported line 324)May include surrounding context.

python
if sys.platform == "darwin":
        subprocess.run(["brew", "install", "trivy"], check=True)
    else:
        subprocess.run(
            "curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin",
            shell=True, check=True,
        )

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/audit.py (reported line 345)May include surrounding context.

python
print(f"🔍 Scanning: {target}")
    print(f"   Command: {' '.join(cmd)}\n")

    result = subprocess.run(cmd, capture_output=True, text=True, timeout=600)

    if result.returncode != 0:
        stderr = result.stderr

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill description focuses on auditing and reporting, but this code creates and mutates Feishu Docs/Bases, including deleting default tables and inserting records. In a security-analysis context, undisclosed remote side effects are risky because they can exfiltrate inventory data and alter third-party resources under the user’s identity.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

Publishing to Feishu Doc sends scan-derived dependency and project information to an external service, but the code provides no upfront privacy or transmission warning beyond the chosen format. For audit tooling, dependency inventories may be sensitive internal metadata, so undisclosed upload increases data leakage risk.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/audit.py (reported line 801)May include surrounding context.

python
if folder_token:
            cmd += ["--folder-token", folder_token]
        print("📄 Creating Feishu Doc...")
        result = subprocess.run(cmd, capture_output=True, text=True, timeout=60, cwd=tmp_dir)
    finally:
        shutil.rmtree(tmp_dir, ignore_errors=True)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This feature uploads dependency inventory data into Feishu Base and performs additional remote mutations such as table creation and deletion, without strong disclosure of those actions. In enterprise environments, dependency names, versions, and project identifiers can be sensitive and should not be transmitted silently.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/audit.py (reported line 833)May include surrounding context.

python
cmd = ["lark-cli", "base", "+base-create", "--name", base_name, "--as", "user"]
    if folder_token:
        cmd += ["--folder-token", folder_token]
    r = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
    if r.returncode != 0:
        print(f"❌ Failed to create Base:\n{r.stderr}")
        return r.stderr

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/audit.py (reported line 857)May include surrounding context.

python
cmd = ["lark-cli", "base", "+base-create", "--name", base_name, "--as", "user"]
    if folder_token:
        cmd += ["--folder-token", folder_token]
    r = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
    if r.returncode != 0:
        print(f"❌ Failed to create Base:\n{r.stderr}")
        return r.stderr

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/audit.py (reported line 877)May include surrounding context.

python
return f"Base: {base_url}\nCould not parse table_id"

    print("   Removing default empty table...")
    tl = subprocess.run(
        ["lark-cli", "base", "+table-list", "--base-token", base_token, "--as", "user"],
        capture_output=True, text=True, timeout=15,
    )

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/audit.py (reported line 884)May include surrounding context.

python
try:
        for tbl in json.loads(tl.stdout).get("data", {}).get("tables", []):
            if tbl.get("id") != table_id:
                subprocess.run(
                    ["lark-cli", "base", "+table-delete",
                     "--base-token", base_token, "--table-id", tbl["id"],
                     "--as", "user", "--yes"],

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/audit.py (reported line 908)May include surrounding context.

python
if "options" in fld:
            payload["options"] = fld["options"]
            payload["multiple"] = False
        subprocess.run(
            ["lark-cli", "base", "+field-create",
             "--base-token", base_token, "--table-id", table_id,
             "--json", json.dumps(payload), "--as", "user"],

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/audit.py (reported line 936)May include surrounding context.

python
"fields": ["Package", "Version", "License", "Risk Tier", "Relation", "Dual License"],
            "rows": batch,
        })
        rb = subprocess.run(
            ["lark-cli", "base", "+record-batch-create",
             "--base-token", base_token, "--table-id", table_id,
             "--as", "user", "--json", payload],

External Script Fetching

Low
Category
Supply Chain
Confidence
99% confidence
Finding

Fetching an external script and piping it directly to sh creates a classic supply-chain execution risk. The skill’s context makes this more dangerous because users expect license scanning, not unaudited remote code execution on their host.

Content

Scanner excerpt · scripts/audit.py (reported line 325)May include surrounding context.

python
subprocess.run(["brew", "install", "trivy"], check=True)
    else:
        subprocess.run(
            "curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin",
            shell=True, check=True,
        )
    return shutil.which("trivy") or "trivy"

Static analysis

No suspicious patterns detected.