Back to skill

Security audit

feishu-message

Security checks for vulnerabilities and agentic risk

Overview

This Feishu messaging skill has legitimate messaging features, but it needs review because it includes under-disclosed destructive and state-changing chat operations plus insecure token caching.

Install only after reviewing the Feishu app scopes and restricting credentials to the minimum needed. Avoid running undocumented scripts, remove or disable disband_chat.js unless intentional, secure or eliminate the token cache, and confirm exactly which chats, users, files, and message history the skill may access or modify.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Tool Hijacking and SpoofingModifies or replaces tools so legitimate-looking calls execute attacker logic
  • 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
Findings (5)

T09 · Insecure Skill Coding Practices

Error
Location
get.js:9
Finding

Tenant access token stored in an inadequately protected plaintext cache

Content
View full analysis
now + 60) return cached.token; } } catch (e) {} // Authentication request omitted for brevity. try { fs.writeFileSync(TOKEN_CACHE_FILE, JSON.stringify({ token: data.tenant_access_token, expire: Math.floor(Date.now() / 1000) + data.expire })); } catch(e) {} } ``` The equivalent write in `send-audio.js` is: ```js const cacheData = { token: data.tenant_access_token, expire: Math.floor(Date.now() / 1000) + data.expire }; fs.writeFileSync(TOKEN_CACHE_FILE, JSON.stringify(cacheData, null, 2)); ``` ### Technical Analysis A tenant access token is persisted as plaintext at a predictable path outside the package directory. The write operation does not specify a restrictive file mode, so effective permissions depend on the process umask and the pre-existing file. The implementation also does not verify that the cache is a regular file, reject symbolic links, verify ownership, or validate that its permissions prevent access by other users. The cache is shared by several scripts and is trusted whenever its `expire` value is sufficiently far in the future. Consequently, a local process capable of reading the cache can steal the bearer token, while a process capable of replacing the cache can cause the Skill to use an attacker-selected token. Silent exception handli ...[truncated 1436 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
disband_chat.js:21
Finding

Undocumented destructive chat-disbanding operation lacks safeguards

Content
View full analysis
"); process.exit(1); } disbandChat(chatId); ``` ### Technical Analysis The package includes a script that directly invokes `client.im.chat.delete` for an arbitrary caller-supplied chat ID. This destructive capability is not disclosed in `SKILL.md`, is not exposed as a documented unified CLI command, and has no interactive confirmation, allowlist, ownership verification, or separate authorization boundary. Although Feishu ultimately enforces application permissions, the script converts possession of the configured application credentials into a simple deletion primitive. This exceeds the minimum privileges needed for the documented retrieval, sending, chat-creation, and pin-listing features. ### Attack Path 1. An attacker, automation error, or manipulated agent action selects a target Feishu chat ID. 2. The attacker invokes `node disband_chat.js ` in an environment containing valid `FEISHU_APP_ID` and `FEISHU_APP_SECRET` values. 3. The Lark SDK authenticates using those application cre ...[truncated 732 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
list_pins_v2.js:35
Finding

Documented read-only pin listing can create or resolve a P2P chat

Content
View full analysis
', 'Chat ID') .action((chatId) => { runScript('list_pins_v2.js', [chatId]); }); ``` The invoked script instead treats the argument as a user ID and calls a chat-creation API: ```js async function getChatId(userId) { // Try to get chat_id from user_id try { const res = await client.im.chat.create({ params: { user_id_type: 'open_id' }, data: { user_id: userId } }); if (res.code === 0) return res.data.chat_id; } catch(e) {} return null; } async function main() { const userId = process.argv[2]; if (!userId) return; const chatId = await getChatId(userId); if (!chatId) { console.log("Chat not found."); return; } const pins = await listPins(chatId); } ``` ### Technical Analysis `SKILL.md` and `index.js` describe `list-pins` as a read-only operation accepting a chat ID. However, `list_pins_v2.js` interprets the same argument as an OpenID and invokes `client.im.chat.create` before listing pins. This violates least surprise and least privilege. A read-only operation should not require chat-creation permission or perform a state-changing request. It also creates a functional mismatch: a legitimate `oc_` chat ID is passed to an API configured for `open_id`, potentially causing errors, while an `ou_` user ID may resolve or create P2P chat state that the caller did not request. ### Attack Path 1. A caller invokes the documented command `index.js list-pins `, expecting only pin retrieval. 2. `index.js` forwards the supplied identifi ...[truncated 732 chars]
Remediation
View remediation
` performs only read operations and sends the identifier in the correct SDK field. - Avoid empty catch blocks; report API failures sufficiently to distinguish invalid input from authorization errors. ]]>

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
get_latest_file.js:27
Finding

Undocumented utility enumerates chat message history and may modify P2P chat state

Content
View full analysis
m.msg_type === 'file'); if (fileMsg) { console.log(JSON.stringify(fileMsg, null, 2)); } else { console.log("No file message found."); } } else { console.log("Error or no messages:", JSON.stringify(data)); } } ``` ### Technical Analysis The utility is packaged but not documented in `SKILL.md`. It obtains a tenant token, optionally sends a POST request to the P2P chat endpoint for a supplied user OpenID, and then requests the target chat's message collection. It searches locally for a file message only after retrieving message-history data. This behavior requires broader access than the documented single-m ...[truncated 1379 chars]
Remediation
View remediation

T07 · Tool Hijacking and Spoofing

Warning
Location
index.js:47
Finding

Send command executes an unaudited sibling script with inherited credentials

Content
View full analysis
', 'Target ID') .option('-c, --content ', 'Content') .option('-x, --text ', 'Text') .option('--title ', 'Title') .action((options) => { const scriptPath = path.resolve(__dirname, '../feishu-post/send.js'); const args = ['--target', options.target]; if (options.content) args.push('--content', options.content); if (options.text) args.push('--text', options.text); if (options.title) args.push('--title', options.title); const child = spawn(process.execPath, [scriptPath, ...args], { stdio: 'inherit', env: process.env }); child.on('close', (code) => process.exit(code)); }); ``` The standalone wrapper has the same trust dependency: ```js const targetScript = path.resolve(__dirname, '../feishu-post/send.js'); const args = process.argv.slice(2); const child = spawn('node', [targetScript, ...args], { stdio: 'inherit' }); ``` ### Technical Analysis The documented `send` command does not execute an implementation contained in this project. It launches `../feishu-post/send.js`, which lies outside the audited package, and supplies the complete process environment. The inherited environment can include `FEISHU_APP_ID`, `FEISHU_APP_SECRET`, proxy settings, and unrelated secrets. Using `spawn` with an argument array prevents ordinary shell metacharacter injection through message content. The security issue is instead the mutable external trust boundary: replacing or compromising the sibling script changes this Skill's effective behavior without changing the revi ...[truncated 1561 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (46)

Known Vulnerable Dependency: protobufjs==7.5.4 — 12 advisory(ies): CVE-2026-44294 (protobuf.js: Denial of service from crafted field names in generated code); CVE-2026-44293 (protobuf.js: Code injection through bytes field defaults in generated toObject c); CVE-2026-44289 (protobuf.js: Denial of service through unbounded protobuf recursion) +9 more

Critical
Category
Supply Chain
Confidence
95% confidence
Finding

protobufjs 7.5.4 is flagged with multiple serious advisories including denial of service and possible code-generation/injection issues. Because it is a dependency of the Lark/Feishu SDK, it may be exercised during API serialization/deserialization; if any attacker-influenced protobuf schemas or payloads are processed, this creates a significant risk of crashes, unbounded recursion, or worse depending on feature usage.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · create_chat.js (reported line 19)May include surrounding context.

js
const path = require('path');
require('dotenv').config({ path: path.resolve(__dirname, '../../.env') });

// Try to load Lark SDK
let Lark;

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · disband_chat.js (reported line 2)May include surrounding context.

js
const path = require('path');
require('dotenv').config({ path: path.resolve(__dirname, '../../.env') });

// Try to load Lark SDK
let Lark;

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · get.js (reported line 5)May include surrounding context.

js
const path = require('path');
require('dotenv').config({ path: path.resolve(__dirname, '../../.env') });

// Try to load Lark SDK
let Lark;

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · get_chat_info.js (reported line 2)May include surrounding context.

js
const path = require('path');
require('dotenv').config({ path: path.resolve(__dirname, '../../.env') });

// Try to load Lark SDK
let Lark;

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · get_latest_file.js (reported line 4)May include surrounding context.

js
const path = require('path');
require('dotenv').config({ path: path.resolve(__dirname, '../../.env') });

// Try to load Lark SDK
let Lark;

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · index.js (reported line 7)May include surrounding context.

js
const path = require('path');
require('dotenv').config({ path: path.resolve(__dirname, '../../.env') });

// Try to load Lark SDK
let Lark;

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · list_pins.js (reported line 4)May include surrounding context.

js
const path = require('path');
require('dotenv').config({ path: path.resolve(__dirname, '../../.env') });

// Try to load Lark SDK
let Lark;

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · list_pins_v2.js (reported line 4)May include surrounding context.

js
const path = require('path');
require('dotenv').config({ path: path.resolve(__dirname, '../../.env') });

// Try to load Lark SDK
let Lark;

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · send-audio.js (reported line 8)May include surrounding context.

js
const path = require('path');
require('dotenv').config({ path: path.resolve(__dirname, '../../.env') });

// Try to load Lark SDK
let Lark;

Known Vulnerable Dependency: axios==1.13.4 — 16 advisory(ies): CVE-2026-44494 (axios Vulnerable to Full Man-in-the-Middle via Prototype Pollution Gadget in `co); CVE-2026-44495 (axios Vulnerable to Credential Theft and Response Hijacking via Prototype Pollut); CVE-2025-62718 (Axios has a NO_PROXY Hostname Normalization Bypass that Leads to SSRF) +13 more

High
Category
Supply Chain
Confidence
94% confidence
Finding

axios is a directly used HTTP client and the reported advisories include SSRF/proxy-bypass, prototype-pollution gadgetry, and response/credential interception classes of issues. In an agent skill that likely sends outbound requests to Feishu/Lark and possibly user-influenced URLs or proxy settings, a vulnerable HTTP client materially increases the risk of SSRF, credential leakage, and request hijacking.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: form-data==4.0.5 — 1 advisory(ies): CVE-2026-12143 (form-data: CRLF injection in form-data via unescaped multipart field names and f)

High
Category
Supply Chain
Confidence
92% confidence
Finding

form-data is directly depended on and the advisory indicates CRLF injection through unescaped multipart field names/filenames. In a messaging or upload-oriented skill, if any multipart field metadata is derived from user-controlled input, this can corrupt request bodies, smuggle unintended headers/parts, or alter downstream server interpretation.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: music-metadata==11.11.2 — 1 advisory(ies): CVE-2026-32256 (music-metadata has an infinite loop vulnerability in ASF parser)

High
Category
Supply Chain
Confidence
93% confidence
Finding

music-metadata is directly included and is specifically meant to parse media metadata, making malformed-file parser bugs highly relevant. The reported infinite loop in ASF parsing can let an attacker trigger CPU exhaustion or service hangs by supplying a crafted media file, which is especially concerning if the skill processes uploads or remote media.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: ws==8.19.0 — 2 advisory(ies): CVE-2026-45736 (ws: Uninitialized memory disclosure); CVE-2026-48779 (ws: Memory exhaustion DoS from tiny fragments and data chunks)

High
Category
Supply Chain
Confidence
90% confidence
Finding

ws is a transitive dependency of the Lark/Feishu SDK, and the reported issues include memory disclosure and memory exhaustion from crafted fragments. If the skill opens WebSocket connections or uses SDK features backed by ws, a malicious peer or man-in-the-middle could potentially leak process memory contents or exhaust resources.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: axios==1.13.4 — 16 advisory(ies): CVE-2026-44494 (axios Vulnerable to Full Man-in-the-Middle via Prototype Pollution Gadget in `co); CVE-2026-44495 (axios Vulnerable to Credential Theft and Response Hijacking via Prototype Pollut); CVE-2025-62718 (Axios has a NO_PROXY Hostname Normalization Bypass that Leads to SSRF) +13 more

High
Category
Supply Chain
Confidence
98% confidence
Finding

The package depends on axios 1.13.4, which is reported here as affected by multiple advisories including SSRF- and prototype-pollution-related issues. In a Feishu messaging skill that likely performs outbound HTTP requests and handles tokens or message content, a vulnerable HTTP client materially increases the risk of request manipulation, credential leakage, or access to internal network resources.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: form-data==4.0.5 — 1 advisory(ies): CVE-2026-12143 (form-data: CRLF injection in form-data via unescaped multipart field names and f)

High
Category
Supply Chain
Confidence
96% confidence
Finding

form-data 4.0.5 is reported as vulnerable to CRLF injection via multipart field names/filenames. If this skill uploads files or forwards user-controlled metadata, an attacker may be able to craft multipart requests that alter request structure or inject unintended headers/content to downstream services.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: music-metadata==11.11.2 — 1 advisory(ies): CVE-2026-32256 (music-metadata has an infinite loop vulnerability in ASF parser)

High
Category
Supply Chain
Confidence
95% confidence
Finding

music-metadata 11.11.2 is reported as having an infinite loop vulnerability in its ASF parser. In a skill that may inspect media attachments from messages, parsing attacker-supplied files could cause denial of service through CPU consumption or hung processing, especially in unattended agent workflows.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill documents a command that uploads a local audio file and sends it, together with recipient identifiers, to Feishu without any warning that local file contents and target IDs will be transmitted to an external service. This can lead users to disclose sensitive recordings or mis-send data to unintended recipients, especially in automated or agent-assisted contexts where remote side effects are easy to overlook.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The create-chat command performs a remote action that creates a new group chat and involves other users, but the skill description does not warn about that side effect. In an agent setting, users may interpret this as a harmless lookup-style action and unintentionally trigger external changes that notify or affect coworkers.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The code loads Feishu credentials from a .env file and caches the resulting access token to a local JSON file without warning the user or enforcing secure storage semantics. A cached bearer token on disk can be reused by other local users, malware, or later processes if file permissions are weak, leading to unauthorized API access.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The script retrieves message data from a remote Feishu API and later prints message contents directly to stdout without any warning, redaction, or confirmation step. In a CLI skill context this can expose private chat content, secrets, or personal data into terminal logs, shell history capture, CI logs, or higher-level agent output channels.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The script reads sensitive credentials from environment variables to authenticate against the Feishu API, but there is no prompt, comment, or docstring warning the user that credentials will be used. For code files, credential access should be disclosed unless clearly communicated elsewhere in the skill description, which is not present in this file.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · get.js (reported line 21)May include surrounding context.

js
const cached = JSON.parse(fs.readFileSync(TOKEN_CACHE_FILE, 'utf8'));
        if (cached.expire > Math.floor(Date.now() / 1000) + 60) return cached.token;
    }
    const res = await fetch('https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ app_id: APP_ID, app_secret: APP_SECRET })

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · get_latest_file.js (reported line 18)May include surrounding context.

js
const cached = JSON.parse(fs.readFileSync(TOKEN_CACHE_FILE, 'utf8'));
        if (cached.expire > Math.floor(Date.now() / 1000) + 60) return cached.token;
    }
    const res = await fetch('https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ app_id: APP_ID, app_secret: APP_SECRET })

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The code sends app credentials to Feishu's authentication endpoint and later transmits chat identifiers to messaging endpoints. Although there is a progress log for history fetching, there is no explicit disclosure that user/system data will be sent over the network, which this rule requires for safety-relevant network operations.

Content

No source excerpt is available for this finding.