Back to skill

Security audit

Skill Dropshipping Sourcing

Security checks for vulnerabilities and agentic risk

Overview

The skill does CJ product sourcing as advertised, but its handling of CJ credentials is under-scoped and could expose them through the local config.

Review this before installing if you will use real CJ credentials. Only use a trusted cj-api.json, keep baseUrl fixed to the official CJ API, keep the credential file out of source control and shared workspaces, and rotate the CJ API key/token if the file may have been exposed.

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/token.js:16
Finding
Configurable API Endpoint Can Redirect CJ Credentials to an Untrusted Server## Vulnerability Details **File Location**: `scripts/token.js:16-17, 25` and `scripts/source.js:35-41` **Vulnerability Type**: Unrestricted credential destination **Risk Level**: High ### Vulnerable Code `scripts/token.js:16-17, 25`: ```js async function refreshToken(apiKey, baseUrl){ const url = `${baseUrl.replace(/\/$/,'')}/authentication/getAccessToken`; const r = await axios.post(url, { apiKey }, { headers: { 'Content-Type':'application/json' }, timeout: 60000 }); if(!r.data?.result) throw new Error(`Token refresh failed: ${JSON.stringify(r.data).slice(0,300)}`); return r.data.data.accessToken; } const baseUrl = cfg.baseUrl || 'https://developers.cjdropshipping.com/api2.0/v1'; ``` `scripts/source.js:35-41`: ```js const baseUrl = (cfg.baseUrl || 'https://developers.cjdropshipping.com/api2.0/v1').replace(/\/$/,''); const token = cfg.accessToken; if(!token) throw new Error('Missing accessToken in cj-api.json (run token.js)'); const url = `${baseUrl}/product/listV2`; const res = await axios.get(url, { headers: { 'CJ-Access-Token': token }, ``` ### Technical Analysis Both scripts obtain `baseUrl` directly from `cj-api.json` without validating its scheme or hostname. The token helper sends the long-lived CJ API key in a POST body to the configured endpoint, while the sourcing script sends the CJ access token in an HTTP header to that endpoint. The Skill is explicitly dedicated to the CJ Dropshipping API, so sending credentials to arbitrary configurable origins is not necessary for its declared functionality. No exact-host allowlist, HTTPS requirement, redirect restriction, or destination confirmation protects these credentials. Axios may also follow HTTP redirects under its default behavior. Consequently, validating only the initial URL would be insufficient unless credential-bearing redirects are also prohibited or carefully constrained. ### Attack Path 1. An attacker or less-trusted ...[truncated 1342 chars]
Remediation
## Remediation Suggestions 1. Remove user-configurable origins if only the official CJ service is supported: ```js const baseUrl = 'https://developers.cjdropshipping.com/api2.0/v1'; ``` 2. If endpoint configuration is required for legitimate testing, parse it with `URL` and enforce: - `https:` as the protocol; - an exact hostname allowlist; - an approved port; - an approved base path; - no embedded username or password. 3. Reject IP literals, lookalike domains, and hostname suffix checks such as `endsWith("cjdropshipping.com")`, which can be bypassed by attacker-controlled subdomains. 4. Disable redirects for requests carrying credentials, or independently validate every redirect destination before forwarding credentials. 5. Keep test or mock endpoint support behind an explicit development-only option that cannot be enabled through the production credential file. 6. Document that credential-bearing requests are sent only to the official CJ origin.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/token.js:40
Finding
CJ API Credentials Are Stored in Plaintext Without Enforced File Permissions## Vulnerability Details **File Location**: `scripts/token.js:11, 40-42` and `SKILL.md:9-12` **Vulnerability Type**: Insecure local secret storage **Risk Level**: Medium ### Vulnerable Code `scripts/token.js:11, 40-42`: ```js function writeJson(p,o){ fs.writeFileSync(p, JSON.stringify(o,null,2)); } cfg.accessToken = newToken; cfg.tokenExpiry = newExp; writeJson(CJ_API_PATH, cfg); ``` `SKILL.md:9-12`: ```md ## Files / creds (local convention) - Config: `./cj-api.json` - `apiKey`, `baseUrl`, `accessToken`, `tokenExpiry` ``` ### Technical Analysis The documented configuration stores both the CJ API key and access token in the same plaintext JSON file. When the access token is refreshed, `writeFileSync` writes the complete configuration back without explicitly setting restrictive permissions. If the file is newly created, its effective permissions depend on the process umask. If it already exists, the script does not verify or repair insecure permissions. The documentation also does not instruct users to exclude the file from source control, restrict access, or use a secret-management facility. Plaintext storage is sometimes operationally necessary for a command-line integration, but combining all credentials in a normal project-local configuration file without permission enforcement or repository safeguards creates avoidable exposure. ### Attack Path 1. A user creates `cj-api.json` in the project directory as documented. 2. The file receives permissive filesystem permissions, is copied into a shared workspace, included in a backup, or is accidentally committed to source control. 3. Another local user, workspace participant, CI artifact consumer, or repository reader obtains the file. 4. The attacker extracts `apiKey` and `accessToken`. 5. The attacker reuses the credentials against the CJ API until they expire or are revoked. This attack requires read access to an exposed copy of the credential ...[truncated 576 chars]
Remediation
## Remediation Suggestions 1. Store the API key in an environment variable, operating-system credential store, or dedicated secret manager rather than in the project configuration. 2. Separate non-sensitive configuration such as the API URL from secret material. 3. If file-based storage remains necessary, create and update the secret file with mode `0600` and verify that existing files are not group- or world-readable. 4. Prefer an atomic secure write: - create a temporary file in the same protected directory; - use exclusive creation and mode `0600`; - write and flush the data; - atomically rename it over the target. 5. Add `cj-api.json` and temporary credential files to `.gitignore`. 6. Document secure ownership, permission, backup, logging, and CI handling requirements. 7. Provide a credential revocation and rotation procedure for suspected exposure. 8. Avoid printing API keys or access tokens in errors, diagnostics, or generated result files.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (4)

Credential Access

High
Category
Privilege Escalation
Content
---
name: skill-dropshipping-sourcing
description: Query CJ Dropshipping API v2.0 to source products and fetch details for catalog building. Use for CJ keyword search, pulling product records (SPU/SKU, images, categories, variants/colors when available), refreshing access tokens, and producing normalized JSON outputs for dropshipping catalog automation.
---

# CJ Sourcing
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
- Config: `./cj-api.json`
  - `apiKey`, `baseUrl`, `accessToken`, `tokenExpiry`

## 1) Refresh access token
```bash
node scripts/token.js
```
Confidence
88% confidence
Finding
The skill instructs users to store sensitive API material, including `apiKey` and `accessToken`, in a local JSON file at a predictable path (`./cj-api.json`). Predictable plaintext secret storage increases the chance of accidental disclosure through source control, workspace sharing, backups, or other tools that can read local files.

Ae1

High
Category
analysis-evasion
Content
node scripts/token.js
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Lp3

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

Static analysis

Detected: suspicious.env_credential_access

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/source.js:11

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/token.js:10