Back to skill

Security audit

Xiaohongshu (RedNote) User Search API

Security checks for vulnerabilities and agentic risk

Overview

The skill does the promised JustOneAPI user search, but it handles the API token in ways that can leak through URLs or process logs.

Review before installing if your JustOneAPI token has meaningful quota, billing, or data access. Use a narrowly scoped and revocable token, avoid shell tracing or command logging when invoking the skill, and rotate the token if it may have appeared in logs or process metadata.

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

Warning
Location
bin/run.mjs:224
Finding
API Access Token Transmitted in the URL Query String<![CDATA[ ## Vulnerability Details **File Location**: `bin/run.mjs:21-28`, `bin/run.mjs:71-74`, and `bin/run.mjs:224-231` **Vulnerability Type**: Sensitive credential exposure through URL query parameters **Risk Level**: Medium ### Vulnerable Code ```js { "defaultValue": null, "description": "Access token for this API service.", "enumValues": [], "location": "query", "name": "token", "required": true, "schemaType": "string" } ``` ```js const url = new URL(operation.path, ensureBaseUrl(baseUrl)); applyPathParams(operation, params, url); applyQueryParams(operation, params, url); const requestInit = { headers: { "accept": "application/json", }, method: operation.method, }; ``` ```js function applyQueryParams(operation, params, url) { for (const parameter of operation.parameters.filter((item) => item.location === "query")) { const value = params[parameter.name]; if (value === undefined) { continue; } appendValue(url.searchParams, parameter.name, value); } } function appendValue(searchParams, name, value) { if (Array.isArray(value)) { for (const item of value) { appendValue(searchParams, name, item); } return; } if (value && typeof value === "object") { searchParams.append(name, JSON.stringify(value)); return; } searchParams.append(name, String(value)); } ``` ### Technical Analysis The operation definition classifies the API access token as a query parameter. The generic query-parameter builder consequently inserts the credential into the final request URL, producing a request resembling: ```text https://api.justoneapi.com/api/xiaohongshu/search-user/v2?token=SECRET&keyword=VALUE&page=1 ``` Although the request uses HTTPS, TLS only protects the URL while it is in transit. The complete URL may still be recorded by the API server, reverse proxies, content-delivery infrastructure, observability systems, application performance monitoring tools, network diagnostics, or error-r ...[truncated 1778 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Change the service contract to accept credentials through an authorization header, preferably: ```js const requestInit = { method: operation.method, headers: { accept: "application/json", authorization: `Bearer ${token}`, }, }; ``` 2. Remove `token` from the operation's query-parameter definitions so the generic query builder cannot append it to the URL. 3. Update `generated/operations.json`, `generated/operations.md`, and `SKILL.md` to document header-based authentication. 4. If the upstream API cannot immediately support headers, configure all API gateways, proxies, server logs, tracing systems, and error-reporting tools to redact the `token` query parameter. 5. Prevent complete request URLs containing credentials from appearing in errors or telemetry. 6. Use narrowly scoped, short-lived credentials and provide token rotation and revocation mechanisms. 7. Add an automated test asserting that serialized request URLs never contain the API token. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
bin/run.mjs:121
Finding
API Token Supplied Through Process Command-Line Arguments<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:39-45` and `bin/run.mjs:121-137` **Vulnerability Type**: Sensitive credential exposure through process arguments **Risk Level**: Low ### Vulnerable Code ```bash node {baseDir}/bin/run.mjs --operation "getSearchUserV2" --token "$JUST_ONE_API_TOKEN" --params-json '{"keyword":"<keyword>"}' ``` ```js function parseArgs(argv) { const parsed = { operation: null, paramsJson: "{}", token: null }; for (let index = 0; index < argv.length; index += 1) { const flag = argv[index]; const value = argv[index + 1]; if (flag === "--operation") { parsed.operation = value; index += 1; continue; } if (flag === "--params-json") { parsed.paramsJson = value; index += 1; continue; } if (flag === "--token") { parsed.token = value; index += 1; continue; } fail(`Unknown argument "${flag}".`); } return parsed; } ``` ### Technical Analysis The documented invocation expands `JUST_ONE_API_TOKEN` into the child process argument vector through the `--token` option. Depending on the operating system, container runtime, process isolation settings, shell wrapper, audit configuration, and orchestration platform, process arguments may be observable through: - Process inspection utilities or process metadata interfaces - Operating-system audit logs - Container or job metadata - Agent execution logs - Monitoring and endpoint-management software - Debugging and crash-reporting tools - Shell tracing or command-recording wrappers The documentation correctly warns users not to paste token values into chat messages, screenshots, or logs, but the invocation mechanism itself still exposes the expanded value to systems that capture command arguments. Reading a credential from an environment variable is not risk-free, but it avoids deliberately copying the secret into the process command line and is the minimum-privilege mechanism already impli ...[truncated 1247 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the `--token` command-line option and read the declared environment variable directly: ```js const token = process.env.JUST_ONE_API_TOKEN; if (!token) { fail("JUST_ONE_API_TOKEN is required."); } ``` 2. Update the documented command so it does not expand the token into the argument vector: ```bash node {baseDir}/bin/run.mjs \ --operation "getSearchUserV2" \ --params-json '{"keyword":"<keyword>"}' ``` 3. Combine this change with header-based authentication so the token is absent from both the command line and request URL. 4. Ensure execution frameworks do not log environment contents or authorization headers. 5. Avoid shell tracing when launching the Skill with sensitive environment variables. 6. Use credentials restricted to the minimum necessary API operations and rotate any token suspected of appearing in process or audit logs. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (7)

Credential Access

High
Category
Privilege Escalation
Content
"parameters": [
        {
          "defaultValue": null,
          "description": "Access token for this API service.",
          "enumValues": [],
          "location": "query",
          "name": "token",
Confidence
95% confidence
Finding
The skill defines the API access token as a query parameter, which causes the credential to be embedded in the URL. Query-string secrets are commonly exposed through logs, browser/history equivalents, reverse proxies, monitoring systems, and error reporting, increasing the chance of credential leakage even when HTTPS is used.

Credential Access

High
Category
Privilege Escalation
Content
"parameters": [
        {
          "defaultValue": null,
          "description": "Access token for this API service.",
          "enumValues": [],
          "location": "query",
          "name": "token",
Confidence
97% confidence
Finding
Passing an access token as a required query parameter is dangerous because query strings are commonly logged by clients, proxies, servers, monitoring tools, and browser/history layers. If exposed, the token could allow unauthorized use of the third-party API service and potentially compromise associated quota, billing, or downstream data access.

Credential Access

High
Category
Privilege Escalation
Content
| Name | In | Required | Type | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `token` | `query` | yes | `string` | n/a | Access token for this API service. |
| `keyword` | `query` | yes | `string` | n/a | Search keyword. |
| `page` | `query` | no | `integer` | `1` | Page number for pagination. |
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Lp3

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding
Without declared permissions the skill's intent is opaque and cannot be validated.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
This code injects a required API token into request parameters and then sends it in the query string to a remote service, which is a sensitive credential-handling and network transmission path. While the manifest labels the field as an access token, there is no confirmation prompt, user-facing notice, or warning in this file explaining that the credential will be sent to an external API.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The manifest requires a token parameter that is sent to an external API service, but it does not clearly warn users or calling agents about that credential transmission. This can lead to inadvertent disclosure or misuse of sensitive API credentials, especially if an orchestrator or user assumes the skill does not forward secrets off-platform.

Vague Triggers

Low
Confidence
81% confidence
Finding
This is a manifest-style JSON file, so vague-trigger rules apply. The description and display name describe a general 'user search' capability but do not specify any invocation phrases, boundaries, or exclusion conditions, making activation scope ambiguous.

Static analysis

Detected: suspicious.secret_argv_exposure

Instructions pass high-value credentials through process argv.

Critical
Code
suspicious.secret_argv_exposure
Location
SKILL.md:42