Back to skill

Security audit

飞书周报

Security checks for vulnerabilities and agentic risk

Overview

This weekly-report skill is coherent, but needs Review because it reads Feishu app secrets and private chat history with weak consent and secret-handling controls.

Install only if you intend the agent to access Feishu app credentials, Feishu chat contents, and workspace memory logs. Confirm the chat IDs and date range before each run, restrict the Feishu app to minimum message-read scopes, avoid printing or passing app_secret on the command line, and review or delete memory files that may retain sensitive work details.

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/fetch_feishu_messages.sh:9
Finding
Feishu application secret exposed through Agent output and process arguments<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:20-30`; `scripts/fetch_feishu_messages.sh:9-16` **Vulnerability Type**: Credential exposure through command output and process arguments **Risk Level**: Medium ### Vulnerable Code ```bash # SKILL.md:20-30 2. From the OpenClaw configuration, obtain the Feishu app_id and app_secret: ```bash grep -E "appId|appSecret" ~/.openclaw/openclaw.json ``` 3. Obtain the current chat_id from the inbound context. 4. Calculate timestamps and execute the retrieval script: ```bash START_TS=$(python3 -c "import datetime; d=datetime.datetime(2026,2,24,0,0,tzinfo=datetime.timezone(datetime.timedelta(hours=8))); print(int(d.timestamp()))") END_TS=$(python3 -c "import datetime; d=datetime.datetime(2026,2,28,23,59,59,tzinfo=datetime.timezone(datetime.timedelta(hours=8))); print(int(d.timestamp()))") bash <skill_dir>/scripts/fetch_feishu_messages.sh <app_id> <app_secret> <chat_id> $START_TS $END_TS ``` ``` ```bash # scripts/fetch_feishu_messages.sh:9-16 APP_ID="${1:?Usage: $0 <app_id> <app_secret> <chat_id> <start_ts_s> <end_ts_s>}" APP_SECRET="${2:?}" CHAT_ID="${3:?}" START_TS="${4:?}" END_TS="${5:?}" TOKEN=$(curl -s -X POST 'https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal' \ -H 'Content-Type: application/json' \ -d "{\"app_id\":\"${APP_ID}\",\"app_secret\":\"${APP_SECRET}\"}" \ | python3 -c "import sys,json; print(json.load(sys.stdin).get('tenant_access_token',''))") ``` ### Technical Analysis The Skill instructs the Agent to use `grep` without suppressing output to extract `appId` and `appSecret`. This can place the secret in the Agent transcript, tool output, execution logs, or other retained telemetry. The secret is then supplied as a positional command-line argument to the shell script. On systems where process metadata is visible to other users or monitoring software, the script's command line can be read from process inspection interfaces such as `/proc/<pi ...[truncated 1848 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not print secrets into Agent or tool output. Replace the documented `grep` command with a dedicated credential-loading mechanism that extracts only the required values without displaying them. 2. Prefer a credential broker, secret manager, or narrowly scoped helper process that performs authentication without returning the application secret to the Agent. 3. Do not pass `app_secret` as a positional command-line argument. Read it from a permission-restricted file descriptor or standard input. 4. Send the JSON request body to curl through standard input so it is not present in curl's argument vector. For example: ```bash TOKEN=$( python3 - "$APP_ID" <<'PY' | curl --fail-with-body --silent --show-error \ -X POST \ -H 'Content-Type: application/json' \ --data-binary @- \ 'https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal' import json import os import sys print(json.dumps({ "app_id": sys.argv[1], "app_secret": os.environ["FEISHU_APP_SECRET"] })) PY ) ``` The environment is still potentially observable on some systems, so a secret manager or inherited file descriptor is preferable for higher-assurance deployments. 5. Ensure `~/.openclaw/openclaw.json` has restrictive filesystem permissions and never include its secret fields in logs. 6. Rotate the existing application secret if the documented workflow has already been used in environments with retained command output. 7. Restrict the Feishu application's scopes to the minimum message-read permissions required for the weekly-report workflow. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/fetch_feishu_messages.sh:22
Finding
Unvalidated identifiers and pagination tokens are concatenated into authenticated Feishu API URLs<![CDATA[ ## Vulnerability Details **File Location**: `scripts/fetch_feishu_messages.sh:22-27` **Vulnerability Type**: Authenticated API query-parameter injection **Risk Level**: Medium ### Vulnerable Code ```bash PAGE_TOKEN="" HAS_MORE=true while [ "$HAS_MORE" = "true" ]; do URL="https://open.feishu.cn/open-apis/im/v1/messages?container_id_type=chat&container_id=${CHAT_ID}&start_time=${START_TS}&end_time=${END_TS}&sort_type=ByCreateTimeAsc&page_size=50" [ -n "$PAGE_TOKEN" ] && URL="${URL}&page_token=${PAGE_TOKEN}" RESP=$(curl -s "$URL" -H "Authorization: Bearer $TOKEN") ``` ### Technical Analysis `CHAT_ID`, `START_TS`, `END_TS`, and `PAGE_TOKEN` are directly concatenated into a URL without format validation or URL encoding. Characters such as `&`, `=`, `#`, and percent-encoded delimiters can alter the resulting query string rather than remaining part of a single parameter value. `CHAT_ID` is obtained from inbound context according to the Skill instructions, while timestamps are supplied to the script by its caller. If an attacker can influence one of these values, the attacker may append, duplicate, truncate, or otherwise modify request parameters. The request carries a valid Feishu tenant access token, so the resulting modified request executes with the application's API privileges. The destination hostname and URL scheme are fixed. Consequently, this issue does not directly enable redirecting the bearer token to an arbitrary external server. Its realistic security effect is manipulation of authenticated requests to the Feishu message API. The precise behavior of duplicate query parameters depends on Feishu's server-side parser, so access remains bounded by Feishu's authorization checks and the application's scopes. ### Attack Path 1. An attacker influences the inbound `chat_id` or another script argument used to construct the request. 2. The attacker includes query delimiters or encoded metacharacters, for example a value that appends an addi ...[truncated 1283 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Validate all caller-controlled values before making any authenticated request: - Require `START_TS` and `END_TS` to contain only decimal digits. - Verify that `START_TS` is not greater than `END_TS`. - Impose a maximum permitted reporting interval. - Validate `CHAT_ID` against Feishu's documented identifier format. 2. Do not manually concatenate query strings. Use curl's encoding facilities so every value remains within its assigned parameter: ```bash CURL_ARGS=( --fail-with-body --silent --show-error --get 'https://open.feishu.cn/open-apis/im/v1/messages' -H "Authorization: Bearer $TOKEN" --data-urlencode 'container_id_type=chat' --data-urlencode "container_id=$CHAT_ID" --data-urlencode "start_time=$START_TS" --data-urlencode "end_time=$END_TS" --data-urlencode 'sort_type=ByCreateTimeAsc' --data-urlencode 'page_size=50' ) if [ -n "$PAGE_TOKEN" ]; then CURL_ARGS+=(--data-urlencode "page_token=$PAGE_TOKEN") fi RESP=$(curl "${CURL_ARGS[@]}") ``` 3. Treat pagination tokens as opaque values and always URL-encode them, even though they originate from Feishu. 4. Bind the requested chat ID to a trusted inbound-context field rather than accepting arbitrary user-authored text as the identifier. 5. Where possible, enforce an allowlist of chats that the Skill is permitted to read. 6. Keep the Feishu application's API scopes restricted to the minimum set of message-read capabilities required by the report-generation task. 7. Use `--fail-with-body --silent --show-error` so transport and HTTP failures are detected without silently processing unexpected responses. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (12)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
代码行为与声明存在明显范围不一致。声明描述的是一个完整的“周报生成”技能,包含两种数据采集方式、本地日志读取、数据合并以及按模板输出周报。当前提供的代码片段只是一段 shell 脚本:使用 app_id/app_secret 获取飞书 tenant access token,随后分页拉取指定 chat_id 和时间范围内的消息,并输出标准化消息 JSON。虽然这与声明中的“方式(1) 调用飞书API拉取聊天记录”一致,但缺少声明中其余核心能力,因此若将该代码片段视为该技能的实现,则描述高于实际行为,构成不匹配。未发现额外的可疑越权能力;问题主要是声明的主要功能远超此代码实际实现范围。

Context-Inappropriate Capability

High
Confidence
97% confidence
Finding
The skill instructs the agent to extract Feishu app credentials from a local OpenClaw config file via shell, exposing secrets unrelated to normal report formatting. Pulling credentials from disk materially increases risk of secret disclosure, misuse of the Feishu app, and unauthorized access to broader chat data if those credentials are reused or exfiltrated.

Missing User Warnings

High
Confidence
96% confidence
Finding
The skill reads local credentials and pulls chat history without a clear user-facing privacy disclosure or informed consent step. Because the accessed data includes secrets and private messages, lack of warning materially raises the risk of silent overcollection and unintended exposure of sensitive organizational information.

External Script Fetching

High
Category
Supply Chain
Content
START_TS="${4:?}"
END_TS="${5:?}"

TOKEN=$(curl -s -X POST 'https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal' \
  -H 'Content-Type: application/json' \
  -d "{\"app_id\":\"${APP_ID}\",\"app_secret\":\"${APP_SECRET}\"}" \
  | python3 -c "import sys,json; print(json.load(sys.stdin).get('tenant_access_token',''))")
Confidence
90% confidence
Finding
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

External Script Fetching

High
Category
Supply Chain
Content
URL="https://open.feishu.cn/open-apis/im/v1/messages?container_id_type=chat&container_id=${CHAT_ID}&start_time=${START_TS}&end_time=${END_TS}&sort_type=ByCreateTimeAsc&page_size=50"
  [ -n "$PAGE_TOKEN" ] && URL="${URL}&page_token=${PAGE_TOKEN}"

  RESP=$(curl -s "$URL" -H "Authorization: Bearer $TOKEN")
  CODE=$(echo "$RESP" | python3 -c "import sys,json; print(json.load(sys.stdin).get('code','-1'))" 2>/dev/null || echo "-1")
  [ "$CODE" != "0" ] && { echo "ERROR: API code $CODE" >&2; exit 1; }
Confidence
90% confidence
Finding
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Lp3

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding
The skill invokes shell commands to read local configuration, enumerate files, and run scripts, but it declares no tool scope or permission boundaries. This increases the chance an agent will execute sensitive local actions without explicit review or least-privilege constraints.

Ssd 3

Medium
Confidence
83% confidence
Finding
The skill explicitly tells the agent to collect conversation records and local memory notes, combine them, and produce a report from that material. This is a natural-language data exposure pattern because it operationalizes gathering and re-presenting potentially sensitive user communications and stored notes, even though it does not use explicit exfiltration terminology.

Vague Triggers

Medium
Confidence
95% confidence
Finding
Broad trigger phrases like '工作总结' or '本周总结' can cause the skill to activate on common summarization requests where users may not expect chat-history retrieval or local file access. In this context, overbroad activation is dangerous because the skill performs sensitive data collection rather than a purely in-memory transformation.

Description-Behavior Mismatch

Medium
Confidence
92% confidence
Finding
The skill expands from summarization into persistent writing of daily memory logs, which changes local state and stores potentially sensitive work content for future reuse. That broadens data retention and creates privacy and integrity risks if users did not explicitly authorize ongoing storage of conversation-derived content.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The optional memory-writing behavior modifies local files and persists work summaries, but the documentation does not present a strong warning about filesystem changes and long-term retention. Users may reasonably expect a reporting skill to summarize data, not create durable records that could later be read, leaked, or become stale and misleading.

Ssd 3

Medium
Confidence
89% confidence
Finding
Persisting substantive conversation content into local memory logs creates a secondary store of potentially sensitive data beyond the immediate report-generation task. That increases long-term exposure, makes later unintended reuse more likely, and can capture private or inaccurate content without users realizing it is being archived.

External Transmission

Medium
Category
Data Exfiltration
Content
START_TS="${4:?}"
END_TS="${5:?}"

TOKEN=$(curl -s -X POST 'https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal' \
  -H 'Content-Type: application/json' \
  -d "{\"app_id\":\"${APP_ID}\",\"app_secret\":\"${APP_SECRET}\"}" \
  | python3 -c "import sys,json; print(json.load(sys.stdin).get('tenant_access_token',''))")
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Static analysis

No suspicious patterns detected.