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

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
发现的风险
2
会不会运行危险命令?检查是否下载程序后直接运行、让他人远程控制电脑,或藏起要运行的命令。未发现风险
会不会泄露文件和密钥?检查是否发送含密码或密钥的文件,以及代码里是否直接写了密钥。未发现风险
会不会删除文件或一直在后台运行?检查是否大范围删除文件、改写磁盘,或设置自动启动。发现 1 项风险
中风险

示例可无限期把聊天和审批事件写入未加保护的本地文件

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

示例把多个消费者放到后台并重定向到 `.ndjson` 文件,却没有设置事件数或超时;文档同时说明默认运行无限制。消息内容会被转换成人类可读文本,审批输出包含状态、用户标识和审批/任务标识。

为什么需要注意

只要事件持续到达,文件就会不断增长,可能占满磁盘,并在本地长期保留聊天内容和业务审批元数据。文件权限、加密、轮转和删除均未在这些指令中指定。

文档中的活动示例确实把聊天与审批流重定向到相对路径的 NDJSON 文件,并在这些示例中未设置事件数或超时;默认值意味着消费者可持续运行和积累事件数据。内容可能包括可读消息、用户标识、审批及任务标识和状态。源码没有说明文件权限,因此“未加保护”本身无法确认,但长期明文落盘造成的隐私、磁盘占用和留存风险成立。用户可要求限定时长/数量、指定受限目录并确认文件权限与清理策略。

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) |
查看另外 4 个位置
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
references/lark-event-im.md:30来自说明文档打开原文件
**`.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-approval.md:123来自说明文档打开原文件
|---|---|---|| `approval_code` | string | Approval definition code; not a subscription dimension || `instance_code` | string | Approval instance code || `task_id` | string | Approval task id || `external_id` | string | Third-party approval external id, when present || `task_external_id` | string | Third-party task external id, when emitted || `assigned_user` | object | Task assignee or operator user IDs, omitted for automatic flows without an operator || `assigned_user.open_id` | string (open_id) | Task assignee or operator open_id, when present || `assigned_user.union_id` | string (union_id) | Task assignee or operator union_id, when present || `assigned_user.user_id` | string (user_id) | Task assignee or operator tenant user_id, when present || `status` | string enum | `REVERTED`, `PENDING`, `APPROVED`, `REJECTED`, `TRANSFERRED`, `ROLLBACK`, `DONE`, `OVERTIME_CLOSE`, `OVERTIME_RECOVER` || `operate_time` | string (timestamp_ms) | Status change time |
references/lark-event-approval.md:152来自说明文档打开原文件
# Broad approval status listening:# run both EventKeys as separate processes; omit subscription_type so each registers both relations.lark-cli event consume approval.instance.status_changed_v4 \  --as user > approval-instance.ndjson &lark-cli event consume approval.task.status_changed_v4 \  --as user > approval-task.ndjson &wait
会不会绕过安全保护?检查是否跳过网站安全验证、开放过多文件权限,或取消操作前的确认。发现 1 项风险
中风险

含糊的审批请求可自动建立范围较广且退出后仍保留的账户订阅

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

当用户没有说明审批实例还是任务、也没有说明“我参与的”还是“我管理的”时,说明要求可同时选择两个 EventKey,并默认注册两种关系;它还明确说,只有在“两种关系会造成实质伤害”时才询问。每个消费者会发出两次服务器端注册,而且任何正常退出方式都不会取消它们。

为什么需要注意

一次看似临时的监听可能持续改变用户飞书账户的订阅状态,并扩大后续投递范围到其参与及管理的审批。停止本地进程不会停止未来投递,用户必须另行取消。

这是实际操作指引,而非警告或反例。用户只笼统要求监听审批状态时,Skill 可推断同时监听实例和任务;关系不明确且允许广泛监听时,又可省略参数,从而为每个 EventKey 注册“参与”和“管理”两种服务器端关系。正常退出不会撤销这些关系,因此一次含糊授权可能留下持续的账户订阅。用户可要求执行前列出 EventKey、关系和持久性,并仅注册明确指定的范围。

references/lark-event-approval.md:55来自说明文档打开原文件
| 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.
查看另外 4 个位置
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:85来自说明文档打开原文件
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:91来自说明文档打开原文件
`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`.
会不会误导 AI 或隐藏内容?检查工作说明是否要求 AI 忽略你的指令、干扰检查结果,或夹带看不见的文字。未发现风险
会不会偷偷改推广链接或收款方?检查是否强制替换推广链接或收款对象,同时要求隐瞒更改。未发现风险

Skill 逻辑拆解

7 个说明模块

此 Skill 指示代理通过已安装的 `lark-cli` 订阅飞书事件,并把事件作为 NDJSON 持续输出;默认既不限制事件数,也不设置超时。

查看原文
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) |

不同事件要求用户或机器人身份及读取权限。例如审批必须使用用户身份,会议事件需要会议、笔记或录制读取权限,白板订阅还要求目标白板的管理权限。

查看原文
references/lark-event-approval.md:63来自说明文档打开原文件
## Scopes & auth| EventKey | Scope | Auth ||---|---|---|| `approval.instance.status_changed_v4` | `approval:instance:read` | user || `approval.task.status_changed_v4` | `approval:task:read` | user |
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 |
references/lark-event-whiteboard.md:17来自说明文档打开原文件
|---|---|---|| `board.whiteboard.updated_v1` | `board:whiteboard:node:read` | user, bot |Supports `--as user` or `--as bot`. The caller must have **manage** access to the target whiteboard, otherwise the subscribe OAPI returns 403 and `event consume` exits with an auth error before listening.

部分事件会在开始监听前调用飞书 API 建立服务器端订阅;Minutes、VC 和白板声明会在正常退出时取消,而审批和任务订阅不会由该命令清理。

查看原文
references/lark-event-minutes.md:11来自说明文档打开原文件
This key uses a **Custom schema** (flat output at `.xxx`) and carries a **PreConsume hook** that auto-subscribes / unsubscribes via OAPI on first / last consumer.
references/lark-event-approval.md:91来自说明文档打开原文件
`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-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.

提供的材料只有使用说明和参考文档,没有 `lark-cli` 的实现,因此无法从这些行独立验证认证信息的存储方式、网络目标或所称路径限制是否由程序实际强制执行。

查看原文
SKILL.md:6来自说明文档打开原文件
metadata:  requires:    bins: ["lark-cli"]  cliHelp: "lark-cli event --help"---
SKILL.md:34来自说明文档打开原文件
| `--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 |
从这里开始 · 工作说明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
文件校验值(用于核对版本)
3d15881395e72a229f3b826d568699ae7bb50db31272e346ca881597a94fa116