Back to skill

Security audit

Nexus Skills

Security checks for vulnerabilities and agentic risk

Overview

This Nexus CLI has a coherent purpose, but it needs review because downloads can send Nexus credentials to any supplied URL and deletion lacks an enforced confirmation step.

Review before installing. Use only a least-privileged Nexus account, preferably read-only unless upload or delete is truly needed. Do not use the download command with external URLs, disable or narrow implicit invocation if possible, and require a code-enforced confirmation gate before allowing delete-component in agent workflows.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/nexus_cli.py:164
Finding

Nexus credentials are disclosed to an arbitrary download origin

Content
View full analysis

Vulnerability Details

File Location: scripts/nexus_cli.py, lines 164–178
Vulnerability Type: Credential disclosure through unrestricted authenticated requests
Risk Level: High

Complete Code Snippet

python
def cmd_download(cfg, args):
    auth = HTTPBasicAuth(cfg["user"], cfg["pass"])
    try:
        resp = requests.get(args.url, auth=auth, stream=True, timeout=300)
    except requests.RequestException as exc:
        die(f"download failed: {exc}")
    if resp.status_code >= 400:
        die(f"download -> HTTP {resp.status_code}")
    dest = args.output or os.path.basename(args.url.split("?")[0]) or "download.bin"
    with open(dest, "wb") as fh:
        for chunk in resp.iter_content(chunk_size=8192):
            fh.write(chunk)
    out({"downloaded": dest, "bytes": os.path.getsize(dest)})

Technical Analysis

The download command accepts an unrestricted full URL in args.url. It then creates an HTTP Basic Authentication object from the configured Nexus username and password or token and attaches that authentication to the request regardless of the URL's origin.

No validation ensures that the supplied URL has the same scheme, hostname, and port as the configured NEXUS_URL. Consequently, invoking the command with an external URL sends the Nexus authorization credentials to that external server. An http:// URL would additionally transmit the credentials without transport encryption.

The affected trust boundary is between the trusted Nexus service configured by the user and an independently controlled HTTP origin. Credentials intended only for Nexus are disclosed to the selected download server.

Attack Path

  1. A Nexus account is configured through NEXUS_USER and NEXUS_PASS, or through ~/.devops-skills/nexus.json.
  2. An attacker causes an external URL under their control to be used by the download command, including through content that induces an implicitly invoked Agent request.
  3. The CLI constructs `HTTPB ...[truncated 891 chars]
Remediation
View remediation

Remediation Suggestions

  • Parse both NEXUS_URL and the requested download URL with a standards-compliant URL parser.
  • Require the download URL to use HTTPS.
  • Before attaching credentials, require an exact match of scheme, normalized hostname, and effective port with NEXUS_URL.
  • Do not attach Nexus credentials to cross-origin requests. If external unauthenticated downloads are intentionally supported, use a separate code path that omits auth.
  • Reject URLs containing embedded user information.
  • Consider accepting repository-relative asset paths rather than arbitrary full URLs and constructing the final URL from the trusted configured origin.
  • Add tests proving that authentication is absent or the operation is rejected for cross-origin and plain-HTTP URLs.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/nexus_cli.py:181
Finding

Irreversible component deletion lacks a code-enforced confirmation gate

Content
View full analysis

Vulnerability Details

File Location: scripts/nexus_cli.py, lines 181–183 and 224–226
Vulnerability Type: Unconfirmed destructive operation
Risk Level: Medium

Complete Code Snippet

python
def cmd_delete_component(cfg, args):
    request(cfg, "DELETE", f"/components/{args.id}")
    out({"deleted": args.id})
python
s = sub.add_parser("delete-component", help="delete a component by id")
s.add_argument("id")
s.set_defaults(func=cmd_delete_component)

The shared request function performs the authenticated operation directly:

python
def request(cfg, method, path, **kwargs):
    auth = HTTPBasicAuth(cfg["user"], cfg["pass"])
    try:
        resp = requests.request(method, cfg["url"] + API + path,
                                auth=auth, timeout=60, **kwargs)

Technical Analysis

The documentation states that deletion is irreversible and requires a second confirmation after checking the component ID. The executable path does not enforce that requirement. Supplying delete-component and an ID immediately issues an authenticated HTTP DELETE request.

There is no interactive prompt, explicit approval flag, dry-run default, confirmation token tied to the selected component, or verification that the ID was obtained from a preceding search or list operation. Therefore, the documentation-only safeguard can be bypassed whenever the CLI is called directly by an Agent or other automation.

The affected trust boundary is between caller-controlled command input and an authenticated, irreversible repository mutation. An unintended or attacker-influenced Agent invocation can exercise the configured account's deletion authority without the user's required second approval.

Attack Path

  1. The configured Nexus account has permission to delete components.
  2. An Agent or automation caller invokes delete-component with a component ID without completing the documented second-confirmation workflow.
  3. Argument parsing accepts the ...[truncated 691 chars]
Remediation
View remediation

Remediation Suggestions

  • Make deletion non-operative by default and provide a dry-run or component-summary mode.
  • Require an explicit confirmation flag, such as --confirm-delete, for non-interactive execution.
  • Bind confirmation to the exact component ID, for example by requiring the caller to repeat the ID or provide a short-lived confirmation token generated after displaying component details.
  • For interactive use, display the target repository, component name, version, and ID before requiring an exact confirmation response.
  • Refuse deletion when confirmation is absent rather than relying on Agent instructions or documentation.
  • Use a least-privileged Nexus account and grant deletion rights only for repositories where deletion is necessary.
  • Add tests confirming that a bare delete-component <id> invocation cannot issue an HTTP DELETE.
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
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (12)

Tainted flow: 'url' from os.environ.get (line 65, 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/nexus_cli.py (reported line 169)May include surrounding context.

python
auth = HTTPBasicAuth(cfg["user"], cfg["pass"])
        url = f"{cfg['url']}{API}/components"
        try:
            resp = requests.post(url, params={"repository": args.repo},
                                 files=files, auth=auth, timeout=300)
        except requests.RequestException as exc:
            die(f"upload failed: {exc}")

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill documents concrete capabilities that rely on environment variables and outbound network access, but it does not declare any explicit tool scope or permission boundaries. This creates a governance gap: an agent may invoke the skill without clear least-privilege constraints, increasing the chance of unintended access to Nexus credentials or unauthorized repository operations such as upload, download, or deletion.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The description uses broad trigger language like 'use whenever the user wants to browse a Nexus repo, find an artifact, publish a file, or clean up components,' which can cause over-selection of this skill for loosely related repository tasks. Because the skill supports networked artifact access and irreversible deletion, overly broad invocation increases the risk of the wrong skill being auto-invoked in a sensitive context.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill enables allow_implicit_invocation without any visible trigger constraints, exclusions, or additional policy guardrails. Because this skill can perform state-changing repository actions such as upload and delete, automatic invocation increases the chance that loosely related user requests or prompt-injected content could trigger sensitive operations without sufficiently explicit user intent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

This markdown file applies to SQP-2, and it instructs users to set credentials and use a CLI that performs authenticated network operations. While it includes a deletion warning elsewhere, there is no user-facing warning here about protecting credentials, using HTTPS, or the privacy/security implications of sending repository access data to the Nexus server.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

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

Content

Scanner excerpt · references/USAGE.md (reported line 47)May include surrounding context.

}

text

> `chmod 600 ~/.devops-skills/nexus.json`,切勿提交到仓库。

---

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The markdown explicitly says to trigger the skill with natural language, then gives example phrases, but it does not define whether those are the only supported triggers or provide negative examples. Phrases like '列一下 Nexus 上都有哪些仓库' are somewhat specific, yet the activation rule remains ambiguous because the scope and constraints of invocation are not clearly bounded.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The download command accepts an arbitrary full URL and sends Nexus credentials via HTTP Basic Auth to that URL. If a user is tricked into supplying a non-Nexus or attacker-controlled URL, the tool can leak credentials and fetch untrusted content, creating an SSRF-style outbound request primitive and credential exposure risk. In this skill context, users expect operations against a configured Nexus instance, so unrestricted cross-host downloads are more dangerous than in a generic HTTP client.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The download path writes response data directly to a local file, which is a safety-relevant file write operation. While the command name suggests downloading, this code path provides no confirmation prompt, warning comment, or user-facing disclosure beyond the generic help text before creating or overwriting the destination file.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This command performs an irreversible DELETE against the Nexus API and immediately reports success afterward. There is no confirmation prompt, cautionary message, or inline warning to alert users that the action is destructive.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
78% confidence
Finding

The file presents the title, usage instructions, and operational guidance primarily in Chinese, while also including a Chinese-specific trigger phrase, but it does not state that the skill is Chinese-only or offer the user a language choice. Under the stated policy, forcing a specific language without opt-in can be a natural-language policy issue.

Content

No source excerpt is available for this finding.

Unverifiable Dependency: requests has 16 known advisory(ies) (CVE-2014-1830 (Exposure of Sensitive Information to an Unauthorized Actor in Requests); CVE-2024-47081 (Requests vulnerable to .netrc credentials leak via malicious URLs); CVE-2024-35195 (Requests `Session` object does not verify requests after making first request wi) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
92% confidence
Finding

The dependency specifier requests>=2.25,<3 does not pin to a specific patched version, so installations may resolve to different releases depending on environment and timing. Because requests has multiple published advisories, this creates supply-chain uncertainty and can leave the skill exposed to known flaws if an affected version is installed.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.env_credential_access

Python code POSTs credential environment variables to an environment-controlled URL.

Critical
Code
suspicious.env_credential_access
Location
scripts/nexus_cli.py:169