Back to skill

Security audit

feishu-chat-forwarder

Security checks for vulnerabilities and agentic risk

Overview

The skill performs its stated Feishu chat-forwarding function, but it can forward private chat history to arbitrary recipients and caches an access token in plaintext.

Install only if you trust the operator and Feishu app permissions, and use it only for chats and recipients where forwarding is explicitly authorized. Protect the .env and memory directories, minimize Feishu app scopes, and prefer removing disk token caching or storing the token with strict private permissions.

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:50
Finding

Tenant Access Token Stored in an Insufficiently Protected Plaintext Cache

Content
View full analysis

Vulnerability Details

File Location: index.js, lines 50-68
Vulnerability Type: Plaintext storage of a reusable bearer token
Risk Level: Medium

Vulnerable Code:

js
async function getToken() {
  try {
    if (fs.existsSync(TOKEN_CACHE_FILE)) {
      const cached = JSON.parse(fs.readFileSync(TOKEN_CACHE_FILE, 'utf8'));
      if (cached.expire > Date.now() / 1000 + 300) return cached.token;
    }
  } catch (e) {}

  const res = await post('https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal', {
    app_id: APP_ID,
    app_secret: APP_SECRET
  });
  
  if (!res.tenant_access_token) throw new Error(`Token fetch failed: ${JSON.stringify(res)}`);

  try {
    fs.writeFileSync(TOKEN_CACHE_FILE, JSON.stringify({
      token: res.tenant_access_token,
      expire: Date.now() / 1000 + res.expire
    }));
  } catch (e) {}

Technical Analysis

The Skill writes a reusable Feishu tenant access token as plaintext to the predictable path ../../memory/feishu_token.json. The fs.writeFileSync call does not specify a restrictive file mode such as 0600. A newly created file therefore receives permissions derived from the process umask and may be readable by other local accounts or processes. If the file already exists, its existing permissions remain in effect.

The implementation also performs separate existence and read operations and does not reject symbolic links or verify the file's owner, type, or permissions. In a locally hostile environment, an attacker with suitable access to the cache directory could potentially manipulate the predictable cache path. Silent exception handling further prevents administrators from learning that secure caching has failed.

The token is sent only to the official Feishu API, and obtaining such a token is necessary for the declared forwarding functionality. The vulnerability is the unnecessary persistence of that credential withou ...[truncated 1305 chars]

Remediation
View remediation

Remediation Suggestions

  • Avoid persistent token caching if obtaining a fresh short-lived token for each invocation is operationally acceptable.
  • If caching is required, create a dedicated private directory that is owned by the service account and has mode 0700.
  • Create or replace the token file atomically with mode 0600; do not rely solely on the ambient process umask.
  • Reject symbolic links and verify that the cache is a regular file owned by the expected account before reading it.
  • Use secure open flags such as exclusive creation and no-follow behavior where supported, then write through the validated file descriptor.
  • Consider a platform credential store or secrets manager instead of a plaintext filesystem cache.
  • Apply the minimum required Feishu application scopes and periodically review them so compromise of the token has limited impact.
  • Log cache security failures without including the token, application secret, or complete authentication response.
  • Remove expired cache files securely and rotate credentials after suspected exposure.

T08 · Insecure Dependencies

Note
Location
index.js:6
Finding

Undeclared Dotenv Dependency Is Resolved Outside the Audited Dependency Graph

Content
View full analysis

Vulnerability Details

File Location: index.js, line 6; package.json, lines 6-8; package-lock.json, lines 5-22
Vulnerability Type: Undeclared security-sensitive runtime dependency
Risk Level: Low

Relevant Code and Manifests:

js
// index.js
require('dotenv').config({ path: path.resolve(__dirname, '../../.env') });
json
// package.json
"dependencies": {
  "commander": "^9.0.0"
}
json
// package-lock.json
"packages": {
  "": {
    "name": "feishu-chat-forwarder",
    "version": "1.0.3",
    "dependencies": {
      "commander": "^9.0.0"
    }
  },
  "node_modules/commander": {
    "version": "9.5.0",
    "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz",
    "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==",
    "license": "MIT",
    "engines": {
      "node": "^12.20.0 || >=14"
    }
  }
}

Technical Analysis

The implementation imports dotenv, but neither package.json nor package-lock.json declares or pins that package. A clean standalone installation will ordinarily fail with a module-resolution error. In a larger deployment, Node.js may instead resolve an undeclared dotenv package from an ancestor node_modules directory.

Because imported CommonJS modules execute code immediately, resolving an unintended or compromised ancestor package can execute arbitrary code in the Skill process. This is particularly sensitive because the import occurs immediately before the Skill reads FEISHU_APP_ID and FEISHU_APP_SECRET from an external .env file. The undeclared package is not covered by this project's lockfile integrity metadata or normal dependency review.

No malicious dependency is present in the supplied project, so this is a dependency-control weakness rather than evidence of an active supply-chain compromise.

Attack Path

  1. Th ...[truncated 1098 chars]
Remediation
View remediation

Remediation Suggestions

  • Add a reviewed dotenv release to the production dependencies section of package.json.
  • Regenerate package-lock.json so the exact resolved package and integrity hash are recorded.
  • Use npm ci in an isolated project directory during deployment to enforce the lockfile and avoid undeclared dependency resolution.
  • Prefer an exact dependency version if deterministic deployments are required.
  • Run dependency provenance, license, and vulnerability checks before accepting the package version.
  • Alternatively, remove the dotenv import and require the deployment environment to provide FEISHU_APP_ID and FEISHU_APP_SECRET directly.
  • Fail explicitly when required credentials are absent, without printing their values.
  • Avoid relying on shared ancestor node_modules directories in production.
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 (5)

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 https = require('https');

// Load environment variables
require('dotenv').config({ path: path.resolve(__dirname, '../../.env') });

const APP_ID = process.env.FEISHU_APP_ID;
const APP_SECRET = process.env.FEISHU_APP_SECRET;

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill is explicitly designed to fetch recent chat history from one chat and forward it to another user or chat, but the description provides no warning about the privacy and confidentiality implications of doing so. This can enable unauthorized disclosure of sensitive messages, personal data, or internal business information, especially because the target can be any supplied open_id/chat ID.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The code persists a Feishu tenant access token to a local JSON file under ../../memory/feishu_token.json without any protections such as restrictive file permissions, encryption, or disclosure to the operator. If the host is shared, compromised, or the memory directory is readable by other users/processes, the cached bearer token can be reused to access Feishu APIs until it expires.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

This skill forwards collected chat messages to a target receiver via the Feishu merge_forward API with no confirmation prompt, warning, or policy check. Because the tool's core behavior is message exfiltration/redistribution between chats or users, misuse or operator error could disclose sensitive conversations to unintended recipients.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
92% confidence
Finding

The dependency uses a caret version range (^9.0.0), which permits automatic installation of newer minor and patch releases. This can introduce supply-chain risk by pulling in unexpected changes or a compromised upstream release, reducing build reproducibility and potentially exposing users to vulnerable versions.

Content

Scanner excerpt · package.json (reported line 7)May include surrounding context.

json
"description": "Feishu Chat Merge Forwarder",
  "main": "index.js",
  "dependencies": {
    "commander": "^9.0.0"
  }
}