Back to skill

Security audit

Xiaohongshu (RedNote) Keyword Suggestions API

Security checks for vulnerabilities and agentic risk

Overview

This skill appears to do only the advertised API lookup, but it handles the API token in ways that can expose it through command lines and logged URLs.

Review this skill before installing if your JustOneAPI token has paid quota, broad account access, or long lifetime. Use a dedicated low-privilege token, avoid running it on shared or heavily monitored systems, ensure logs redact `--token` and `token=` query values, and rotate any token that may already have appeared in process or URL logs.

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:136
Finding
API Token Exposed Through Command-Line Arguments<![CDATA[ ## Vulnerability Details **File Location**: `bin/run.mjs:136-140`; documented usage at `SKILL.md:41` **Vulnerability Type**: Credential exposure through process arguments **Risk Level**: Medium ### Vulnerable Code ```js if (flag === "--token") { parsed.token = value; index += 1; continue; } ``` The documented invocation explicitly expands the secret into the command-line argument vector: ```bash node {baseDir}/bin/run.mjs --operation "searchRecommendV1" --token "$JUST_ONE_API_TOKEN" --params-json '{"keyword":"<keyword>"}' ``` ### Technical Analysis The helper accepts the JustOneAPI access token through the `--token` command-line option. When the documented shell command is executed, the shell expands `JUST_ONE_API_TOKEN`, placing its value directly in the Node.js process argument vector. Depending on operating-system access controls and deployment configuration, command-line arguments may be visible through process inspection utilities, process metadata interfaces, monitoring agents, crash reports, audit systems, or telemetry collectors. The implementation does not print the token itself, but accepting it through `process.argv` unnecessarily increases the number of local systems that may observe the credential. This behavior exceeds minimum privilege in credential handling because the declared API functionality can instead obtain the required token directly from the already-declared `JUST_ONE_API_TOKEN` environment variable or through protected standard input. ### Attack Path 1. A user follows the command documented in `SKILL.md`. 2. The shell expands `$JUST_ONE_API_TOKEN` into the plaintext token. 3. The token becomes part of the Node.js process argument vector. 4. A local user, privileged process-monitoring service, diagnostic collector, or telemetry system captures the command-line arguments. 5. An attacker or unauthorized operator retrieves the token from the captured process metadata. 6. The token is replayed against JustOneAPI un ...[truncated 645 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Read the declared environment variable directly instead of requiring command-line expansion: ```js const token = process.env.JUST_ONE_API_TOKEN; if (!token) { fail("JUST_ONE_API_TOKEN is required.", { operationId: operation.operationId, }); } ``` 2. Remove the `--token` option from `parseArgs` and update `SKILL.md` to use: ```bash JUST_ONE_API_TOKEN="$JUST_ONE_API_TOKEN" node {baseDir}/bin/run.mjs \ --operation "searchRecommendV1" \ --params-json '{"keyword":"<keyword>"}' ``` 3. Where stronger isolation is required, accept credentials through protected standard input or an operating-system secret manager. 4. Ensure process monitoring, crash reporting, and telemetry systems redact historical `--token` values. 5. Rotate any token that may already have been captured in process logs or monitoring data. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
bin/run.mjs:20
Finding
API Token Transmitted in the URL Query String<![CDATA[ ## Vulnerability Details **File Location**: `bin/run.mjs:20-29`, `bin/run.mjs:70-77`, and `bin/run.mjs:168-192`; schema copies at `generated/operations.json:18-27` and `generated/operations.md:19` **Vulnerability Type**: Sensitive credential placed in a request URL **Risk Level**: Medium ### Vulnerable Code The operation declares the access token as a query parameter: ```js { "defaultValue": null, "description": "Access token for this API service.", "enumValues": [], "location": "query", "name": "token", "required": true, "schemaType": "string" } ``` The token is injected into the generic parameter object and all query parameters are appended to the URL: ```js function injectToken(operation, params, cliToken) { const tokenParam = operation.parameters.find((parameter) => parameter.name === "token"); if (!tokenParam || params.token !== undefined) { return; } if (!cliToken) { fail("--token is required for this operation.", { operationId: operation.operationId, }); } params.token = cliToken; } ``` ```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)); } ``` The resulting request has the following effective form: ```text https://api.justoneapi.com/api/xiaohongshu/search-recommend/v1?token=<secret>&keyword=<keyword> ``` ### Technical Analysis The implementation sends the API token as part of the URL query string. HTTPS en ...[truncated 1943 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Change the API authentication contract to use an HTTP authorization header, preferably: ```js const requestInit = { headers: { accept: "application/json", authorization: `Bearer ${token}`, }, method: operation.method, }; ``` 2. Remove `token` from the operation's query-parameter schema and prevent generic query serialization from processing credentials. 3. Obtain the token directly from `process.env.JUST_ONE_API_TOKEN` or another protected secret source. 4. Until the service supports header-based authentication, configure all clients, gateways, proxies, access logs, tracing systems, and error-reporting platforms to redact the `token` query parameter. 5. Avoid including complete request URLs in errors or diagnostic output. Continue returning only the operation ID and sanitized status information. 6. Apply short expiration periods and least-privilege scopes to API tokens, monitor for unexpected usage, and rotate tokens that may have appeared in historical URL 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
89% confidence
Finding
This finding reflects credential handling rather than explicit credential theft, but the code does process an access token and sends it in the request URL. In this skill context, that creates a real exposure path for the credential through normal operational logging and third-party infrastructure rather than an intentional credential-access backdoor.

Credential Access

High
Category
Privilege Escalation
Content
"parameters": [
        {
          "defaultValue": null,
          "description": "Access token for this API service.",
          "enumValues": [],
          "location": "query",
          "name": "token",
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
"parameters": [
        {
          "defaultValue": null,
          "description": "Access token for this API service.",
          "enumValues": [],
          "location": "query",
          "name": "token",
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
84% confidence
Finding
The skill invokes a network-capable helper (`node .../run.mjs`) that can make outbound API requests, but it does not declare an explicit tool scope such as `permissions` or `allowed-tools`. This creates a policy/visibility gap: platforms or reviewers cannot reliably constrain or audit the network behavior from the manifest alone, increasing the chance of unintended external requests or misuse if the skill is modified or repurposed.

Missing User Warnings

Medium
Confidence
98% confidence
Finding
The skill defines the API access token as a query parameter and later appends all query parameters to the URL. Secrets in URLs are commonly exposed via logs, browser/history records, proxies, monitoring tools, and upstream infrastructure, making accidental credential disclosure more likely even when HTTPS is used.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
Placing an access token in a query parameter is dangerous because query strings are commonly logged by clients, proxies, gateways, browser history, and observability systems. The lack of any user-facing warning or safer authentication guidance increases the chance that credentials are exposed or mishandled during normal use.

Vague Triggers

Low
Confidence
78% confidence
Finding
This is a manifest-style JSON file, so vague-trigger review applies. The description explains what the API does but provides no explicit trigger phrases, activation boundaries, or exclusion conditions, which can make invocation conditions ambiguous in systems that derive routing from descriptions.

Static analysis

Detected: suspicious.secret_argv_exposure

Instructions pass high-value credentials through process argv.

Critical
Code
suspicious.secret_argv_exposure
Location
SKILL.md:41