Back to skill

Security audit

feishu-video

Security checks for vulnerabilities and agentic risk

Overview

The voice-message skill mostly matches its stated Feishu purpose, but it needs Review because it includes underdeclared video-sending capability and unsafe app-secret handling examples.

Install only after reviewing whether you want this package to support video as well as audio. Use least-privilege Feishu app scopes, avoid passing app secrets as command-line arguments, prefer a secret manager or carefully controlled environment variables, and treat any selected media file as uploaded to Feishu/Lark. If you only need voice messages, remove or ignore the video script and documentation before use.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/send-voice.mjs:20
Finding
Feishu app secret exposed through command-line arguments<![CDATA[ ## Vulnerability Details **File Location**: `scripts/send-voice.mjs:20-28, 62-63`; `scripts/send-video.mjs:22-30, 70-71`; `SKILL.md:49-57`; `README.md:39-47, 51-58` **Vulnerability Type**: Sensitive credential exposure through process arguments and shell history **Risk Level**: Medium ### Vulnerable Code From `scripts/send-voice.mjs:20-28`: ```javascript const { values: args } = parseArgs({ options: { 'app-id': { type: 'string' }, 'app-secret': { type: 'string' }, 'user-id': { type: 'string' }, 'chat-id': { type: 'string' }, 'audio-file': { type: 'string' }, 'duration': { type: 'string' }, 'help': { type: 'boolean', short: 'h' } } }); ``` From `scripts/send-voice.mjs:62-63`: ```javascript const APP_ID = args['app-id'] || process.env.FEISHU_APP_ID; const APP_SECRET = args['app-secret'] || process.env.FEISHU_APP_SECRET; ``` The same pattern occurs in `scripts/send-video.mjs:22-30, 70-71`. The documentation actively demonstrates passing the secret as an argument. For example, `SKILL.md:49-57` contains: ```bash node scripts/send-voice.mjs \ --app-id "cli_xxx" \ --app-secret "xxx" \ --user-id "ou_xxx" \ --audio-file "audio.opus" \ --duration 3480 ``` ### Technical Analysis Command-line arguments are not an appropriate channel for long-lived application secrets. Depending on the operating system and execution environment, arguments can be recorded or exposed through: - Shell history files - Process-listing and monitoring tools - CI/CD job logs - Agent tool-call or execution logs - Terminal session recording - Debugging and telemetry systems Although the scripts also support `FEISHU_APP_SECRET`, the CLI option remains enabled and is promoted in the primary usage examples. This makes accidental credential exposure likely during ordinary documented use. The secret is transmitted only to Feishu's declared HTTPS authentication endpoint, which is necessary for the Skill's opera ...[truncated 1619 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the `--app-secret` command-line option from both message-sending scripts. 2. Remove all examples that place secrets directly in command lines. 3. Prefer a dedicated secret manager supplied by the deployment environment. 4. If secret-manager integration is unavailable, read the secret from hidden standard input or a protected file descriptor. 5. Environment variables may be retained as a compatibility mechanism, but operators should be warned that some process-management and diagnostic environments can capture them. 6. Ensure execution systems redact `FEISHU_APP_SECRET` and tenant tokens from logs and traces. 7. Apply minimum Feishu application scopes needed for media upload and bot message delivery. 8. Rotate the existing app secret if real credentials have previously been entered using the documented command-line form. 9. Add automated tests or linting rules that reject examples containing `--app-secret`. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
scripts/send-video.mjs:169
Finding
Temporary video covers and segments are not reliably deleted after failures<![CDATA[ ## Vulnerability Details **File Location**: `scripts/send-video.mjs:169-183, 230-247, 327-351` **Vulnerability Type**: Unsafe temporary-file lifecycle and residual sensitive media **Risk Level**: Low ### Vulnerable Code Cover images are created in a temporary directory at `scripts/send-video.mjs:169-183`: ```javascript function extractCoverImage(filePath) { const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'feishu-video-')); const coverPath = path.join(tempDir, 'cover.jpg'); execFileSync('ffmpeg', [ '-y', '-i', filePath, '-frames:v', '1', '-q:v', '2', coverPath ], { stdio: 'ignore' }); return coverPath; } ``` Video segments are similarly created at `scripts/send-video.mjs:230-247`: ```javascript const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'feishu-video-seg-')); const outputPattern = path.join(tempDir, 'segment-%03d.mp4'); execFileSync('ffmpeg', [ '-y', '-i', filePath, '-c', 'copy', '-f', 'segment', '-segment_time', `${segmentSeconds}`, '-reset_timestamps', '1', outputPattern ], { stdio: 'ignore' }); const segments = fs.readdirSync(tempDir) .filter(name => name.endsWith('.mp4')) .sort() .map(name => path.join(tempDir, name)); return { segments, tempDir }; ``` Cleanup occurs only on successful control paths at `scripts/send-video.mjs:327-351`: ```javascript if (!SKIP_COVER) { try { const coverPath = extractCoverImage(segmentPath); imageKey = await uploadCoverImage(token, coverPath); fs.rmSync(path.dirname(coverPath), { recursive: true, force: true }); } catch (error) { console.warn(`⚠️ ${segmentLabel}Failed to generate cover image, sending without cover`); console.warn(` ${error.message}`); } } await sendVideoMessage(token, fileKey, imageKey); if (segmentTempDir) { fs.rmSync(segmentTempDir, { recursive: true, force: true }); } ``` ### Technical Analysis Temporary file ...[truncated 2034 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Track every created temporary directory immediately after creation. 2. Place cleanup in a `finally` block so it executes after success, API failure, local-tool failure, or message-send failure. 3. Use a single top-level temporary workspace for each invocation and recursively remove it in `finally`. 4. Ensure temporary directories and generated files are accessible only to the current operating-system user. 5. Add signal handlers for graceful cleanup on normal termination signals where practical. 6. Consider streaming uploads or avoiding derived files when supported by the API and media tooling. 7. Add tests that simulate failures during cover upload, segment upload, and message sending, then verify that no temporary media remains. 8. Retain periodic operating-system cleanup of stale temporary files as defense in depth, not as the primary lifecycle control. A suitable structure is: ```javascript let tempDir = null; try { tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'feishu-video-')); // Generate, upload, and send media. } finally { if (tempDir) { fs.rmSync(tempDir, { recursive: true, force: true }); } } ``` ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (20)

Credential Access

High
Category
Privilege Escalation
Content
| Endpoint | Description |
|----------|-------------|
| `/auth/v3/tenant_access_token/internal` | Get access token |
| `/im/v1/files` | Upload audio file |
| `/im/v1/messages` | Send voice message |
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
## API Details

### 1. Get Tenant Access Token
```
POST https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal
```
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
## API Details

### 1. Get Tenant Access Token
```
POST https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal
```
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
## API Details

### 1. Get Tenant Access Token
```
POST https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal
```
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
## API Details

### 1. Get Tenant Access Token
```
POST https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal
```
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
## API Details

### 1. Get Tenant Access Token
```
POST https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal
```
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
## API Details

### 1. Get Tenant Access Token
```
POST https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal
```
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Description-Behavior Mismatch

High
Confidence
99% confidence
Finding
The file implements video-message sending even though the skill is described and scoped as an audio/voice messaging skill. This capability mismatch is dangerous because it expands the skill's effective permissions and data-handling behavior beyond what a reviewer or user would reasonably expect, enabling covert or unauthorized media exfiltration under misleading packaging.

Description-Behavior Mismatch

Medium
Confidence
98% confidence
Finding
The manifest states the skill is for sending voice/audio messages to Feishu users, and the README repeatedly frames the skill as voice-message focused. However, the documented commands include a separate `send-video.mjs` flow for sending video messages, which expands the behavior beyond the declared audio-only scope.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The skill documentation instructs users to upload and send audio/video content to Feishu APIs but does not clearly warn that user-provided media will leave the local environment and be transmitted to a third-party service. In an agent setting, this can cause accidental disclosure of sensitive recordings or videos if the user does not realize external transfer occurs.

Lp3

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The skill documents use of environment variables and outbound network calls to Feishu APIs, but it does not declare any explicit tool scope or permissions boundaries. This increases the chance that an agent or user invokes the skill without clear awareness that secrets will be read from the environment and data will be transmitted externally.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The skill instructs users to provide Feishu app credentials and upload audio content to Feishu, but it does not warn that credentials and user audio will leave the local environment and be sent to a third-party service. This can lead to accidental disclosure of sensitive voice content or misuse of app secrets by users who do not realize the privacy implications.

Context-Inappropriate Capability

Medium
Confidence
96% confidence
Finding
The segmentation, cover extraction, upload, and send workflow introduces substantial video-processing capability that is unjustified for an audio-only skill. Even if the code uses legitimate Feishu APIs, the hidden expansion of media handling increases attack surface and creates a trust-boundary violation between declared purpose and actual behavior.

External Transmission

Medium
Category
Data Exfiltration
Content
formData.append('image_type', 'message');
    formData.append('image', new Blob([coverBuffer]), 'cover.jpg');

    const response = await fetch('https://open.feishu.cn/open-apis/im/v1/images', {
        method: 'POST',
        headers: {
            'Authorization': `Bearer ${token}`
Confidence
60% 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
// Get Tenant Access Token
async function getTenantAccessToken() {
    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'
Confidence
60% 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
// Get Tenant Access Token
async function getTenantAccessToken() {
    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'
Confidence
60% 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
formData.append('duration', DURATION_MS.toString());
    formData.append('file', new Blob([audioBuffer]), fileName);

    const response = await fetch('https://open.feishu.cn/open-apis/im/v1/files', {
        method: 'POST',
        headers: {
            'Authorization': `Bearer ${token}`
Confidence
60% 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
formData.append('duration', DURATION_MS.toString());
    formData.append('file', new Blob([audioBuffer]), fileName);

    const response = await fetch('https://open.feishu.cn/open-apis/im/v1/files', {
        method: 'POST',
        headers: {
            'Authorization': `Bearer ${token}`
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Description-Behavior Mismatch

Low
Confidence
85% confidence
Finding
The documentation's API endpoint section lists only token retrieval, file upload for audio, and message sending for voice messages, reinforcing an audio-only purpose. Elsewhere, the same README documents video-message sending, indicating the skill behavior exceeds the stated audio-message scope.

Natural-Language Policy Violations

Low
Confidence
95% confidence
Finding
The file includes user-facing example output entirely in Chinese, which can indicate a fixed language/locale assumption. The skill does not state that Chinese output is optional, configurable, or required for a region-specific use case.

Static analysis

Detected: suspicious.env_credential_access

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/send-video.mjs:70

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/send-voice.mjs:62