Back to skill

Security audit

Lark Calendar Litiao

Security checks for vulnerabilities and agentic risk

Overview

This Lark calendar/task skill is mostly aligned with its purpose, but it needs careful review because it can change real Lark records, automatically adds a fixed attendee to every created event, gathers broad employee directory data, and includes undeclared chat messaging helpers.

Install only if this skill is meant for the specific Lark tenant and organization policy where Boyang must be added to every created event. Before use, grant the Feishu app only the required calendar/task/contact scopes, avoid messaging scopes, confirm the actual default calendar ID, protect `.secrets.env`, and require explicit user confirmation before deletes, attendee/member changes, or other writes.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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 (4)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
lib/employees.mjs:48
Finding

Organization-Wide Employee Directory Collection Exceeds Name-Resolution Requirements

Content
View full analysis

Vulnerability Details

File Location: lib/employees.mjs, lines 48-77
Vulnerability Type: Excessive directory access and unnecessary collection of employee PII
Risk Level: High

Vulnerable Code

javascript
async function fetchEmployees() {
  const employees = new Map();
  let pageToken = '';

  try {
    do {
      const params = {
        department_id: '0', // Root department = all employees
        page_size: 50,
        user_id_type: 'user_id'
      };
      if (pageToken) params.page_token = pageToken;

      const result = await larkApi('GET', '/contact/v3/users', { params });

      for (const user of (result.items || [])) {
        employees.set(user.user_id, {
          user_id: user.user_id,
          name: user.name,
          en_name: user.en_name,
          nickname: user.nickname,
          email: user.email,
          mobile: user.mobile,
          department_ids: user.department_ids,
          open_id: user.open_id
        });
      }

      pageToken = result.has_more ? result.page_token : '';
    } while (pageToken);

Technical Analysis

The declared employee-directory functionality only requires converting explicitly supplied names into Lark user_id values. Instead of performing a targeted lookup, the implementation requests users from department 0, paginates through the root directory, and stores every returned employee.

It also retains sensitive or unnecessary fields, including email addresses, mobile numbers, department memberships, and Open IDs. These fields are not required for name-to-user_id resolution. The collected records remain in a process-wide cache and can subsequently be returned by the exported listEmployees() and searchEmployees() functions.

This violates least-privilege and data-minimization principles. The behavior increases the sensitivity of the application process and broadens the impact of any code that can i ...[truncated 1138 chars]

Remediation
View remediation

Remediation Suggestions

  1. Replace tenant-wide enumeration with targeted lookups for only the names explicitly supplied by the user.
  2. Request and retain only user_id, name, en_name, and, if essential, nickname.
  3. Do not retain email addresses, mobile numbers, department memberships, or Open IDs.
  4. Remove or restrict the exported listEmployees() and searchEmployees() functions unless full-directory access is an explicit, authorized feature.
  5. Use the narrowest Feishu contact scope that supports targeted lookup.
  6. Add explicit authorization checks before any directory-wide operation.
  7. Document the exact directory data accessed, its retention period, and its consumers.
  8. Clear cached directory records when they are no longer required and avoid returning mutable cached objects.

T05 · Unauthorized Access and Privilege Escalation

Error
Location
lib/calendar.mjs:96
Finding

Every Created Event Automatically Discloses Event Metadata to a Fixed User

Content
View full analysis

Vulnerability Details

File Location: lib/calendar.mjs, lines 96-107 and lib/employees.mjs, lines 202-212
Vulnerability Type: Forced attendee insertion and unintended information disclosure
Risk Level: High

Vulnerable Code

javascript
export async function createEvent({
  title,
  description = '',
  startTime,
  endTime,
  attendeeIds = [],
  location = '',
  timezone = DEFAULT_TIMEZONE,
  calendarId = DEFAULT_CALENDAR_ID
}) {
  // Always include Boyang
  const finalAttendeeIds = ensureBoyangIncluded(attendeeIds);
javascript
/**
 * Ensure Boyang is in the attendee list
 * @param {string[]} userIds
 * @returns {string[]}
 */
export function ensureBoyangIncluded(userIds) {
  if (!userIds.includes(BOYANG_USER_ID)) {
    return [...userIds, BOYANG_USER_ID];
  }
  return userIds;
}

The fixed identifier is defined as:

javascript
// Boyang's user_id - always added as attendee
export const BOYANG_USER_ID = 'dgg163e1';

Attendee creation enables notification:

javascript
return larkApi('POST', `/calendar/v4/calendars/${calendarId}/events/${eventId}/attendees`, {
  params: { user_id_type: 'user_id' },
  data: {
    attendees,
    need_notification: true
  }
});

Technical Analysis

createEvent() modifies the caller-provided attendee list by adding a fixed Lark user ID. This happens even when the caller intentionally supplies no attendees. The event itself is marked private, but adding the fixed user as an attendee gives that account access to event metadata and can trigger a notification.

Although the behavior is mentioned as a business rule in SKILL.md, it remains a substantial privilege and privacy concern because it is unconditional and cannot be disabled per event. The implementation does not require event-specific confirmation before disclosing the title, description, time, location, and other event details ...[truncated 979 chars]

Remediation
View remediation

Remediation Suggestions

  1. Remove unconditional use of ensureBoyangIncluded() from createEvent().
  2. Require callers to provide every attendee explicitly.
  3. If a mandatory organizational attendee is genuinely required, make the policy configurable and require clear per-event confirmation.
  4. Display the final attendee list before sending the event to Feishu.
  5. Provide an explicit option to disable automatic notifications.
  6. Log policy-based attendee additions without logging sensitive event contents.
  7. Add tests verifying that an empty attendee list remains empty and that no fixed account is added without explicit authorization.

T09 · Insecure Skill Coding Practices

Warning
Location
lib/calendar.mjs:8
Finding

Implemented Default Calendar Differs from the Documented Default

Content
View full analysis

Vulnerability Details

File Location: lib/calendar.mjs, lines 8-9; conflicting documentation at SKILL.md, line 26
Vulnerability Type: Security-relevant configuration mismatch causing operations on an unintended resource
Risk Level: Medium

Vulnerable Code and Configuration

The implementation uses:

javascript
// Default calendar ID (小鹦鹉 calendar)
export const DEFAULT_CALENDAR_ID = 'feishu.cn_aotpypXdLWDwgRr62Y25ie@group.calendar.feishu.cn';

The documentation states:

markdown
**Default Calendar:** `feishu.cn_caF80RJxgGcbBGsQx64bCh@group.calendar.feishu.cn` (Claw calendar)

Technical Analysis

Calendar operations use DEFAULT_CALENDAR_ID whenever the caller omits the calendar argument. The hard-coded identifier in the implementation is different from the identifier presented to users in SKILL.md.

Consequently, a user relying on the documented default cannot accurately determine which calendar will be read or modified. This is particularly dangerous for update and deletion operations because an event ID and omitted calendar option may direct an authenticated request to an unexpected calendar.

Attack Path

  1. A user reviews SKILL.md and trusts the documented default calendar.
  2. The user invokes a create, list, update, delete, or attendee-management command without --calendar.
  3. The script imports the different DEFAULT_CALENDAR_ID from lib/calendar.mjs.
  4. The authenticated API request targets the implemented calendar rather than the documented calendar.
  5. Data is created, read, modified, or deleted in an unintended resource if the application has access.

Impact Assessment

This mismatch can cause calendar metadata to be disclosed to the wrong calendar, events to be created in an unexpected group calendar, or existing events to be modified or deleted against an unintended calendar context.

Actual impact depends on the application account's access to ...[truncated 167 chars]

Remediation
View remediation

Remediation Suggestions

  1. Replace the hard-coded default with a required environment variable such as FEISHU_DEFAULT_CALENDAR_ID.
  2. Ensure the implementation and SKILL.md reference the same value.
  3. Validate the selected calendar identifier at startup and fail closed when it is absent or malformed.
  4. For destructive operations, display the resolved calendar ID and require explicit confirmation.
  5. Consider requiring --calendar for deletion and attendee-removal operations rather than applying a default.
  6. Add a test that compares the documented configuration example with the runtime default.

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
lib/lark-api.mjs:119
Finding

API Wrapper Exposes Undeclared Arbitrary Messaging Capability

Content
View full analysis

Vulnerability Details

File Location: lib/lark-api.mjs, lines 119-142
Vulnerability Type: Undeclared capability that expands application authority beyond calendar and task management
Risk Level: Medium

Vulnerable Code

javascript
/**
 * Reply to a message
 * @param {string} messageId - Message ID to reply to
 * @param {object} content - Message content
 */
export async function replyMessage(messageId, content) {
  return larkApi('POST', `/im/v1/messages/${messageId}/reply`, { data: content });
}

/**
 * Send message to a chat
 * @param {string} receiveId - Chat ID or user ID
 * @param {string} receiveIdType - 'chat_id' | 'user_id' | 'open_id'
 * @param {object} content - Message content
 */
export async function sendMessage(receiveId, receiveIdType, content) {
  return larkApi('POST', '/im/v1/messages', {
    params: { receive_id_type: receiveIdType },
    data: {
      receive_id: receiveId,
      ...content
    }
  });
}

Technical Analysis

The Skill declares calendar-event, task, attendee, and employee-name-resolution functionality. The API wrapper additionally exports functions that can reply to messages and send arbitrary content to chats or users.

The packaged command-line scripts do not currently call these functions, so no direct automatic message-sending path was identified. Nevertheless, exporting them from the shared authenticated wrapper expands the module's effective capability. Any local module or future script that imports these functions can use the configured application identity to send content if the Feishu application has the corresponding messaging scopes.

This functionality is not necessary for the declared calendar and task operations and conflicts with least-privilege design.

Attack Path

  1. The configured Feishu application is granted message-sending permissions.
  2. Code running in the same project imports sendMessage() or `r ...[truncated 779 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove sendMessage() and replyMessage() from this calendar/task Skill.
  2. If messaging is required elsewhere, place it in a separate, explicitly documented package with independent credentials and scopes.
  3. Do not grant messaging scopes to the Feishu application used by this Skill.
  4. Introduce an endpoint allowlist in larkApi() so this package can call only approved calendar, task, authentication, and narrowly required contact endpoints.
  5. Add automated tests that reject requests to undeclared API families such as /im/v1.
  6. Audit existing application scopes and revoke any permissions not required by the declared functionality.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • 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
Findings (29)

Credential Access

High
Category
Privilege Escalation
Confidence
94% confidence
Finding

The skill explicitly requires an app secret from .secrets.env, meaning it depends on highly sensitive credentials to perform organization-level actions in Lark. In the context of an agent skill with no declared scope boundary, credential exposure could enable unauthorized calendar/task manipulation and API abuse across the connected tenant.

Content

Scanner excerpt · SKILL.md (reported line 20)May include surrounding context.

Configuration

Required Environment Variables (in .secrets.env):

bash
FEISHU_APP_ID=cli_a9f52a4ed7b8ded4
FEISHU_APP_SECRET=<your-app-secret>

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · lib/lark-api.mjs (reported line 12)May include surrounding context.

js
// Load secrets from workspace root
const __dirname = dirname(fileURLToPath(import.meta.url));
config({ path: join(__dirname, '../../../../.secrets.env') });

// Debug: log loaded config (remove in production)
if (!process.env.FEISHU_APP_ID) {

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · lib/lark-api.mjs (reported line 17)May include surrounding context.

js
// Load secrets from workspace root
const __dirname = dirname(fileURLToPath(import.meta.url));
config({ path: join(__dirname, '../../../../.secrets.env') });

// Debug: log loaded config (remove in production)
if (!process.env.FEISHU_APP_ID) {

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · lib/lark-api.mjs (reported line 30)May include surrounding context.

js
let tokenExpiry = 0;

/**
 * Get or refresh access token
 */
async function getAccessToken() {
  // Return cached token if still valid (with 5 min buffer)

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · lib/lark-api.mjs (reported line 50)May include surrounding context.

js
let tokenExpiry = 0;

/**
 * Get or refresh access token
 */
async function getAccessToken() {
  // Return cached token if still valid (with 5 min buffer)

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

This calendar/task skill exposes chat messaging primitives (replyMessage, sendMessage) that are outside the stated manifest scope. In an agent context, extra outbound communication capability materially increases abuse potential because the skill could contact arbitrary users/chats, send misleading messages, or relay sensitive data without that being expected from a calendar-only integration.

Content

No source excerpt is available for this finding.

Exfiltration Commands

High
Category
Prompt Injection
Confidence
95% confidence
Finding

The presence of a generic message-sending command in a calendar/task skill creates an exfiltration and abuse channel because arbitrary content can be transmitted to users or chats. Combined with employee-directory resolution noted in the skill description, this capability could be used to target recipients precisely and leak sensitive meeting/task data or send deceptive messages.

Content

Scanner excerpt · lib/lark-api.mjs (reported line 129)May include surrounding context.

js
}

/**
 * Send message to a chat
 * @param {string} receiveId - Chat ID or user ID
 * @param {string} receiveIdType - 'chat_id' | 'user_id' | 'open_id'
 * @param {object} content - Message content

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

completeTask is presented as completing a task, but it only calls updateTask without any completion-specific fields, so callers may believe a task was completed when it was not. In an agent context, this can cause integrity issues, workflow failures, and unsafe automation decisions because downstream systems or users may rely on a state change that never occurred.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill exposes access to environment-based credentials and can perform real calendar/task mutations, but it declares no explicit tool scope or permission boundary in the skill manifest. That increases the chance of overbroad execution in an agent runtime, where the model may access secrets or invoke sensitive operations without clear policy constraints.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The skill documentation references .secrets.env usage and employee-directory resolution without warning about credential sensitivity or the privacy implications of storing and resolving employee identities. This can lead to mishandling of app secrets and inappropriate exposure of internal personnel data.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The documentation advertises create, update, and delete operations for events and tasks without warning that these actions are destructive or require explicit user confirmation. In an agent setting, this can normalize unsafe execution and lead to accidental modification or deletion of real business records.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

This code creates, updates, and deletes calendar events via remote API calls, which changes user calendar data and can notify attendees. Although the functions are documented technically, there is no user-facing confirmation, warning comment, or visible disclosure about these potentially impactful operations in this file.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

Every created event forcibly includes a specific attendee via hard-coded logic, regardless of the caller's requested attendee list. This creates a covert data-sharing and surveillance channel because sensitive meeting details, timing, and updates are automatically disclosed to an undisclosed third party.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill exposes attendee-management capabilities that are broader than the stated description of creating, updating, and deleting events/tasks plus directory lookup. Hidden scope expansion is dangerous because a user or orchestrator may invoke the skill under incomplete assumptions, causing unauthorized participant changes and notification side effects on real calendars.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

Attendee add/remove operations always send notifications and alter participant lists on remote calendar events without any indication in the skill description. This can leak meeting metadata, trigger unwanted communications, and materially change collaboration state in a way users may not anticipate.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The code hardcodes a specific employee ID and ensures that person is always added to attendee lists. This creates an undisclosed control channel that can leak meeting details to an extra participant and alters user intent during calendar operations, which is especially sensitive in a scheduling skill.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The module retrieves and stores more employee data than is needed for simple name-to-user_id resolution, including email, mobile, department IDs, and open_id, and later exposes broad listing/search helpers. In the context of a calendar skill, this expands access to internal directory data beyond the stated purpose and increases privacy and data-minimization risk if these helpers are invoked or surfaced by the agent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill fetches employee contact data from the Lark Contact API, including personally identifiable fields, without any indication in this file of user-facing disclosure, consent, or justification. While backend API access may be technically permitted, the lack of transparency is risky because users may not expect a calendar assistant to enumerate and cache directory contact details.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This module reads FEISHU_APP_ID and FEISHU_APP_SECRET from environment-backed secrets and sends them in an HTTP request to obtain an access token. While the code has technical comments, it provides no user-facing prompt, warning, or disclosure about accessing credentials and transmitting them over the network.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The natural-language comment and constant force use of feishu.cn specifically for the China Lark deployment. This imposes a locale/region choice in the skill behavior without any visible opt-in or documented user selection mechanism in this file.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

sendMessage enables arbitrary outbound chat delivery by chat ID or user ID, which is not justified by the described calendar/task functionality. In the skill context this is more dangerous because directory lookup plus messaging creates a path to target employees directly, enabling spam, phishing, or quiet exfiltration through chat.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The deleteTask function issues a DELETE request that removes a task, which is a destructive operation. Although the function has a brief docstring, it does not provide any user disclosure, confirmation prompt, or visible warning about the irreversible effect of deleting a task.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The manifest says the skill creates, updates, and deletes calendar events and tasks, but this file also exposes member management (addTaskMembers, removeTaskMembers) and task retrieval/listing (getTask, listTasks). Those are materially broader operations than the narrow CRUD wording in the description, especially assignment management and bulk listing.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

The documentation sets a default timezone of Asia/Singapore, which is a locale-specific default, but does not explain user opt-in or when that locale is appropriate. This can lead to unintended behavior for users operating in other regions and matches the policy concern about forcing a specific locale without clear choice.

Content

No source excerpt is available for this finding.

Excessive Permissions

Low
Category
Privilege Escalation
Confidence
80% confidence
Finding

Skill requests more permissions than appear necessary for its stated functionality. Review if elevated access is justified.

Content

Scanner excerpt · SKILL.md (reported line 224)May include surrounding context.

md
- `task:task:read` — Read tasks
- `contact:user.employee_id:readonly` — Read user info ✅ (already enabled)

**To add permissions:**
1. Go to [Lark Open Platform](https://open.larksuite.com/app/cli_a9f52a4ed7b8ded4/auth)
2. Add scopes: `task:task:write`, `contact:contact:readonly` (for dynamic employee lookup)
3. Re-publish the app version

Static analysis

Detected: suspicious.env_credential_access

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
lib/lark-api.mjs:15