Back to skill

Security audit

feishu-mention

Security checks for vulnerabilities and agentic risk

Overview

This skill does what it claims, but it uses Feishu app secrets and group-member data in ways users should review before installing.

Install only if you are comfortable with the skill reading Feishu app credentials from OpenClaw config, querying Feishu for bot and chat-member identity data, and caching that data locally. Avoid sharing debug output or openclaw.json contents, restrict Feishu app permissions, and prefer a version that lazily uses only the selected account, hardens cache file permissions, and escapes generated XML.

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

T09 · Insecure Skill Coding Practices

Warning
Location
index.js:51
Finding
Import-Time Authentication Uses Every Configured Feishu Account<![CDATA[ ## Vulnerability Details **File Location**: `index.js:51`, `index.js:88-110`, `index.js:131-151`, `index.js:326` **Vulnerability Type**: Excessive credential use and unexpected import-time network activity **Risk Level**: Medium ### Complete Code Snippet ```javascript // Initialize bots info (async, but we trigger it) this._ensureBotInfos().catch(err => log('ERROR', 'Failed to ensure bot infos:', err.message)); ``` ```javascript // Fetch from API // We only need to fetch for accounts that have credentials const promises = Object.entries(this.accountsConfig).map(async ([accountId, config]) => { if (!config.appId || !config.appSecret) return null; try { const token = await this._getTenantAccessToken(config.appId, config.appSecret); if (!token) return null; const res = await fetch('https://open.feishu.cn/open-apis/bot/v3/info', { headers: { 'Authorization': `Bearer ${token}` } }); const data = await res.json(); if (data.code === 0 && data.bot) { return { name: data.bot.app_name, open_id: data.bot.open_id, appId: config.appId, accountId: accountId }; } } catch (e) { log('ERROR', `Failed to fetch bot info for ${accountId}:`, e.message); } return null; }); ``` ```javascript async _getTenantAccessToken(appId, appSecret) { const cache = this.tokenCache.get(appId); if (cache && Date.now() < cache.expireTime) { return cache.token; } try { const response = await fetch('https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal', { method: 'POST', headers: { 'Content-Type': 'application/json; charset=utf-8' }, body: JSON.stringify({ app_id: appId, app_secret: appSecret }) }); const data = await response.json(); if (data.code === 0) { const expireTime = Date.now() + (data.expire - 300) * 1000; this.tokenCache.set(appId, { token: data.tenant_access_token, expireTime }); return data.tenant_acc ...[truncated 2415 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove `_ensureBotInfos()` from the constructor so importing the package has no network side effects. 2. Initialize bot data lazily only after `resolve()` is called. 3. Authenticate only the account selected by the supplied `accountId`. 4. Avoid authenticating every configured bot account for discovery. Prefer a non-secret local mapping of account IDs to known OpenIDs, or retrieve one specifically mentioned bot on demand. 5. Separate configuration parsing from secret access so metadata-only operations do not retain all `appSecret` values in the resolver instance. 6. Document all network requests and identify exactly which account credentials each operation uses. 7. Add tests asserting that module import performs no network requests and that resolving through one account does not authenticate unrelated accounts. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
index.js:299
Finding
Feishu Directory Data Is Cached Without Explicit Filesystem Protection<![CDATA[ ## Vulnerability Details **File Location**: `index.js:34-36`, `index.js:118-123`, `index.js:299-306` **Vulnerability Type**: Insecure storage and unsafe cache-file handling **Risk Level**: Medium ### Complete Code Snippet ```javascript if (!fs.existsSync(this.cacheDir)) { fs.mkdirSync(this.cacheDir, { recursive: true }); } ``` ```javascript // Save to cache fs.writeFileSync(botCacheFile, JSON.stringify({ updated_at: Date.now(), data: this.botInfos }, null, 2)); ``` ```javascript saveCache(appId, chatId, membersData) { const cacheFile = this._getCacheFile(appId, chatId); fs.writeFileSync(cacheFile, JSON.stringify({ updated_at: Date.now(), members_data: membersData }, null, 2)); this.memoryCache.set(`${appId}_${chatId}`, membersData); } ``` ### Technical Analysis The resolver persists Feishu group-member records and bot information in JSON files using process-default filesystem permissions. It does not explicitly create the directory with mode `0700` or cache files with mode `0600`. The cached records can contain member names, member or OpenID identifiers, bot names, account IDs, and app IDs. Although access tokens and app secrets are not written into these cache files, the stored data is organizational directory information that should not be exposed to unrelated local users. The cache-writing operations also do not verify file ownership, reject symbolic links, validate the existing file type, or perform atomic replacement. If an attacker can write to the cache directory, a pre-created symbolic link could redirect `writeFileSync()` to another file accessible to the victim process. Alternatively, manipulated cache content can alter mention resolution because cached mappings are trusted after parsing. ### Attack Path A cache-poisoning path is: 1. A local attacker gains write access to `~/.openclaw/workspace/cache/feishu_mentions`. 2. The attacker predicts or observes `bots_info.json`, or derives a member cache filename whe ...[truncated 1380 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Create the cache directory with mode `0700`: ```javascript fs.mkdirSync(this.cacheDir, { recursive: true, mode: 0o700 }); ``` 2. Create cache files with mode `0600` and enforce that mode on existing files. 3. Before reading or writing, use `lstat()` to reject symbolic links and non-regular files. 4. Verify that existing cache files and the cache directory are owned by the current user. 5. Write to a securely created temporary file in the same directory, flush it, and atomically rename it over the destination. 6. Validate cache schemas before trusting data. Require expected field types and validate Feishu OpenIDs against an allowlisted identifier format. 7. Consider storing only the minimum fields required for mention resolution rather than complete API member records. 8. Handle permission and ownership errors explicitly instead of silently falling back to potentially unsafe cache state. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
index.js:206
Finding
Unescaped Values Are Inserted into Feishu XML Mention Tags<![CDATA[ ## Vulnerability Details **File Location**: `index.js:206-208` **Vulnerability Type**: XML or markup injection **Risk Level**: Medium ### Complete Code Snippet ```javascript buildMentionTag(name, openId) { return `<at user_id="${openId}">${name}</at>`; } ``` ### Technical Analysis The function inserts `openId` into a quoted XML attribute and `name` into an XML text node without contextual escaping or identifier validation. Member names can originate from Feishu API responses or cached member data. Aliases and direct calls to the exported `FeishuMentionResolver` class can also supply values that are not inherently trusted. A locally poisoned cache can provide both fields. XML metacharacters such as `&`, `<`, `>`, `"`, and `'` can therefore corrupt the generated tag or introduce additional markup. The attribute and text contexts require different escaping rules. The implementation currently performs neither. The `openId` should additionally be constrained to Feishu's expected identifier syntax rather than treated as arbitrary markup content. ### Attack Path 1. An attacker controls a member display name, a caller-provided mapping, or a locally cached member record. 2. The crafted record is selected during mention resolution. 3. `buildMentionTag()` interpolates the crafted `name` or `openId` directly into the XML string. 4. The resolved string is passed to a Feishu message-sending API. 5. The downstream markup parser receives malformed or attacker-altered XML, potentially changing the displayed message or introducing unintended markup elements. For example, a malicious value containing a quotation mark in `openId` can terminate the `user_id` attribute, while a name containing `<` or `&` can alter the text-node structure. ### Impact Assessment Successful exploitation can modify the structure or presentation of an outgoing Feishu message, create malformed mention tags, or cause an unintended identity or markup element to be interpreted by the do ...[truncated 180 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Escape text-node values before inserting `name`: - `&` to `&amp;` - `<` to `&lt;` - `>` to `&gt;` 2. Escape attribute values before inserting `openId`, including `&`, `<`, `>`, `"`, and `'`. 3. Validate `openId` against the documented Feishu OpenID format and reject values containing whitespace or markup characters. 4. Validate data loaded from cache and API responses before passing it to `buildMentionTag()`. 5. Prefer a trusted serializer or structured message API over manual XML string concatenation where Feishu's API supports it. 6. Add tests covering names and identifiers containing quotation marks, angle brackets, ampersands, and malformed identifier values. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
assets/debug_guide.md:7
Finding
Debugging Guide Encourages Printing the Complete Credential Configuration<![CDATA[ ## Vulnerability Details **File Location**: `assets/debug_guide.md:7-16` **Vulnerability Type**: Unsafe credential-handling guidance **Risk Level**: Low ### Complete Code Snippet ```markdown ### Step 1: Check OpenClaw Configuration The resolver depends entirely on `~/.openclaw/openclaw.json`. 1. Open the configuration file: ```bash cat ~/.openclaw/openclaw.json ``` 2. Check the `channels.feishu.accounts` section: * Does the `accountId` you use exist? * Does the bot account you want to mention exist? * Are the `appId` and `appSecret` correct? ``` ### Technical Analysis The guide recommends printing the complete `~/.openclaw/openclaw.json` file to the terminal. The same documentation explains that this file contains Feishu `appSecret` values, and the configuration may also contain unrelated OpenClaw credentials. Terminal contents can be captured by CI logs, shell session recording, screen sharing, support transcripts, or copied diagnostic output. Asking users to inspect whether the secret is correct increases the likelihood that the full secret will be displayed or shared. This is an accidental-disclosure risk in documentation rather than runtime exfiltration by the Skill. ### Attack Path 1. A user experiences a mention-resolution failure. 2. The user follows the troubleshooting guide and runs `cat ~/.openclaw/openclaw.json`. 3. The complete configuration, including application secrets, appears in terminal output. 4. The user shares the terminal output with support personnel, posts it in an issue, runs it in recorded CI, or exposes it during screen sharing. 5. Another party obtains the displayed credentials and can use the corresponding Feishu application authority until the secrets are revoked or rotated. ### Impact Assessment Exposure of a Feishu `appSecret` can allow an unauthorized party to request tenant access tokens for the affected application. The resulting privileges are bounded by the permissions granted to ...[truncated 230 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the recommendation to print the complete configuration file. 2. Provide a redacted inspection command that displays account names and whether required fields exist without showing their values. 3. Add an explicit warning never to paste `openclaw.json`, `appSecret`, access tokens, or unredacted terminal output into tickets, chat messages, or logs. 4. Provide a small diagnostic script that reports: - Whether the configuration file exists. - Which account IDs are configured. - Whether `appId` and `appSecret` fields are present. - No secret values. 5. Advise immediate secret rotation if configuration output has already been shared. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (25)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The documented purpose says the tool converts mentions into Feishu XML and should be used automatically before sending messages, but the analyzed behavior reportedly returns a different output format, adds undeclared cache-management features, and may require direct identifiers instead of using conversation context. This mismatch is dangerous because downstream agents may trust the skill's declared contract, then send malformed messages, leak identifiers, or invoke broader functionality than intended.

Ae1

High
Category
analysis-evasion
Content
const { resolve } = require('./index.js');
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Tool Parameter Abuse

High
Category
Tool Misuse
Content
**解决方案:**
*   确保 `openclaw.json` 正确。
*   尝试删除缓存文件 `rm ~/.openclaw/workspace/cache/feishu_mentions/bots_info.json` 强制刷新。

### 错误 2: 群成员解析失败
Confidence
85% 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).

Description-Behavior Mismatch

High
Confidence
98% confidence
Finding
The skill manifest requires converting mentions into Feishu/Lark XML before sending, but this resolver emits plain-text strings like '@name openid'. In a security-sensitive messaging workflow, that mismatch can silently break notification behavior and cause users or bots not to be notified, defeating the control the skill is supposed to enforce and enabling message delivery with incorrect semantics.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The README instructs users to store and use Feishu app credentials and to perform enterprise directory/member lookups, but it does not warn about protecting secrets, limiting credential exposure, or the privacy implications of resolving user identities from chat context. In an agent skill that automatically processes mentions before sending messages, this omission increases the chance that operators mishandle app secrets or perform unnecessary identity lookups without appropriate safeguards.

Lp3

Medium
Category
MCP Least Privilege
Confidence
84% confidence
Finding
The skill declares file and write requirements in metadata and its documented behavior implies network access, but it does not define a clear restrictive tool scope such as allowed-tools or equivalent permission boundaries. In an agent environment, this increases the blast radius by allowing a seemingly simple mention-formatting skill to read configuration, write cache files, and potentially call external APIs without transparent least-privilege constraints.

Natural-Language Policy Violations

Medium
Confidence
91% confidence
Finding
This markdown contains substantial usage, workflow, and API guidance only in Chinese, including the main description and parameter explanations. Because the skill does not offer an English/locale option or justify that it is intended only for Chinese-speaking users, it creates a natural-language locale constraint without user opt-in.

Description-Behavior Mismatch

Medium
Confidence
91% confidence
Finding
The documentation states that the tool automatically reads app credentials from local config and discovers bot OpenIDs, which extends behavior beyond pure text transformation into credential-backed enumeration of identities. That broader data access can surprise users and agents, and if misused could expose internal bot/account mappings or normalize over-privileged use of local secrets.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The guide explicitly instructs users to print `~/.openclaw/openclaw.json`, which may contain sensitive credentials such as `appSecret`, and to inspect local cache files containing bot identifiers. In a debugging document for an agent skill, normalizing direct secret inspection without masking or caution increases the chance those values are copied into logs, terminals, screenshots, or support channels.

Natural-Language Policy Violations

Medium
Confidence
90% confidence
Finding
The file’s natural-language strings, comments, and example inputs are entirely in Chinese, including user-facing console output and sample text. This effectively constrains usage to a specific language without any opt-in or indication that the skill is intentionally region-specific.

Missing User Warnings

Medium
Confidence
86% confidence
Finding
This code automatically uses configured Feishu app credentials to call remote APIs for bot info and later caches returned data to local JSON files, but there is no confirmation prompt or user-facing notice about the outbound requests or local persistence. The only visible messaging is internal error logging, which does not disclose the behavior to users before or during execution.

External Transmission

Medium
Category
Data Exfiltration
Content
}

    try {
      const response = await fetch('https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json; charset=utf-8' },
        body: JSON.stringify({ app_id: appId, app_secret: appSecret })
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The resolver fetches full chat membership data from Feishu and stores it on disk in a user cache directory without any consent, minimization, or protection checks. In an agent setting, this expands access from the single mentioned name to the entire member list, creating unnecessary collection and local persistence of potentially sensitive identity data.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
This markdown file presents all user-facing instructions in Chinese and does not indicate that the skill is region-specific or provide an opt-in language choice. Under the policy for natural-language violations, forcing a specific language without user opt-in is a reportable issue.

Intent-Code Divergence

Medium
Confidence
92% confidence
Finding
The module documentation explicitly says it replaces mentions with '@name openid' format, which conflicts with the skill metadata's required XML conversion behavior. This kind of documentation/implementation mismatch is dangerous because developers and agents may trust the code path as compliant and send malformed mentions, causing silent notification failures in a high-priority messaging tool.

Missing User Warnings

Medium
Confidence
85% confidence
Finding
The resolver persists chat member data locally for up to two hours under a user home directory, which may include names and open IDs. In shared, multi-user, or less-trusted agent environments, this creates unnecessary retention of potentially sensitive identity metadata and increases exposure if the host is compromised or the cache directory is accessible to other processes.

Natural-Language Policy Violations

Medium
Confidence
91% confidence
Finding
The test input string is explicitly written in Chinese and there is no indication that the skill offers language selection or that it is limited to a Chinese-specific context. This creates a natural-language policy concern because the file bakes in a specific locale without opt-in or justification.

Natural-Language Policy Violations

Low
Confidence
81% confidence
Finding
This markdown file contains user-facing instructional content only in Chinese, and it does not indicate that the skill is intentionally limited to Chinese-speaking users or a China-specific environment. Under the language/locale policy, forcing a specific language without opt-in can be a natural-language policy concern.

Natural-Language Policy Violations

Low
Confidence
95% confidence
Finding
The file title and all instructional content are presented only in Chinese, which effectively forces a specific language on users. Under the stated policy, locale or language constraints should either be optional for users or clearly justified as region-specific.

Missing User Warnings

Low
Confidence
82% confidence
Finding
This markdown explains that the skill reads `~/.openclaw/openclaw.json` for `appId`/`appSecret` values and later calls the Feishu API to retrieve group members. Although these actions are part of the feature description, the document does not explicitly warn users that the skill uses stored credentials and may access group membership data, which can affect privacy-sensitive information handling.

Natural-Language Policy Violations

Low
Confidence
91% confidence
Finding
The natural-language instructions, feature descriptions, warnings, and usage guidance are all presented in Chinese, which effectively forces a specific language for users consuming the skill documentation. The file does not indicate an opt-in, alternative language, or a justified locale-specific scope.

Description-Behavior Mismatch

Low
Confidence
88% confidence
Finding
If mention resolution may query Feishu for group membership data but the skill description omits that, users and calling agents are not fully informed about external data access and potential privacy impact. Even if the behavior is legitimate, hidden network lookups of membership information violate transparency expectations and can cause inadvertent disclosure or policy violations.

Missing User Warnings

Low
Confidence
88% confidence
Finding
The debug guide recommends enabling verbose logging with `DEBUG=true` and shows sample output containing internal identifiers like bot `open_id`, then instructs users to inspect cached bot metadata. While this is useful for troubleshooting, it can expose operational identifiers in logs and local artifacts that may later be shared or retained insecurely.

Natural-Language Policy Violations

Low
Confidence
89% confidence
Finding
The message payload is hard-coded to use the `zh_cn` locale and includes Chinese-language content without any indication that the user can choose another language or that the skill is intentionally region-specific. This matches the policy category for language or locale constraints that are not documented as optional or justified.

Natural-Language Policy Violations

Low
Confidence
88% confidence
Finding
The file's docstrings, status messages, and examples are entirely in Chinese, indicating a fixed language/locale experience. There is no indication that users can opt into another language or that the Chinese-only behavior is a documented regional requirement.

Static analysis

Detected: suspicious.env_credential_access

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
index.js:16