Back to skill

Security audit

Twitter User Profile API

Security checks for vulnerabilities and agentic risk

Overview

The skill appears to call the advertised JustOneAPI Twitter profile endpoint, but it handles the API token in ways that can expose it through command lines and request URLs.

Review this before installing if the JustOneAPI token has paid quota, broad permissions, or long lifetime. Use only a narrowly scoped token if possible, avoid running it in shared or heavily logged environments, and rotate the token if command lines or full request URLs may be captured. The skill should only be used for user-requested Twitter/X profile lookups by restId.

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:225
Finding

Authentication Token Transmitted in the Request URL Query String

Content
View full analysis

Vulnerability Details

File Location: bin/run.mjs:22-29, bin/run.mjs:70-72, and bin/run.mjs:225-231
Vulnerability Type: Credential exposure through URL query parameters
Risk Level: Medium

Vulnerable Code

The operation declares the authentication token as a query parameter:

javascript
      {
        "defaultValue": null,
        "description": "Authentication token required for API access.",
        "enumValues": [],
        "location": "query",
        "name": "token",
        "required": true,
        "schemaType": "string"
      },

All declared query parameters, including token, are then appended to the URL:

javascript
const baseUrl = manifest.baseUrl;
const url = new URL(operation.path, ensureBaseUrl(baseUrl));
applyPathParams(operation, params, url);
applyQueryParams(operation, params, url);
javascript
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);
  }
}

Consequently, the effective request has the following form:

text
https://api.justoneapi.com/api/twitter/get-user-detail/v1?token=SECRET&restId=USER_ID

Technical Analysis

Sending the token to api.justoneapi.com is necessary for the declared API functionality. However, placing authentication credentials in the URL exceeds the minimum safe exposure necessary for authentication.

HTTPS encrypts the complete URL during transport, so a passive network observer cannot normally read the query string. Nevertheless, URLs are routinely captured by infrastructure outside the immediate application, including:

  • Reverse-proxy and API gateway access logs
  • Server request logs
  • Web application firewalls and monitor ...[truncated 1926 chars]
Remediation
View remediation

Remediation Suggestions

  1. Change the API authentication contract to use an HTTP authorization header, preferably:

    javascript
    const requestInit = {
      headers: {
        accept: "application/json",
        authorization: `Bearer ${token}`,
      },
      method: operation.method,
    };
    
  2. Remove token from operation.parameters and ensure it is never passed to URLSearchParams.

  3. If JustOneAPI currently requires query-string authentication, coordinate a server-side migration to header-based authentication. Client-only changes must not be made without server support.

  4. Until migration is possible:

    • Configure gateways, proxies, servers, and tracing systems to redact the token query parameter.
    • Disable full-URL logging for this endpoint.
    • Use narrowly scoped, short-lived tokens.
    • Rotate the token immediately if URLs may already have been logged.
  5. Add an explicit denylist in applyQueryParams so credential-like fields cannot accidentally enter URLs:

    javascript
    const sensitiveNames = new Set(["token", "apiKey", "access_token"]);
    
    function applyQueryParams(operation, params, url) {
      for (const parameter of operation.parameters.filter(
        (item) => item.location === "query"
      )) {
        if (sensitiveNames.has(parameter.name)) {
          throw new Error(`Sensitive parameter cannot be placed in URL: ${parameter.name}`);
        }
    
        const value = params[parameter.name];
        if (value !== undefined) {
          appendValue(url.searchParams, parameter.name, value);
        }
      }
    }
    
  6. Add automated tests asserting that serialized request URLs never contain authentication credentials.

T09 · Insecure Skill Coding Practices

Warning
Location
bin/run.mjs:154
Finding

Authentication Token Accepted Through a Command-Line Argument

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:39-46 and bin/run.mjs:154-177
Vulnerability Type: Local credential disclosure through process arguments
Risk Level: Medium

Vulnerable Code

The documented invocation passes the secret directly on the command line:

bash
node {baseDir}/bin/run.mjs --operation "getTwitterUserDetailV1" --token "$JUST_ONE_API_TOKEN" --params-json '{"restId":"<restId>"}'

The executable explicitly parses the token from process.argv:

javascript
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

Command-line arguments are not an appropriate secret-delivery mechanism. Depending on the operating-system configuration, container runtime, orchestration platform, and process ownership model, arguments may be visible through:

  • Process inspection utilities such as ps
  • Linux /proc/<pid>/cmdline
  • Container and workload inspection interfaces
  • Endpoint monitoring and process auditing products
  • Shell tracing or debugging output
  • CI/CD job metadata and command logs

Although the shell expands "$JUST_ONE_API_TOKEN" without printing it under normal conditions, the expanded token becomes part of the Node.js process argument vector. The Skill documentation also declares JUST_ONE_API_TOKEN as the primary environment variable, so requiring users ...[truncated 1319 chars]

Remediation
View remediation

Remediation Suggestions

  1. Read the declared environment variable directly instead of requiring --token:

    javascript
    const token = process.env.JUST_ONE_API_TOKEN;
    
    if (!token) {
      fail("JUST_ONE_API_TOKEN is required.", {
        operationId: operation.operationId,
      });
    }
    
  2. Update the documented command to omit the secret-bearing argument:

    bash
    JUST_ONE_API_TOKEN="$JUST_ONE_API_TOKEN" \
      node {baseDir}/bin/run.mjs \
      --operation "getTwitterUserDetailV1" \
      --params-json '{"restId":"<restId>"}'
    
  3. Remove support for --token, or reject it with a message directing users to the environment variable or an approved secret provider.

  4. For higher-security deployments, load the token from a secret manager, protected file descriptor, or standard input rather than from either command arguments or broadly inherited environment variables.

  5. Prevent the token from being accepted inside --params-json, since that would also expose it in the process argument vector.

  6. Ensure errors, debug output, and telemetry never serialize the token.

  7. Rotate any token that may have appeared in process audit records, CI logs, shell traces, or container metadata.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (5)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill instructs execution of a Node helper that performs outbound API requests using a bearer token, but the manifest does not declare any explicit tool scope such as allowed network access or permitted tools. This creates a transparency and policy-enforcement gap: an agent or reviewer cannot reliably constrain what the skill is allowed to do, increasing the risk of unintended network calls or misuse of the provided secret in environments that rely on manifest-declared permissions.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill requires an authentication token and sends it as a query string parameter, which is then embedded in the full request URL. Query parameters are commonly exposed through logs, monitoring systems, browser/history equivalents, reverse proxies, and error telemetry, so the token can be unintentionally disclosed even when HTTPS is used.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The manifest does not warn users that their authentication token and target account lookup data are sent to an external API provider, which creates a transparency and data-handling risk. This is more dangerous in context because the token is a sensitive credential and the skill routes it as a query parameter to a third-party endpoint, increasing the chance of accidental disclosure through logs, monitoring systems, or misuse.

Content

No source excerpt is available for this finding.

Vague Triggers

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

The manifest description is too vague about when and why the operation should be invoked, which can lead an agent to call the external API in situations the user did not clearly intend. In this skill, that ambiguity matters because the call transmits a required authentication token and a user identifier to a third-party service.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

This markdown file documents retrieval of user profile metadata, audience metrics, and follower/following counts, which are user-related data elements. Under the markdown-specific warning rule, the description should disclose privacy or data-use implications when the skill affects user data, but no such warning is present here.

Content

No source excerpt is available for this finding.

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