Back to skill

Security audit

Feishu Doc Exporter

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly does what it says, but recursive exports can write files outside the chosen output folder if Feishu folder names contain path traversal text.

Review before installing. Only use it with Feishu documents you are authorized to export, choose a secure local output directory, and avoid recursive exports on folders whose names may be controlled by others until output-path containment is fixed. Expect Markdown output only; PDF export is advertised but not implemented.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (2)

T09 · Insecure Skill Coding Practices

Warning
Location
index.js:41
Finding
Output Directory Traversal Through Untrusted Feishu Folder Names<![CDATA[ ## Vulnerability Details **File Location**: `index.js:41-45` and `index.js:100-105` **Vulnerability Type**: Path traversal through remotely supplied directory names **Risk Level**: Medium ### Vulnerable Code ```js if (recursive) { for (const item of [...items]) { if (item.type === 'folder') { const subItems = await listFolder(item.token, true); items = items.concat(subItems.map(subItem => ({ ...subItem, path: path.join(item.name, subItem.path || subItem.name) }))); } } } ``` ```js const content = await readDocument(item.token); const title = content.title || item.name; const outputSubPath = item.path ? path.join(options.output, path.dirname(item.path)) : options.output; const filePath = saveMarkdown(content.content, outputSubPath, title); console.log(`✅ 已保存到: ${filePath}`); ``` The final filesystem write occurs in `saveMarkdown`: ```js function saveMarkdown(content, outputPath, title) { const filePath = path.join(outputPath, `${title.replace(/[\/\\:*?"<>|]/g, '_')}.md`); fs.mkdirSync(path.dirname(filePath), { recursive: true }); fs.writeFileSync(filePath, content); return filePath; } ``` ### Technical Analysis Folder names and paths returned by the Feishu Drive tool are remotely controlled metadata. During recursive enumeration, the implementation passes `item.name` directly to `path.join`. It later combines the resulting `item.path` with the user-selected output directory. Although document titles are partially sanitized before being used as filenames, directory components are neither sanitized nor checked against the intended export root. Node.js normalizes `..` path components when evaluating `path.join`. Consequently, a folder name such as `../../target` can cause the resolved destination to escape `options.output`. This issue applies to recursive folder exports where an attacker can influence the names of folders included in an export. The application does not verify that the fin ...[truncated 1708 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Treat every remotely supplied folder name as an untrusted path segment. 1. Resolve the configured export directory to an absolute canonical root. 2. Sanitize or reject each remote folder component independently. 3. Reject `.`, `..`, absolute paths, NUL bytes, forward slashes, and backslashes in folder names. 4. Resolve the complete destination and confirm that it remains inside the export root before creating directories or writing files. 5. Apply the containment check immediately before every filesystem write to avoid relying solely on earlier validation. 6. Consider replacing unsafe remote names with deterministic escaped names instead of silently normalizing them. Example containment validation: ```js function resolveSafeDestination(exportRoot, relativeDirectory) { const root = path.resolve(exportRoot); const destination = path.resolve(root, relativeDirectory); if ( destination !== root && !destination.startsWith(root + path.sep) ) { throw new Error('Unsafe folder path'); } return destination; } ``` Folder components should also be validated before path construction: ```js function sanitizeFolderSegment(name) { if ( typeof name !== 'string' || name === '.' || name === '..' || name.includes('/') || name.includes('\\') || name.includes('\0') || path.isAbsolute(name) ) { throw new Error('Invalid remote folder name'); } return name; } ``` Add automated tests covering `..`, nested traversal, absolute paths, mixed separators, NUL bytes, and valid similarly named folders. Tests should assert that no generated destination can escape the resolved export root. ]]>

T08 · Insecure Dependencies

Note
Location
package-lock.json:19
Finding
Dependency Lockfile Uses a Non-Official Package Registry Mirror<![CDATA[ ## Vulnerability Details **File Location**: `package-lock.json:19-26` **Vulnerability Type**: Third-party dependency retrieved from an additional supply-chain endpoint **Risk Level**: Low ### Vulnerable Code ```json "node_modules/commander": { "version": "12.1.0", "resolved": "https://registry.npmmirror.com/commander/-/commander-12.1.0.tgz", "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", "license": "MIT", "engines": { "node": ">=18" } } ``` ### Technical Analysis The lockfile directs package managers to retrieve `commander` from `registry.npmmirror.com` rather than the official npm registry at `registry.npmjs.org`. This introduces an additional third-party endpoint into the installation trust chain. The dependency is pinned to version `12.1.0` and protected by a SHA-512 integrity value. That integrity check materially reduces the likelihood of unnoticed package substitution because modified content must match the recorded hash. No evidence in the audited files shows that the locked package is malicious. The residual concern is provenance, availability, and organizational trust: installations may contact and depend on a registry mirror that users or deployment environments have not explicitly approved. ### Attack Path 1. A user or automated build installs dependencies while honoring the committed lockfile. 2. The package manager requests the `commander` archive from `registry.npmmirror.com`. 3. The installation therefore depends on the availability and security of that mirror and its delivery path. 4. For maliciously substituted content to be accepted under normal integrity enforcement, it would also need to satisfy the pinned SHA-512 integrity value, or integrity verification would need to be bypassed or disabled. 5. If untrusted dependency content were accepted, it would run with the permissions available to the Node.js application or installation environment. ...[truncated 619 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Regenerate the lockfile using the official npm registry: ```bash npm config set registry https://registry.npmjs.org/ rm -rf node_modules package-lock.json npm install ``` 2. Review the regenerated lockfile and confirm that the `resolved` URL points to `https://registry.npmjs.org/`. 3. Preserve SHA-512 integrity metadata and ensure CI never disables lockfile or integrity verification. 4. Use `npm ci` in automated builds to enforce the committed dependency graph. 5. Configure an explicit registry allowlist in CI and production build environments. 6. If an internal or regional mirror is operationally required, document it as a trusted dependency source, authenticate it where supported, monitor it, and verify that mirrored artifacts match approved upstream package hashes. ]]>
Vulnerability Patterns
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (9)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The code generally aligns with a Feishu document export tool: it reads Feishu documents, traverses folders recursively, and writes exported content to local files. However, the declared description says it exports to Markdown/PDF, while the implementation only writes .md files and never generates PDFs despite accepting a --format option. Additionally, the code exposes a distinct folder-listing capability through the 'list' command, which is not mentioned in the description. The primary purpose is still related to Feishu document export, but the description is not fully accurate because it overstates PDF support and omits the listing function.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
This markdown file documents exporting Feishu documents to an output directory and later mentions backup and offline access, which implies copying document contents to local storage. However, it does not explicitly warn users that the operation may persist sensitive or proprietary data on disk, affecting privacy and data handling.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The README states that the tool requires read permissions for documents, folders, and files, but it presents these scopes only as setup requirements. It does not explicitly disclose to users that the skill will access workspace content and metadata and export that data outside Feishu.

Description-Behavior Mismatch

Medium
Confidence
98% confidence
Finding
The manifest describes the skill as a batch exporter to Markdown/PDF, and the CLI even exposes a `--format` option for `markdown/pdf`. However, all export paths unconditionally call `saveMarkdown(...)` and write `.md` files; there is no PDF generation logic anywhere in the implementation.

Natural-Language Policy Violations

Low
Confidence
85% confidence
Finding
Natural-language instructions and operational guidance are presented only in Chinese, which can amount to forcing a specific language without user opt-in. There is no indication that the skill is region-specific or that alternative language support is intentionally limited.

Missing User Warnings

Low
Confidence
91% confidence
Finding
This markdown file describes batch export behavior and explicitly mentions exporting images as local files, but it does not warn users that running the skill will create files and directory structures on disk. For a skill that writes potentially many documents and assets locally, a brief disclosure about local file creation and output location would improve safety clarity.

Description-Behavior Mismatch

Low
Confidence
85% confidence
Finding
The stated purpose is batch exporting Feishu docs, yet the skill exposes a standalone `list` command that enumerates folder contents and prints document tokens without performing export. This is adjacent functionality, but it is broader than the manifest's described export-only scope.

Vague Triggers

Low
Confidence
84% confidence
Finding
This manifest file describes the skill generically as a document exporter but does not specify concrete activation phrases, invocation scope, or exclusions. In a manifest context, that can make it unclear when the skill should activate versus when ordinary discussion of Feishu documents should not trigger it.

Unpinned Dependencies

Low
Category
Supply Chain
Content
"author": "铲子",
  "license": "MIT",
  "dependencies": {
    "commander": "^12.0.0"
  }
}
Confidence
40% confidence
Finding
Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
index.js:16