T01 · Skill Instruction Hijacking
- Location
prompts/digest-intro.md:58- Finding
Mandatory Promotional Content Injected into Generated Digests
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This skill mostly matches its stated digest sidecar purpose, but it handles reusable Feishu credentials with under-scoped network and local-file safeguards.
Review before installing. Use only trusted Feishu accounts, avoid direct_credentials unless necessary, do not configure custom Feishu domains, and check permissions on ~/.follow-builders-sidecar if you proceed. The publisher should restrict Feishu domains to feishu/lark, store credentials with 0600-style protections, and replace predictable /tmp files with private per-run temporary directories.
prompts/digest-intro.md:58Mandatory Promotional Content Injected into Generated Digests
scripts/feishu-card-api.js:20Arbitrary Feishu API Base URL Can Receive Application Secrets and Bearer Tokens
scripts/sidecar-credentials.js:37Feishu Application Secret Is Stored Without Explicit Restrictive Permissions
scripts/run-sidecar.js:43Predictable Shared Temporary Files Permit Symlink Attacks and Payload Tampering
The README explicitly describes writing plaintext appId, appSecret, and chatId into a local file under the user's home directory. If local filesystem access is obtained by another user, process, backup system, or malware, these credentials can be harvested and used to access or abuse the Feishu integration.
Feishu card delivery supports two modes:
- `openclaw_account`: reuse an OpenClaw-configured Feishu account plus a target chat id
- `direct_credentials`: write a local-only Feishu `appId` / `appSecret` / `chatId` into `~/.follow-builders-sidecar/credentials.json`
If the chosen Feishu app cannot upload images, avatar upload falls back to the
configured default OpenClaw Feishu account.
The declared description is about operational control of scheduling and digest delivery for another skill, including takeover/rollback behavior. The supplied code does none of that. Instead, it is an image utility that processes avatar files using Pillow. This is a materially different primary purpose and introduces undeclared file/image-processing capabilities unrelated to the stated sidecar functionality.
The declared description is about scheduling/delivery takeover and rollback behavior for a sidecar around the follow-builders skill. The supplied code does not implement scheduling, cron takeover, digest configuration, status inspection, or rollback. Instead, it is a standalone integration module for Feishu/Lark messaging that authenticates to Feishu, retrieves avatar images from external URLs, uploads images, and sends interactive cards. Those are materially different capabilities and resources from the declared purpose, so this is a clear description-behavior mismatch.
The declared purpose is about operational control of scheduling and delivery takeover for a follow-builders skill, including configuration, status inspection, and rollback behavior. The supplied code does not implement scheduling, cron takeover, digest configuration, status inspection, or rollback logic. Instead, it provides helper functions for a Feishu card/local messaging workflow: parsing CLI args such as recipient/account info, reading JSON from file/stdin, generating temporary files, calling a Python image-cropping script for avatars, and writing card JSON. These are materially different capabilities and indicate a different primary purpose than the declared description.
The declared description is about a sidecar that manages scheduling and delivery takeover behavior for another skill, including status inspection and rollback to original cron. The supplied code does not implement scheduling, delivery orchestration, takeover state inspection, or rollback. Instead, it only reads configuration and source data from disk and loads prompt files, optionally fetching prompt text remotely. Those behaviors are not aligned with the stated primary purpose. While config loading could be a supporting detail, the chunk’s main functionality is generic resource loading, and the remote prompt fetch is an undeclared capability not suggested by the description.
The declared description is about orchestration and operational control of a sidecar skill: taking over scheduling and delivery, configuring digest delivery, checking takeover status, and rolling back cron behavior. The supplied code does not implement any of those control-plane functions. Instead, it implements content/network utility functions for retrieving and parsing remote data from podcast RSS endpoints and Twitter/X oEmbed APIs. These are materially different capabilities and resources than the description suggests, so this chunk does not accurately represent the declared purpose.
The declared description focuses on scheduling/delivery takeover management for an upstream skill: configuring delivery, inspecting takeover status, and rolling back cron behavior. The supplied code does not implement takeover management, scheduling control, status inspection, rollback, or cron-related behavior. Instead, it prepares content for digest generation by reading config, downloading feed data and prompt files, enriching content, and printing a JSON payload. This is a materially different primary purpose and includes undeclared network/content aggregation capabilities, so the description does not accurately represent the code.
The declared description centers on operational sidecar behavior for scheduling and delivery management of another skill. The supplied code chunk does not implement any of those functions. Instead, it is a pure rendering utility that parses a JSON file and converts digest content into formatted plaintext. It has no cron interaction, no status inspection, no delivery/channel configuration, and no takeover/rollback mechanisms. This is a materially different primary purpose, so the description does not accurately represent the code.
The declared description is about a sidecar that manages operational takeover of scheduling and delivery for another skill: taking over cron/scheduling, configuring delivery, checking takeover status, and rolling back. The supplied code does not implement those control-plane behaviors. Instead, it is a content-processing and delivery pipeline for generating a daily AI builders digest as a Feishu card. Its primary function is to assemble source data, filter relevant items, prompt an LLM to create structured card content, normalize/repair the result, persist a payload file, and optionally send the card. While 'delivery' is partially involved via optional Feishu sending, the scheduling/takeover/status/rollback aspects central to the declared purpose are absent. Therefore the code materially differs from the declared purpose and includes undeclared content-generation and source-processing capabilities.
The declared description is about an OpenClaw sidecar that manages takeover of scheduling and delivery for another skill, including status inspection and rollback to the original cron. The supplied code chunk does not implement scheduling control, cron takeover, rollback, or status inspection. Instead, it is a delivery utility focused specifically on composing and sending Feishu cards from supplied content. While 'delivery' is mentioned in the description, this code's concrete primary purpose is message construction and transmission via Feishu APIs, including credential resolution, avatar fetching/uploading, and recipient targeting—capabilities not reflected in the declared description. This is therefore a material description-behavior mismatch.
The skill reads an existing local config, can reuse configured delivery accounts, and optionally writes direct Feishu app credentials to a local credentials.json file. Handling reusable messaging credentials materially raises the risk of account compromise, unauthorized message sending, or credential leakage if storage permissions, redaction, and lifecycle controls are weak.
- reads `~/.follow-builders/config.json` once during takeover
- writes `~/.follow-builders-sidecar/config.json`
- writes `~/.follow-builders-sidecar/state.json`
- optionally writes `~/.follow-builders-sidecar/credentials.json` for local-only direct Feishu app credentials
- can reuse OpenClaw-configured Feishu account settings when Feishu card delivery is enabled
## When to use this skill
Referenced artifact was not completely inspected
node scripts/sidecar-setup.js
Referenced artifact was not completely inspected
node scripts/sidecar-configure.js ...
Referenced artifact was not completely inspected
node scripts/sidecar-status.js
Referenced artifact was not completely inspected
node scripts/sidecar-rollback.js --reenable-original
Referenced artifact was not completely inspected
node scripts/run-sidecar.js --skip-delivery
Referenced artifact was not completely inspected
1. Before changing sidecar compatibility logic, inspect the upstream `SKILL.md`.
Referenced artifact was not completely inspected
1. Before changing sidecar compatibility logic, inspect the upstream `SKILL.md`.
Referenced artifact was not completely inspected
1. Before changing sidecar compatibility logic, inspect the upstream `SKILL.md`.
The documentation confirms that direct Feishu credentials remain in ~/.follow-builders-sidecar/credentials.json, which implies persistent local secret storage. Even if intended to stay local, plaintext or weakly protected credential files are attractive targets for other local processes, backups, or accidental disclosure.
- The sidecar does not modify the upstream `follow-builders` repo.
- The sidecar does not send local files to arbitrary third-party endpoints.
- OpenClaw and Feishu routing are used only to deliver the digest the user asked for.
- Direct Feishu app credentials, when configured, stay in `~/.follow-builders-sidecar/credentials.json` and are not intended for repository storage.
- The sidecar's own local state lives under `~/.follow-builders-sidecar/`.
## Trust statement
Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.
}
}
return prompts;
}
export {
Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.
}
}
return prompts;
}
export {
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
const REPO_DIR = join(SCRIPT_DIR, '..');
const SIDECAR_HOME = join(homedir(), '.follow-builders-sidecar');
const SIDECAR_CONFIG_PATH = join(SIDECAR_HOME, 'config.json');
const SIDECAR_CREDENTIALS_PATH = join(SIDECAR_HOME, 'credentials.json');
const SIDECAR_STATE_PATH = join(SIDECAR_HOME, 'state.json');
const ORIGINAL_CONFIG_PATH = join(homedir(), '.follow-builders', 'config.json');
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
const REPO_DIR = join(SCRIPT_DIR, '..');
const SIDECAR_HOME = join(homedir(), '.follow-builders-sidecar');
const SIDECAR_CONFIG_PATH = join(SIDECAR_HOME, 'config.json');
const SIDECAR_CREDENTIALS_PATH = join(SIDECAR_HOME, 'credentials.json');
const SIDECAR_STATE_PATH = join(SIDECAR_HOME, 'state.json');
const ORIGINAL_CONFIG_PATH = join(homedir(), '.follow-builders', 'config.json');
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
const REPO_DIR = join(SCRIPT_DIR, '..');
const SIDECAR_HOME = join(homedir(), '.follow-builders-sidecar');
const SIDECAR_CONFIG_PATH = join(SIDECAR_HOME, 'config.json');
const SIDECAR_CREDENTIALS_PATH = join(SIDECAR_HOME, 'credentials.json');
const SIDECAR_STATE_PATH = join(SIDECAR_HOME, 'state.json');
const ORIGINAL_CONFIG_PATH = join(homedir(), '.follow-builders', 'config.json');
No suspicious patterns detected.