Back to skill

Security audit

fecify-site-manager-v1

Security checks for vulnerabilities and agentic risk

Overview

The skill matches its Fecify store-management purpose, but it needs review because it stores API tokens and can make broad live store changes with weak safeguards.

Install only if you trust the publisher and need this Fecify workflow. Use a dedicated least-privilege token, bind only HTTPS sites, prefer a test store first, inspect CSV image URLs before import, do not use --skip-validation in production, and rotate or delete stored tokens when finished.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/csv-import/import-shopify-csv.js:282
Finding
Server-Side Request Forgery Through CSV-Controlled Image URLs<![CDATA[ ## Vulnerability Details **File Location**: `scripts/csv-import/import-shopify-csv.js:282-320` **Vulnerability Type**: Server-Side Request Forgery and potential internal-data relay **Risk Level**: High ### Vulnerable Code ```js function getExt(url) { const m = url.match(/\.(\w{3,4})(\?|$)/); return m ? m[1] : 'jpg'; } function downloadImage(url) { return new Promise((resolve, reject) => { const transport = url.startsWith('https:') ? https : http; transport.get(url, { timeout: 30000 }, (res) => { if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) { return downloadImage(res.headers.location).then(resolve).catch(reject); } if (res.statusCode !== 200) return reject(new Error(`HTTP ${res.statusCode}`)); const bufs = []; res.on('data', d => bufs.push(d)); res.on('end', () => resolve(Buffer.concat(bufs))); }).on('error', reject).on('timeout', () => reject(new Error('Timeout'))); }); } async function uploadImages(images, productTitle, imgConcurrency = 5, imgRetries = 3) { const slugify = s => s.replace(/[^a-zA-Z0-9\u4e00-\u9fff-]/g, '_').substring(0, 30); const results = await concurrentMap(images, imgConcurrency, async (img) => { let lastErr; for (let attempt = 0; attempt <= imgRetries; attempt++) { try { const buf = await downloadImage(img.src); const ext = getExt(img.src); const r = await api.post('/api/skill/base-image/upload', { image_base64encode: buf.toString('base64'), image_name: `${slugify(productTitle)}_${img.position}.${ext}`, group_type: 'product' }); ``` ### Technical Analysis The importer obtains `img.src` from the CSV `Image Src` column and passes it directly to `http.get` or `https.get`. It performs no validation of: - The URL scheme - The destination hostname - Resolved IP addresses - Loopback, link-local, private, or reserved address ranges - Redirect destinations - ...[truncated 1915 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Parse every image URL with `new URL()` and reject parsing failures. 2. Permit only `https:` unless a narrowly scoped development option explicitly allows HTTP. 3. Resolve the hostname before connecting and reject every address in loopback, private, link-local, multicast, unspecified, documentation, and reserved ranges for both IPv4 and IPv6. 4. Repeat the complete scheme, hostname, DNS, and IP validation for every redirect. 5. Set a small redirect limit rather than using unrestricted recursion. 6. Consider an allowlist of approved image CDN domains. 7. Reject responses whose declared or detected MIME type is not an approved image format. 8. Apply strict response-size and timeout limits. 9. Where possible, perform image decoding and re-encoding before upload so arbitrary response bytes cannot be relayed unchanged. 10. Protect against DNS rebinding by connecting to a previously validated resolved address while preserving the expected TLS server name. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/base/api-client.js:55
Finding
Access Tokens Can Be Transmitted over Unencrypted HTTP<![CDATA[ ## Vulnerability Details **File Location**: `scripts/base/api-client.js:55-85`; also present in `scripts/base/save-config.js:26-42` **Vulnerability Type**: Cleartext transmission of authentication credentials **Risk Level**: High ### Vulnerable Code ```js const baseUrl = new URL(config.url); // 拼接完整路径:baseUrl 可能包含子路径(如 /apimanager666),必须保留 const fullPath = baseUrl.pathname.replace(/\/$/, '') + '/' + path.replace(/^\//, ''); const options = { hostname: baseUrl.hostname, port: baseUrl.port || (baseUrl.protocol === 'https:' ? 443 : 80), path: fullPath + (baseUrl.search || ''), method: method.toUpperCase(), headers: { 'skill-access-token': config.token, 'Content-Type': 'application/json', ...extraHeaders }, timeout: 30000 }; const transport = baseUrl.protocol === 'https:' ? https : http; const req = transport.request(options, (res) => { ``` The same behavior occurs during configuration initialization: ```js const options = { hostname: baseUrl.hostname, port: baseUrl.port || (baseUrl.protocol === 'https:' ? 443 : 80), path: apiPath, method: 'GET', headers: { 'skill-access-token': token, 'Content-Type': 'application/json' }, timeout: 30000 }; const transport = baseUrl.protocol === 'https:' ? https : http; ``` ### Technical Analysis The configured site URL is accepted without requiring the `https:` protocol. When the URL uses `http:`, the code deliberately selects Node.js's unencrypted HTTP transport but still places the reusable access token in the `skill-access-token` header. HTTP provides no transport confidentiality or server authentication. Any party able to observe or modify the connection can read the token or impersonate the configured server. The protocol is also not explicitly restricted to supported values. Any protocol other than `https:` is routed through the HTTP module, resulting in unsafe and inconsistent behavior. ### Attack Path 1. ...[truncated 948 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Validate URLs before saving them and reject every protocol except `https:`. 2. Repeat protocol validation inside `api-client.js`; do not rely solely on configuration-time validation. 3. If local HTTP development is necessary, require an explicit opt-in and restrict it to verified loopback addresses. 4. Do not silently downgrade to HTTP based on an arbitrary protocol value. 5. Retain normal TLS certificate verification and do not introduce certificate-validation bypasses. 6. Warn users and refuse operation when an existing persisted configuration contains an HTTP URL. 7. Rotate tokens that may previously have been transmitted over HTTP. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/base/site-config.js:62
Finding
Persistent Access Tokens Are Stored in Plaintext with Default Filesystem Permissions<![CDATA[ ## Vulnerability Details **File Location**: `scripts/base/site-config.js:62-70` **Vulnerability Type**: Insecure storage of reusable credentials **Risk Level**: Medium ### Vulnerable Code ```js function saveConfig(domain, url, token) { const dir = path.join(SITES_ROOT, domain); if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); fs.writeFileSync( path.join(dir, 'config.json'), JSON.stringify({ url, token, updatedAt: new Date().toISOString() }, null, 2), 'utf8' ); ``` ### Technical Analysis The access token is serialized directly into `config.json` as plaintext. Neither the directory nor the file is created with an explicit restrictive mode. Consequently, effective permissions depend on the process umask and permissions inherited from parent directories. In multi-user, shared-agent, backup, or diagnostic environments, the configuration may be readable by processes that do not require access to the Fecify credential. The token is persistent by design, increasing the period during which a local disclosure can occur. ### Attack Path 1. A user configures a Fecify site and supplies a reusable access token. 2. `saveConfig` writes the token into `data/fecify-shared/sessions/<domain>/config.json`. 3. A local user, co-located process, backup reader, or support process with filesystem access reads the file. 4. The token is extracted from the JSON document. 5. The attacker uses the token to invoke the corresponding Fecify API. ### Impact Assessment Successful exploitation discloses a persistent bearer-style credential. The attacker receives the API privileges assigned to that token and can continue using it until it is revoked or rotated. The scope includes the configured site and any product, image, or other management APIs authorized for the token. This issue does not independently provide operating-system privilege escalation, but it can cause remote application-level account compromise. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions 1. Store tokens in an operating-system credential service or dedicated encrypted secret store. 2. If file storage is unavoidable, create the site and session directories with mode `0700`. 3. Create credential files atomically with mode `0600`. 4. Verify and repair permissions on existing files during startup or migration. 5. Avoid placing tokens in logs, diagnostic archives, dry-run files, or error reports. 6. Separate non-sensitive site metadata from credential material. 7. Provide token deletion and rotation workflows. 8. Document the storage location and local trust assumptions. 9. Consider encrypting tokens with a key held outside the project data directory. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/base/site-config.js:27
Finding
Path Traversal Through the FECIFY_DOMAIN Environment Variable<![CDATA[ ## Vulnerability Details **File Location**: `scripts/base/site-config.js:27-50` **Vulnerability Type**: Path traversal and unintended local file access **Risk Level**: Medium ### Vulnerable Code ```js function getDomain() { // 1. 环境变量优先(临时覆盖) if (process.env.FECIFY_DOMAIN) { return process.env.FECIFY_DOMAIN.trim(); } // 2. 会话绑定文件 const sf = _sessionFile(); try { const d = fs.readFileSync(sf, 'utf8').trim(); if (d) return d; } catch { /* 不存在 */ } return null; } // ---- 设置当前会话的域名 ---- function setDomain(domain) { const sf = _sessionFile(); fs.writeFileSync(sf, domain, 'utf8'); } // ---- 获取指定域名的配置 ---- function getConfig(domain) { const file = path.join(SITES_ROOT, domain, 'config.json'); if (!fs.existsSync(file)) return null; return JSON.parse(fs.readFileSync(file, 'utf8')); } ``` Related write operations also use a domain parameter as a path component: ```js function saveInitData(domain, data) { const dir = path.join(SITES_ROOT, domain); if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); fs.writeFileSync( path.join(dir, 'init-data.json'), JSON.stringify({ data, updatedAt: new Date().toISOString() }, null, 2), 'utf8' ); } ``` ### Technical Analysis `FECIFY_DOMAIN` is trusted as a directory name and passed to `path.join` without hostname validation or a post-resolution containment check. Values containing traversal components such as `../` are normalized by the filesystem path APIs and may escape `SITES_ROOT`. In the directly observed current-configuration flow, this permits attempts to read a `config.json` outside the intended sessions directory. Exported helper functions also accept arbitrary domain strings, so future or external callers can expose corresponding write behavior through `saveConfig` or `saveInitData`. Replacing slashes in `FECIFY_SESSION` does not mitigate this separate `FECIFY_DOMAIN` path. ### A ...[truncated 1302 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Validate the domain as a hostname rather than treating it as a free-form path. 2. Reject separators, traversal components, empty labels, control characters, and absolute paths. 3. Construct the destination with `path.resolve`. 4. Verify that the resolved destination starts with the canonical `SITES_ROOT` followed by `path.sep`. 5. Use a generated identifier or cryptographic hash of the normalized hostname as the directory key. 6. Apply identical validation inside every exported function accepting a domain. 7. Treat environment overrides as untrusted input. 8. Remove `FECIFY_DOMAIN` override support if it is not operationally necessary. 9. Add tests covering `../`, absolute paths, encoded separators, Windows separators, and unusual hostname forms. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/csv-import/import-shopify-csv.js:287
Finding
Unbounded Buffering of Remote Image and API Responses<![CDATA[ ## Vulnerability Details **File Location**: `scripts/csv-import/import-shopify-csv.js:287-299`; related API buffering at `scripts/base/api-client.js:86-89` **Vulnerability Type**: Resource exhaustion and denial of service **Risk Level**: Medium ### Vulnerable Code ```js function downloadImage(url) { return new Promise((resolve, reject) => { const transport = url.startsWith('https:') ? https : http; transport.get(url, { timeout: 30000 }, (res) => { if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) { return downloadImage(res.headers.location).then(resolve).catch(reject); } if (res.statusCode !== 200) return reject(new Error(`HTTP ${res.statusCode}`)); const bufs = []; res.on('data', d => bufs.push(d)); res.on('end', () => resolve(Buffer.concat(bufs))); }).on('error', reject).on('timeout', () => reject(new Error('Timeout'))); }); } ``` The API client similarly buffers complete responses: ```js const req = transport.request(options, (res) => { let data = ''; res.on('data', chunk => data += chunk); res.on('end', () => { try { const json = JSON.parse(data); ``` ### Technical Analysis Both request implementations accumulate complete response bodies in memory without enforcing a maximum byte count. The image importer allows concurrent downloads and configurable retry counts, multiplying memory and bandwidth use. The timeout does not impose a response-size limit. A server can return a very large body quickly enough to remain within the timeout, or continuously provide data in a manner that consumes resources before termination. Declared `Content-Length` is not checked, and chunked responses have no limit at all. After download, `Buffer.concat` creates another allocation, and Base64 encoding further expands the data by approximately one third. ### Attack Path 1. An attacker supplies a CSV with image URLs under their control. 2. The imp ...[truncated 974 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Define a strict maximum image size appropriate for the upload API. 2. Reject responses whose `Content-Length` exceeds that limit. 3. Track streamed bytes and destroy the request immediately when the limit is exceeded, including for chunked responses. 4. Apply a smaller bounded limit to JSON API responses. 5. Validate image MIME types before buffering or processing. 6. Stream data into a bounded image decoder where possible instead of retaining the entire raw response. 7. Cap concurrency and retry arguments to safe ranges and reject zero, negative, `NaN`, or excessive values. 8. Limit redirect depth. 9. Apply both connection and overall response deadlines. 10. Run import work under operating-system memory and CPU limits as defense in depth. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (43)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
代码行为与声明的核心用途不一致。声明描述的是一个多站点 Fecify 管理技能,重点包括站点绑定、API Token、配置持久化,以及商品/订单/CSV 导入等业务能力;而实际代码只是一个 CSV 检测脚本,读取本地文件后识别 Shopify 商品 CSV 的表头特征、排除非商品表、分析变体结构并校验数据质量。它既不连接 Fecify 站点,也不处理会话、令牌或持久化,更不执行商品/订单管理或实际导入。虽然声明中提到“CSV 批量导入”,该代码可被视为导入前的辅助检测组件,但其对象是 Shopify CSV 且功能范围远窄于声明,因此属于明显的描述-行为不匹配。

Tp4

High
Category
MCP Tool Poisoning
Confidence
89% confidence
Finding
该代码块的核心功能非常明确:执行 Shopify 商品 CSV 到 Fecify 的批量导入,包括 CSV 解析、图片抓取与上传、商品 JSON 构建、标签生成、并发导入、失败落盘和结果汇总。它确实属于声明中“支持商品、CSV 批量导入”等范围的一部分,但声明的主要卖点——多站点管理、会话与站点绑定、URL/API Token 配置持久化、以及订单操作——在这段代码中都没有体现。按评估标准,这不是轻微实现细节缺失,而是声明的主要能力与代码实际行为存在明显范围差异,因此应判定为描述与行为不匹配。

Ae1

High
Category
analysis-evasion
Content
node scripts/csv-import/import-shopify-csv.js <CSV> [--max=N] [--skip=N] [--dry-run] [--use-network-images] [--gen-tags=none|auto|force] [--tag-count=N] [--img-
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Tool Parameter Abuse

High
Category
Tool Misuse
Content
node scripts/csv-import/detect-shopify-csv.js <CSV文件>

# Step 2 — 执行(根据用户选择组装参数)
node scripts/csv-import/import-shopify-csv.js <CSV> [--max=N] [--skip=N] [--dry-run] [--use-network-images] [--gen-tags=none|auto|force] [--tag-count=N] [--img-concurrency=N] [--img-retries=N] [--import-concurrency=N] [--skip-validation]
```
Confidence
91% confidence
Finding
The documented import command exposes a `--skip-validation` flag even though the skill earlier states detection/validation cannot be skipped. In this context, bypassing validation on bulk CSV imports can allow malformed or malicious data, bad image references, or integrity-breaking records to be ingested into a live commerce system, undermining the safety guard the workflow claims to enforce.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
node scripts/csv-import/import-shopify-csv.js <CSV> --img-concurrency=10 --import-concurrency=5

# 跳过执行层校验(仅调试用,不推荐)
node scripts/csv-import/import-shopify-csv.js <CSV> --skip-validation
```

(必须带 `FECIFY_SESSION` env)
Confidence
95% confidence
Finding
The documented --skip-validation flag disables execution-layer validation for a workflow that creates products and uploads images based on user-supplied CSV content and network resources. Even though it is labeled 'debug only, not recommended,' exposing this option in agent-facing documentation makes it easier to bypass safeguards and submit malformed or dangerous data to downstream APIs.

Credential Access

High
Category
Privilege Escalation
Content
return new Promise((resolve, reject) => {
        const config = getCurrentConfig();
        if (!config || !config.url || !config.token) {
            return reject(new Error('未配置站点信息,请先提交 URL 和 Access Token。'));
        }

        // 校验 /api/apps/{addon}/... 路径:插件必须已安装
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
*   --img-concurrency=N      图片下载上传并发数(默认 5)
 *   --img-retries=N          图片下载失败最大重试次数(默认 3)
 *   --import-concurrency=N   商品导入并发数(默认 2)
 *   --skip-validation        跳过执行层数据校验(不推荐)
 *   FECIFY_SESSION=xxx       指定会话(同其他 api-call 规则)
 */
Confidence
80% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Tool Parameter Abuse

High
Category
Tool Misuse
Content
const max = maxArg ? parseInt(maxArg.split('=')[1]) : Infinity;
  const skipArg = args.find(a => a.startsWith('--skip='));
  const skip = skipArg ? parseInt(skipArg.split('=')[1]) : 0;
  const skipValidation = args.includes('--skip-validation');
  const dryRun = args.includes('--dry-run');
  const useNetworkImages = args.includes('--use-network-images');
Confidence
80% confidence
Finding
The script exposes a runtime flag that disables execution-layer validation before importing products. In this context, the importer already performs network image fetching, file writes, and product creation across multiple managed stores, so bypassing validation makes it easier for malformed or unintended data to be pushed into production, amplifying operational and integrity risk.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
*   node scripts/proxy/api-call.js GET /api/products/list '{"page":1}'
 *   node scripts/proxy/api-call.js POST /api/products/create '{"title":"test"}'
 *   node scripts/proxy/api-call.js PUT /api/products/123 '{"title":"updated"}'
 *   node scripts/proxy/api-call.js DELETE /api/products/123
 */

const api = require('../base/api-client');
Confidence
93% confidence
Finding
The script accepts arbitrary HTTP methods and paths from command-line arguments and forwards them directly to the underlying authenticated API client, including destructive methods like DELETE. In this skill context, where a session is bound to a persisted site URL and API token, this becomes a powerful generic proxy that can modify or delete remote store data if an upstream agent, prompt, or user input is abused.

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
93% confidence
Finding
The skill explicitly states that site URL and API token are persisted under `data/fecify-shared/` and survive restarts, but it gives no user-facing warning about credential storage, retention, or access controls. Storing long-lived API credentials without transparent disclosure increases the risk of accidental exposure, unauthorized reuse across sessions, and insecure handling by operators.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The instructions tell the agent to ask for `站点URL` and `AccessToken`, then pass them directly to a save script that persists configuration and fetches initialization data, yet no warning is provided about transmitting or storing sensitive credentials. This can cause users to disclose secrets without informed consent and may place tokens into command history, logs, process listings, or persistent files.

Unsafe Defaults

Medium
Category
Tool Misuse
Content
node scripts/csv-import/detect-shopify-csv.js <CSV文件>

# Step 2 — 执行(根据用户选择组装参数)
node scripts/csv-import/import-shopify-csv.js <CSV> [--max=N] [--skip=N] [--dry-run] [--use-network-images] [--gen-tags=none|auto|force] [--tag-count=N] [--img-concurrency=N] [--img-retries=N] [--import-concurrency=N] [--skip-validation]
```
Confidence
88% confidence
Finding
Even if `--skip-validation` is optional rather than default-enabled, documenting it in the normal execution path creates an unsafe operational default because users or downstream agents may invoke it to save time. In a data-import skill for commerce operations, that weakens integrity protections and increases the chance of corrupt, unreviewed, or attacker-crafted content entering the system.

Natural-Language Policy Violations

Medium
Confidence
91% confidence
Finding
The entire skill documentation is written in Chinese and does not indicate that other languages are supported or that the language choice is optional. Under the stated policy, forcing a specific language without user opt-in can be a natural-language policy violation unless the locale constraint is documented and justified.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The documentation explicitly requires a session credential and states that failed imports are archived with full API request bodies and raw responses, but it does not warn about the sensitivity of credentials, product data, image URLs, or archived failure artifacts. This creates a realistic risk of inadvertent exposure of secrets and business data through logs, temp files, or operator handling, especially in shared environments.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The guidance explicitly directs implementers to add image downloading/uploading and API-based imports, which can transmit local or third-party data to remote services. Because the document does not require any user notice, confirmation step, or clear indication that network actions and remote mutations will occur, downstream skills built from this guidance may perform externally visible actions without informed consent.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The documented main flow includes POST-based product creation as a standard execution path, but it does not require an approval gate before modifying remote store data. In the context of a site-management skill with persistent site URL and API token, this omission is more dangerous because an agent following the guidance could make irreversible changes to a bound production store.

Missing User Warnings

Medium
Confidence
87% confidence
Finding
The documentation provides a live product-creation POST workflow, including a complete request example, but does not warn that invoking it will create persistent store data. In a skill that manages real e-commerce sites with persisted site bindings and API tokens, this increases the risk of accidental unauthorized or unintended writes to production catalogs by users or downstream agents.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
This documentation describes a destructive product update flow where callers are instructed to fetch full product data, modify fields, and resubmit complete `images`/`variants`/`options` arrays, but it does not clearly warn that omitted sub-entities may be deleted or overwritten. In a skill that manages persistent e-commerce sites bound to real shop credentials, this increases the chance of accidental inventory, media, or variant loss through normal operator use rather than an external exploit.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The module description states that it automatically reads the bound URL and token and all business scripts use it to access the API, and the implementation sends the token in the `skill-access-token` header. This is a safety-relevant network operation involving credentials, but the file contains no confirmation prompt or user-facing disclosure about that transmission.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
This code persists a sensitive access token via config.saveConfig(domain, url, token). Although the header comment describes usage, it does not warn that the token will be stored locally, and there is no runtime disclosure or confirmation before saving the credential.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
This script sends the provided access token to an arbitrary user-supplied URL and permits plain HTTP as well as HTTPS. In the context of a site-management skill that binds persistent credentials for multiple stores, this creates a real risk of credential exposure through misconfiguration, phishing, SSRF-like internal targeting, or network interception when HTTP is used.

Unsafe Defaults

Medium
Category
Tool Misuse
Content
*   --img-concurrency=N      图片下载上传并发数(默认 5)
 *   --img-retries=N          图片下载失败最大重试次数(默认 3)
 *   --import-concurrency=N   商品导入并发数(默认 2)
 *   --skip-validation        跳过执行层数据校验(不推荐)
 *   FECIFY_SESSION=xxx       指定会话(同其他 api-call 规则)
 */
Confidence
80% confidence
Finding
Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.

Unsafe Defaults

Medium
Category
Tool Misuse
Content
*   --img-concurrency=N      图片下载上传并发数(默认 5)
 *   --img-retries=N          图片下载失败最大重试次数(默认 3)
 *   --import-concurrency=N   商品导入并发数(默认 2)
 *   --skip-validation        跳过执行层数据校验(不推荐)
 *   FECIFY_SESSION=xxx       指定会话(同其他 api-call 规则)
 */
Confidence
80% confidence
Finding
Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.

Unsafe Defaults

Medium
Category
Tool Misuse
Content
*   --img-concurrency=N      图片下载上传并发数(默认 5)
 *   --img-retries=N          图片下载失败最大重试次数(默认 3)
 *   --import-concurrency=N   商品导入并发数(默认 2)
 *   --skip-validation        跳过执行层数据校验(不推荐)
 *   FECIFY_SESSION=xxx       指定会话(同其他 api-call 规则)
 */
Confidence
80% confidence
Finding
Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.

Static analysis

No suspicious patterns detected.