跳转到正文
报告库
用途分类 / 其他用途

Lark Event Skill 安全审计

作者说它能做什么(原文)

Lark/Feishu real-time event listening / subscribing / consuming: stream events as NDJSON via `lark-cli event consume <EventKey>` (covers IM messages/reactions/chat changes, Approval status changes, Task updates, VC meeting started/joined/ended, Minutes generated, Whiteboard updated, etc.). Use for Lark bots, real-time message processing, long-running subscribers, streaming webhook/push handlers. S

第三方安全检查结论

发现安全风险

已检查文件
8
发现的风险
3
会不会运行危险命令?检查是否下载程序后直接运行、让他人远程控制电脑,或藏起要运行的命令。未发现风险
会不会泄露文件和密钥?检查是否发送含密码或密钥的文件,以及代码里是否直接写了密钥。发现 1 项风险
中风险

示例会把可能含消息正文和身份标识的无限事件流明文写入本地文件

原文依据:4 处
发现了什么

Skill 展示了两个无事件上限、无超时的后台 IM 消费者,并直接重定向到 receive.ndjson 和 reaction.ndjson。接收消息事件的 content 可包含可读消息正文,sender_id 和 chat_id 可标识发送者和会话。

为什么需要注意

只要进程持续运行,聊天内容、反应和标识符就会不断积累在工作目录文件中;其他本地用户、备份、同步工具或后续处理程序可能读取这些数据,磁盘占用也会持续增长。

该风险有依据,但相关命令位于示例中,只有代理照例执行时才会发生。示例把两个后台事件流重定向到明文 NDJSON 文件,且未设置事件数或时限;默认值意味着持续运行。消息事件可包含可读正文以及发送者、会话标识,因此文件会随事件累积敏感通信数据。用户可要求限定 `--max-events`/`--timeout`,只采集必要字段,并事先确认保存位置、访问权限、保留期和删除方式。

SKILL.md:54来自说明文档
# Consume multiple EventKeys concurrently (one shape per process, no dispatcher)lark-cli event consume im.message.receive_v1          --as bot > receive.ndjson &lark-cli event consume im.message.reaction.created_v1 --as bot > reaction.ndjson &wait
查看另外 3 个位置
SKILL.md:32来自说明文档
| `--jq <expr>` | jq expression to filter / transform each event; empty output skips the event || `--max-events N` | Exit after N events. Default 0 = unlimited || `--timeout D` | Exit after duration D (e.g. `30s`, `2m`). Default 0 = no timeout. Whichever of `--max-events` / `--timeout` fires first wins || `--output-dir <dir>` | Write each event as a file (relative paths only; prevents traversal) || `--quiet` | Suppress ready/exit markers and per-event stderr diagnostics, including drop warnings. This can hide event loss. **AI should not use this** — it removes readiness and integrity signals || `--as user\|bot\|auto` | Identity for the session (see lark-shared) |
references/lark-event-im.md:28来自说明文档
**sender_id is open_id only**: the event payload carries no display name. Call the contact API separately if you need the sender's name.**`.content` shape depends on `message_type`** (this key uses a flat Custom schema; see [`events/im/message_receive.go`](../../../events/im/message_receive.go)):| message_type | `.content` shape | How to read ||---|---|---|| `text` / `post` / `image` / `file` / `audio` / `sticker` / `share_chat` / `share_user` / `media` / `system` | Human-readable text (convertlib-processed; `@mentions` resolved to display names) | Use `.content` directly || `interactive` (card) | Raw card JSON string (structured actions can't be losslessly flattened) | `.content \| fromjson` to get the card object |
references/lark-event-im.md:62来自说明文档
# group onlylark-cli event consume im.message.receive_v1 --as bot \  --jq 'select(.chat_type=="group") | {chat: .chat_id, from: .sender_id, msg: .content}'```
会不会删除文件或一直在后台运行?检查是否大范围删除文件、改写磁盘,或设置自动启动。未发现风险
会不会绕过安全保护?检查是否跳过网站安全验证、开放过多文件权限,或取消操作前的确认。发现 2 项风险
中风险

模糊的审批监听请求可能创建范围较广且不会自动撤销的服务端订阅

原文依据:4 处
发现了什么

当用户没有说明审批关系时,Skill 建议省略 subscription_type;这会为同一事件同时注册“我参与的审批”和“我管理的审批”。这些订阅在进程退出后仍保留,必须通过 event consume 之外的操作撤销。

为什么需要注意

一次临时监听可能永久扩大该用户后续接收的审批事件范围。停止进程、超时或达到事件上限都不会恢复原状态,还可能持续暴露审批状态及相关人员标识。

该风险有明确依据。审批监听的实时指引允许在关系不明确时省略 `subscription_type`,从而为同一事件注册“参与”和“管理”两类服务端关系;即使消费者正常退出,这些关系也不会被撤销。因此,含糊的“监听审批状态”请求可能产生超出用户预期且持续存在的事件订阅。用户可要求作者在注册前明确列出范围并取得确认,同时提供可验证的撤销方法。

references/lark-event-approval.md:49来自说明文档
User-intent inference:| User intent | EventKey(s) | `subscription_type` ||---|---|---|| Mentions approval instances, approval forms, approval order/status, or "instance status" | `approval.instance.status_changed_v4` | infer from relation words below || Mentions approval tasks, approval todo items, approver operations, or "task status" | `approval.task.status_changed_v4` | infer from relation words below || Says "approval status changes/events" without saying task vs instance | both EventKeys | infer from relation words below || Says "my approvals", "approvals involving me", "I requested/approved", "待我审批", "我发起/我参与" | requested EventKey(s) | `INVOLVED_APPROVAL` || Says "approvals I manage", "managed definitions", "definitions managed by me", "我管理的审批定义" | requested EventKey(s) | `MANAGED_APPROVAL` || Explicitly asks for both involved and managed, or says "all approval subscriptions" | requested EventKey(s), or both if EventKey is also ambiguous | omit `subscription_type`, or pass both values in one `-p` || Relation is ambiguous and the user wants broad coverage | requested EventKey(s), or both if EventKey is also ambiguous | omit `subscription_type` so PreConsume registers both |If the user's wording omits the relation and broad listening is acceptable, omit `subscription_type`. Ask only when registering both relations would be materially harmful.
查看另外 3 个位置
references/lark-event-approval.md:79来自说明文档
For each resolved `subscription_type`, PreConsume sends one request body:```json{"subscription_type":"INVOLVED_APPROVAL"}```If `subscription_type` is omitted, PreConsume sends two registration requests for that EventKey: one with `INVOLVED_APPROVAL`, then one with `MANAGED_APPROVAL`. If listening to both instance and task events, run two consumers; each consumer may omit `subscription_type` to register both relations for its own EventKey.
references/lark-event-approval.md:89来自说明文档
Shutdown behavior:`event consume` does not call the Approval unsubscribe APIs when it exits. This applies to graceful exit, Ctrl+C / SIGTERM, stdin EOF, `--timeout`, and `--max-events`.To stop future delivery for a user, cancel the Approval subscription relation outside this consumer. The unsubscribe APIs are separate operations and are not called by `event consume`.
references/lark-event-approval.md:58来自说明文档
| Says "approvals I manage", "managed definitions", "definitions managed by me", "我管理的审批定义" | requested EventKey(s) | `MANAGED_APPROVAL` || Explicitly asks for both involved and managed, or says "all approval subscriptions" | requested EventKey(s), or both if EventKey is also ambiguous | omit `subscription_type`, or pass both values in one `-p` || Relation is ambiguous and the user wants broad coverage | requested EventKey(s), or both if EventKey is also ambiguous | omit `subscription_type` so PreConsume registers both |If the user's wording omits the relation and broad listening is acceptable, omit `subscription_type`. Ask only when registering both relations would be materially harmful.
中风险

任务监听会留下无法由该 CLI 清理的服务端订阅

原文依据:3 处
发现了什么

任务消费者启动时会调用订阅 API,但文档称当前 CLI 元数据中没有对应取消订阅端点;正常退出也不会清理,重复运行还会再次发送订阅请求。

为什么需要注意

用户可能以为结束监听已撤销授权效果,但服务器关系仍存在。后续任务更新可能继续被推送,重复订阅还可能造成难以确认的持久账户状态。

该风险有明确依据。启动任务消费者会以用户或机器人身份调用远端订阅接口;文档明确表示当前 CLI 没有配套的取消订阅操作,正常退出不会清理,并且重启会再次订阅。其影响是用户停止本地进程后,服务端关系仍可能存在。用户可在授权前要求作者说明订阅是否幂等、如何查看和撤销关系,并将所用身份与任务范围限制到必要范围。

references/lark-event-task.md:28来自说明文档
On startup, `event consume` calls:```textPOST /open-apis/task/v2/task_v2/task_subscription?user_id_type=open_id```The Task subscription API has no matching unsubscribe endpoint in the current CLI metadata, so graceful exit has no cleanup call for this EventKey. Re-running the consumer repeats the subscribe call for the selected identity.This EventKey is single-consumer per local bus subscription: start one `event consume task.task.update_user_access_v2` process for a given app/profile/identity at a time.
查看另外 2 个位置
references/lark-event-task.md:17来自说明文档
|---|---|---|| `task.task.update_user_access_v2` | `task:task:read` | user, bot |Supports `--as user` or `--as bot`.- `--as user`: receive task updates visible to the current user through authorship, assignment, following, or other access.- `--as bot`: receive task updates for tasks the application is responsible for.
references/lark-event-task.md:36来自说明文档
This EventKey is single-consumer per local bus subscription: start one `event consume task.task.update_user_access_v2` process for a given app/profile/identity at a time.
会不会误导 AI 或隐藏内容?检查工作说明是否要求 AI 忽略你的指令、干扰检查结果,或夹带看不见的文字。未发现风险
会不会偷偷改推广链接或收款方?检查是否强制替换推广链接或收款对象,同时要求隐瞒更改。未发现风险

Skill 逻辑拆解

7 个说明模块

该 Skill 指导用户通过 lark-cli 订阅飞书事件,并将每个事件作为 NDJSON 输出;默认不限制事件数量或运行时间,只有显式设置 --max-events 或 --timeout 才会自动结束。

查看原文
SKILL.md:21来自说明文档
| `lark-cli event schema <EventKey> [--json]` | Show an EventKey's params and output schema || `lark-cli event consume <EventKey> [flags]` | Blocking consume; events → stdout NDJSON || `lark-cli event status [--json] [--fail-on-orphan]` | Inspect the local bus daemon status |
SKILL.md:32来自说明文档
| `--jq <expr>` | jq expression to filter / transform each event; empty output skips the event || `--max-events N` | Exit after N events. Default 0 = unlimited || `--timeout D` | Exit after duration D (e.g. `30s`, `2m`). Default 0 = no timeout. Whichever of `--max-events` / `--timeout` fires first wins || `--output-dir <dir>` | Write each event as a file (relative paths only; prevents traversal) |

不同事件会使用用户或机器人身份,并要求读取消息、审批、任务、会议、妙记或白板相关权限;部分事件在开始监听前还会调用飞书 API 创建服务端订阅。

查看原文
references/lark-event-approval.md:14来自说明文档
Both keys carry a **PreConsume hook** that subscribes the current authorized user through the Approval subscription APIs before listening. The consumer intentionally does **not** unsubscribe on exit; the server-side Approval subscription relation remains until it is canceled outside `event consume`. These keys require `--as user`.
references/lark-event-task.md:15来自说明文档
| EventKey | Scope | Auth ||---|---|---|| `task.task.update_user_access_v2` | `task:task:read` | user, bot |Supports `--as user` or `--as bot`.
references/lark-event-vc.md:23来自说明文档
|---|---|---|| `vc.meeting.participant_meeting_started_v1` | `vc:meeting.meetingevent:read` | user || `vc.meeting.participant_meeting_joined_v1` | `vc:meeting.meetingevent:read` | user || `vc.meeting.participant_meeting_ended_v1` | `vc:meeting.meetingevent:read` | user || `vc.note.generated_v1` | `vc:note:read` | user || `vc.recording.recording_started_v1` | `vc:recording:read` | user || `vc.recording.recording_transcript_generated_v1` | `vc:recording:read` | user || `vc.recording.recording_ended_v1` | `vc:recording:read` | user |

Skill 支持用 jq 过滤或转换事件,但运行期 jq 错误会丢弃相应事件而不终止监听;诊断只出现在 stderr 警告中。使用者若依赖该流驱动审批、任务或消息处理,需要同时监控 stderr。

查看原文
SKILL.md:139来自说明文档
`event consume` runs Process hooks that may pre-decode some payload fields (flattening V2 envelopes, rendering `.content` to plain text, etc.) — behavior differs from raw OAPI. **Always read the field's `description` before writing jq**, especially for generic field names like `content` / `data` / `body` / `payload`.**Why it matters**: blindly applying `fromjson` to an already-decoded text field makes jq error on every event and silently drop it — the consumer looks alive but emits nothing, with only a single `WARN` line buried on stderr. (This is the general behavior: any jq runtime error skips the event with a one-line WARN; the loop does not abort.)
从这里开始 · 工作说明SKILL.md
lark-event
连线表示工作说明包含的模块,不是实际运行顺序。点击模块可查看原文。

文件引用关系图

13 处引用
哪些文件发起引用引用了什么
连线表示真实的文件引用,不是运行顺序。点击节点可高亮相关连线,并查看具体文件和原文位置。虚线表示还有文件需要定位。
文件与检查记录8 个文件

检查范围与遗漏

逐文件查看涉及的内容

下方列出本次涉及的原文范围;纳入检查不代表已查清所有问题。

  • SKILL.md已纳入全文
  • references/lark-event-application.md已纳入全文
  • references/lark-event-approval.md已纳入全文
  • references/lark-event-im.md已纳入全文
  • references/lark-event-minutes.md已纳入全文
  • references/lark-event-task.md已纳入全文
  • references/lark-event-vc.md已纳入全文
  • references/lark-event-whiteboard.md已纳入全文

这份报告只针对上方版本。我们看了拿到的代码和说明文件,没有实际运行 Skill,也没有检查它另外安装的软件包。因此,这不是“保证安全”的承诺;换了版本或使用环境,结果也可能不同。

  • SKILL.md工作说明
  • references/lark-event-application.md配套文件
  • references/lark-event-approval.md配套文件
  • references/lark-event-im.md配套文件
  • references/lark-event-minutes.md配套文件
  • references/lark-event-task.md配套文件
  • references/lark-event-vc.md配套文件
  • references/lark-event-whiteboard.md配套文件

代码和说明中提到的操作

运行命令
SKILL.md:41来自说明文档
```bash# Default: stream every event for the key (no filter, no projection)
SKILL.md:67来自说明文档
## Subprocess contract
SKILL.md:75来自说明文档
`event consume` treats stdin close as a shutdown signal (wired for AI subprocess callers). **Bounded runs are exempt: when `--max-events` or `--timeout` is set (> 0), stdin EOF is ignored and the run exits only via its own bound, timeout, or SIGTERM.** For unbounded runs, `< /dev/null` / `nohup` / systemd's default `StandardInput=null` will cause an immediate graceful exit (stderr `reason: signal`). To keep an unbounded run alive:
连接外部网站
references/lark-event-whiteboard.md:27来自说明文档
Whiteboard token can be obtained via the docs OAPI [list document blocks](https://open.feishu.cn/document/ukTMukTMukTM/uUDN04SN0QjL1QDN/document-docx/docx-v1/document-block/list): the block whose `block_type=43` is a whiteboard, and `block.token` is the whiteboard token.
读取了多少行
772
文件校验值(用于核对版本)
fdbffcb11bfa8007ad83591383621cdef8b7ac0a4ab3e8ca62a5dad1c34ea8da