Back to skill

Security audit

feishu-doc-skill

Security checks for vulnerabilities and agentic risk

Overview

This Feishu document helper mostly matches its stated purpose, but it stores reusable Feishu credentials and tokens locally in plaintext without enforcing private file permissions.

Review this skill before installing if you will use it with sensitive Feishu workspaces. Prefer environment variables or a dedicated low-scope Feishu app, avoid checking the local token/config files into any repository, restrict permissions on .feishu-user-token.json and .feishu-oauth-config.json, and confirm document targets before image insertion or any write-capable workflow.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/feishu_oauth_server.js:42
Finding
OAuth credentials and user tokens are stored without restrictive file permissions## Vulnerability Details **File Location**: `scripts/feishu_oauth_server.js:42-48` and `scripts/feishu_oauth_server.js:117-124` **Vulnerability Type**: Plaintext sensitive-data storage with environment-dependent permissions **Risk Level**: Medium ### Vulnerable Code ```js function saveCredentials(appId, appSecret) { const payload = { saved_at: new Date().toISOString(), app_id: appId, app_secret: appSecret, }; fs.writeFileSync(CONFIG_OUTPUT, `${JSON.stringify(payload, null, 2)}\n`, 'utf8'); } ``` ```js function writeTokenFile(appId, tokenData) { const payload = { saved_at: new Date().toISOString(), redirect_uri: REDIRECT_URI, app_id: appId, ...tokenData, }; fs.writeFileSync(TOKEN_OUTPUT, `${JSON.stringify(payload, null, 2)}\n`, 'utf8'); } ``` ### Technical Analysis The OAuth server writes two security-sensitive JSON files: - The optional OAuth configuration file contains the Feishu App Secret. - The token file contains the user access token and may contain other token response fields, including reusable refresh-token data. The calls to `fs.writeFileSync` do not specify a restrictive file mode such as `0o600`. Consequently, newly created file permissions depend on the process umask. In an environment with a permissive umask or shared workspace, other local users or processes may be able to read these files. The code also does not inspect or repair permissions when overwriting pre-existing files. The token file is created automatically after successful OAuth authorization. App Secret persistence is user-selectable through the “remember credentials” option, but selecting that option still stores the secret in plaintext without enforcing owner-only access. ### Attack Path 1. A user runs `scripts/feishu_oauth_server.js`. 2. The user submits a Feishu App ID and App Secret and completes OAuth authorization. 3. The server writes `.feishu-user-token.json`; if credential remembrance is enabled, it also writes `.feishu-oaut ...[truncated 1188 chars]
Remediation
## Remediation Suggestions 1. Create secret-bearing files with owner-only permissions: ```js fs.writeFileSync(CONFIG_OUTPUT, `${JSON.stringify(payload, null, 2)}\n`, { encoding: 'utf8', mode: 0o600, }); fs.writeFileSync(TOKEN_OUTPUT, `${JSON.stringify(payload, null, 2)}\n`, { encoding: 'utf8', mode: 0o600, }); ``` 2. Explicitly correct permissions after writing, including for files that already existed: ```js fs.chmodSync(CONFIG_OUTPUT, 0o600); fs.chmodSync(TOKEN_OUTPUT, 0o600); ``` 3. Use atomic writes: create a temporary file in the same directory with mode `0o600`, flush it, and rename it over the destination. This reduces the risk of partial writes and permission inconsistencies. 4. Avoid storing the App Secret when possible. Prefer environment variables or an operating-system credential store. If persistence is necessary, clearly warn that the secret will be stored locally and provide an explicit deletion mechanism. 5. Store OAuth tokens in a platform credential manager or encrypted secret store rather than plaintext JSON where supported. 6. Validate that the destination directory is not group- or world-writable and reject symbolic-link destinations before writing sensitive files. 7. Document token cleanup and revocation procedures, including deletion of both local files and revocation through Feishu when compromise is suspected.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (28)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The description presents the skill as a document read/write helper, but it also instructs starting a local OAuth server, collecting App ID/App Secret, exchanging tokens, and persisting user tokens locally. Undisclosed credential handling is security-relevant because users may supply sensitive secrets without understanding they will be stored and reused.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
The description presents the skill as a document read/write helper, but it also instructs starting a local OAuth server, collecting App ID/App Secret, exchanging tokens, and persisting user tokens locally. Undisclosed credential handling is security-relevant because users may supply sensitive secrets without understanding they will be stored and reused.

Ae1

High
Category
analysis-evasion
Content
- 如果没有用户 token,可以直接运行 `scripts/feishu_oauth_server.js`,再在 `http://127.0.0.1:3333` 页面里填写 `App ID / App Secret` 发起授权。
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- 如果没有用户 token,可以直接运行 `scripts/feishu_oauth_server.js`,再在 `http://127.0.0.1:3333` 页面里填写 `App ID / App Secret` 发起授权。
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- 如果没有用户 token,可以直接运行 `scripts/feishu_oauth_server.js`,再在 `http://127.0.0.1:3333` 页面里填写 `App ID / App Secret` 发起授权。
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Lp3

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding
The skill invokes networked Feishu APIs and accesses local environment/token files, but it does not declare any explicit tool scope or permissions boundary. This increases the chance of overbroad execution and makes it harder for users or the platform to understand that the skill can access credentials and remote services.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The skill advertises writing back to Feishu documents and inserting images without clearly warning that these actions modify remote user data. Users may authorize operations expecting read-only behavior and unintentionally alter shared documents or knowledge-base content.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill tells users to launch a local OAuth server and enter App ID/App Secret without warning that these are sensitive credentials or explaining storage and handling risks. This can lead to accidental exposure of application secrets and user access tokens, especially if the local server or token files are not properly protected.

External Transmission

Medium
Category
Data Exfiltration
Content
}

async function getAppAccessToken(appId, appSecret) {
  const response = await fetch(
    'https://open.feishu.cn/open-apis/auth/v3/app_access_token/internal',
    {
      method: 'POST',
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
async function getUserAccessToken(appId, appSecret, code) {
  const appAccessToken = await getAppAccessToken(appId, appSecret);
  const response = await fetch('https://open.feishu.cn/open-apis/authen/v1/access_token', {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${appAccessToken}`,
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
This code hard-codes Chinese-language UI content and explicitly sets the HTML document language to zh-CN. The policy for natural-language content requires either user choice/opt-in or a clearly documented justification for a locale restriction, neither of which appears in this file.

Missing User Warnings

Medium
Confidence
85% confidence
Finding
The module retrieves FEISHU_USER_ACCESS_TOKEN from the environment and also loads a saved token from .feishu-user-token.json, but the file provides no comment, log, or other user-facing disclosure that sensitive authentication material will be accessed. This matches the code-file warning requirement for credential access because the behavior is silent within this file.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
getTenantAccessToken transmits app_id and app_secret to the Feishu authentication endpoint via requestFeishuJson, which is a network operation involving sensitive data. There is no confirmation, logging, or explanatory comment in this file warning that credentials will be sent to an external service.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The markdown renderer hard-codes Chinese strings such as '飞书文档', '文档信息', '快速摘要', '主要章节', '结构统计', and '内容预览'. This enforces a specific language in user-facing output with no opt-in, selection mechanism, or justification, which matches the locale-policy violation criteria.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
The thrown error string is hardcoded in Chinese, which imposes a specific language on users without any visible choice or documented justification. This is a natural-language policy issue because the file consistently presents user-facing error text in one locale only.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
This error message is presented only in Chinese and does not offer user opt-in to that locale. Absent documentation that the skill is region-specific, forcing a single language violates the language/locale policy.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
These thrown errors use Chinese-only text for HTTP and API failure reporting, with no indication that users can select another language. That creates a language policy concern unless the skill is explicitly documented as Chinese-only.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
The timeout failure path returns a Chinese-only user-facing message and does not provide any locale choice. This is a natural-language policy violation unless a justified locale restriction is documented elsewhere.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The script fetches full Feishu document metadata and block contents, then prints the result directly to stdout without any explicit confirmation, masking, or warning. In a skill designed to read enterprise documents, this can expose sensitive internal content to logs, calling processes, terminal history, or downstream tooling if a user does not realize the data will be emitted verbatim.

Missing User Warnings

Medium
Confidence
81% confidence
Finding
This code extracts a token from a supplied Feishu URL and calls `readFeishuDoc(token)`, which implies a network operation against a remote document service. In this file there is no confirmation prompt, warning comment, or user-facing disclosure beyond a generic usage string, so users are not explicitly informed that the script will access remote document content based on the provided link.

Natural-Language Policy Violations

Low
Confidence
94% confidence
Finding
The usage message is hard-coded in Chinese (`用法:`), which imposes a specific language on users without any opt-in or documented justification. This matches the policy category for language or locale constraints expressed in natural-language strings.

Natural-Language Policy Violations

Low
Confidence
94% confidence
Finding
The script emits usage and error text in Chinese, beginning with the usage string at L25 and continuing in later user-facing messages. For a general-purpose skill, forcing a specific language without user opt-in is a natural-language policy concern under the locale/language rule.

Missing User Warnings

Low
Confidence
81% confidence
Finding
This code performs outbound HTTP requests to the Feishu API and may transmit query parameters, headers, and JSON request bodies, but there is no confirmation prompt, logging, or explanatory comment/docstring disclosing that behavior. For a general-purpose API helper, the network transmission is not directly explained in this file.

Natural-Language Policy Violations

Low
Confidence
91% confidence
Finding
The thrown error message is only in Chinese (`无法从链接中提取飞书文档 token`), which forces a specific language without any visible opt-in or locale selection. The policy requires avoiding fixed language constraints unless the locale is explicitly justified or user-selectable.

Missing User Warnings

Low
Confidence
84% confidence
Finding
The code sends an authenticated HTTP request via `requestFeishuJson` and includes a bearer access token in the Authorization header. In this file there is no confirmation prompt, logging, comment, or docstring disclosing that a remote Feishu API call will be made with user credentials.

Static analysis

Detected: suspicious.env_credential_access, suspicious.exposed_secret_literal

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/feishu_oauth_server.js:9

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/insert_feishu_local_image.js:149

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
scripts/insert_feishu_local_image.js:147