Back to skill

Security audit

WorkBuddy Check-in

Security checks for vulnerabilities and agentic risk

Overview

The skill is coherent and disclosed, but it handles a full WorkBuddy login token through stdout and command-line headers, which creates meaningful local exposure risk.

Review carefully before installing. Only use this if you trust the publisher with access to your current WorkBuddy account session, avoid running decrypt-token.js directly, avoid capturing script output in shared logs, and prefer manually supplied trusted Node/Electron runtimes over automatic Electron installation.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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 (2)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/decrypt-token.js:162
Finding
WorkBuddy bearer token exposed through standard output and process arguments<![CDATA[ ## Vulnerability Details **File Location**: `scripts/decrypt-token.js:162-169`, `scripts/checkin.sh:115-129`, and `scripts/checkin.sh:154-157` **Vulnerability Type**: Sensitive credential exposure **Risk Level**: Medium ### Vulnerable Code `scripts/decrypt-token.js:162-169`: ```javascript if (token && typeof token === "string") { process.stderr.write( "[安全提示] 已从本地登录态读取 accessToken(新版明文存储),仅用于 WorkBuddy 官方签到接口;" + "请勿将其写入日志、分享或提交。\n" ); emitAndExit(0, "DECRYPT_RESULT:" + token); return; } ``` The legacy decryption branch uses the same output mechanism at `scripts/decrypt-token.js:225-232`: ```javascript if (token) { process.stderr.write( "[安全提示] 已从本地会话解密 accessToken(旧版 state.vscdb),仅用于 WorkBuddy 官方签到接口;" + "请勿将其写入日志、分享或提交。\n" ); emitAndExit(0, "DECRYPT_RESULT:" + token); return; } ``` `scripts/checkin.sh:115-129`: ```bash TOKEN="$(read_token)" if [ -z "$TOKEN" ]; then log "❌ 未找到 Node 或 Electron 运行时,或运行时未能产出令牌。请安装 Node.js,或设置 WB_CHECKIN_NODE / WB_CHECKIN_ELECTRON 指向可用运行时。" exit 1 fi if [[ "$TOKEN" == ERR* ]]; then log "❌ 获取令牌失败(${TOKEN})。请确认已安装并登录 WorkBuddy 桌面端。" exit 1 fi API="https://copilot.tencent.com" STATUS=$(curl -s -m 15 -X POST "$API/billing/meter/checkin-status" \ -H "Content-Type: application/json" -H "Accept: application/json" \ -H "Authorization: Bearer $TOKEN" -d '{}' 2>/dev/null || echo "") ``` `scripts/checkin.sh:154-157`: ```bash RESULT=$(curl -s -m 15 -X POST "$API/billing/meter/daily-checkin" \ -H "Content-Type: application/json" -H "Accept: application/json" \ -H "Authorization: Bearer $TOKEN" -d '{}' 2>/dev/null || echo "") ``` ### Technical Analysis The token reader deliberately writes the complete WorkBuddy access token to standard output using the `DECRYPT_RESULT:<token>` format. Although the normal shell wrapper captures that output, directly invoking `decrypt-token.js`, redirecting its output, running it under a verbose automation framework, or attaching output-capt ...[truncated 1943 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Combine token retrieval and HTTPS submission in one process so the credential is never emitted through stdout. 2. Replace the shell-to-Node plaintext token protocol with a narrow operation such as `performCheckin()`, returning only sanitized status data. 3. If curl must remain external, provide the sensitive header through a protected mechanism that avoids the visible argument vector. For example, use a descriptor-backed curl configuration with permissions restricted to the current user and remove it immediately after use. 4. Ensure any temporary credential-bearing resource is created atomically with mode `0600`, is excluded from logs and backups, and is deleted on all exit paths through a trap. 5. Clear the shell variable immediately after the last authenticated request: ```bash unset TOKEN ``` 6. Document that direct execution of the token reader exposes a credential, even after the internal interface has been hardened. 7. Add automated tests that reject plaintext tokens in stdout, stderr, logs, and normal process arguments. ]]>

T08 · Insecure Dependencies

Note
Location
scripts/setup.sh:116
Finding
Optional Electron installation uses a non-exact dependency version<![CDATA[ ## Vulnerability Details **File Location**: `scripts/setup.sh:116-122` **Vulnerability Type**: Unpinned third-party runtime installation **Risk Level**: Low ### Vulnerable Code ```bash echo "⚠️ 未检测到 Electron 运行时,尝试通过 npm 下载(约 100MB,需要 node/npm)..." echo " ⚠️ 供应链提示:将从官方 npm registry 下载 electron@37 并执行,请确认网络可信。" command -v npm >/dev/null 2>&1 || { echo "❌ 未找到 npm,请先安装 Node.js,或手动放置 Electron 后重试"; exit 1; } mkdir -p "$RUNTIME_DIR" cd "$RUNTIME_DIR" npm init -y >/dev/null 2>&1 npm install electron@37 >/dev/null 2>&1 || { echo "❌ Electron 下载失败(网络/代理问题),请手动安装"; exit 1; } ``` ### Technical Analysis The setup script optionally installs `electron@37`, which specifies a major release line rather than one exact, reviewed artifact. The effective package and transitive dependency set may therefore change between installations without changes to this repository. An npm installation also invokes package installation behavior and downloads Electron runtime content. The effective source depends on the user's npm registry, proxy, and Electron mirror configuration. The project documentation explicitly suggests alternate registry and binary mirrors, which can further change the trusted distribution path. Automatic installation is disabled by default and requires explicit user opt-in through `WB_CHECKIN_AUTO_INSTALL_ELECTRON=1`. This substantially reduces exposure and is why the finding is rated Low. No evidence was found that the legitimate Electron package currently used by the script is malicious. ### Attack Path 1. A legacy WorkBuddy user lacks a usable Electron runtime. 2. The user explicitly enables automatic installation and runs `setup.sh`. 3. npm resolves the current package matching the `37` major release from the configured registry, while Electron obtains its runtime through the applicable download configuration. 4. If the registry, mirror, package account, newly allowed package release, or dependency distribution channel has been compromised, attac ...[truncated 861 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin Electron to one exact reviewed version rather than the entire major release line: ```bash npm install --save-exact electron@37.x.y ``` 2. Retain and review a lockfile, then install reproducibly with `npm ci` instead of generating and deleting dependency metadata on every installation. 3. Verify the expected package and runtime integrity against a trusted, project-maintained checksum or signature before execution. 4. Enforce an approved HTTPS registry for this operation rather than silently inheriting an arbitrary user registry or mirror. 5. Clearly display the resolved package version and download origin before installation. 6. Continue requiring explicit opt-in; do not enable automatic dependency download by default. 7. Prefer a manually supplied, authenticated, and version-checked Electron binary for the legacy compatibility path. 8. Where compatible with Electron's distribution mechanism, disable unnecessary npm lifecycle scripts and minimize the installed dependency graph. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (16)

YARA rule 'backdoor_persistence': Backdoor persistence with malicious payloads (shell commands, SSH key injection, hidden root users) [malware]

High
Category
YARA Match
Content
ts/decrypt-token.js`:基于 Electron `safeStorage` 解密本地 `state.vscdb` 会话,`node:sqlite` 不可用时自动回退 `python3`
- 一键安装脚本 `scripts/setup.sh` / `scripts/setup.ps1`:自动检测或通过 npm 下载 Electron 运行时,并验证解密链路
- 多 Agent 框架适配(WorkBuddy 自动化任务 / Claude Code / Codex / OpenClaw / 纯终端),定时方式覆盖 crontab / launchd / schtasks / WorkBuddy recurring
- 幂等保护:每次运行先查 `checkin-status`,今日已签到立即跳过,支持一天多时间点补签(默认推荐 09/12/15/18/21 点)
- 随机错峰:`WB_CHECKIN_JITTER=<秒>` 环境变量让脚本启动前随机等待,避免整点风暴
- 兼容旧版应用名 CodeBuddy:`WB_CHECKIN_APP_NAME=CodeBuddy` 覆盖钥匙串绑定名

### 设计要点

- **全本机运行**:不含任何后端服务,令牌仅发往腾讯官方接口 `copilot.tencent.com`,不上传第三方
- **令牌不落盘**:仅在内存中传递;`
Confidence
75% confidence
Finding
YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

YARA rule 'backdoor_persistence': Backdoor persistence with malicious payloads (shell commands, SSH key injection, hidden root users) [malware]

High
Category
YARA Match
Content
(macOS 命中钥匙串、Windows/Linux 走系统 DPAPI/keyring)。推荐手动指定已校验的 Electron(设 `WB_CHECKIN_ELECTRON`),不依赖自动下载。
- **python3 回退(默认关闭)**:仅当旧版分支的 `node:sqlite` 不可用时,设 `WB_CHECKIN_ALLOW_PY_FALLBACK=1` 才会调用外部 `python3` 读取会话库。默认关闭以缩小信任边界。
- **定时任务(crontab / launchd / 任务计划程序)**:用于多时间点幂等补签,脚本本身不写入系统定时,需你显式配置。

### 供应链提示

安装 Electron 默认**不自动下载**(避免静默引入第三方大二进制)。如需自动安装,须显式设置环境变量 `WB_CHECKIN_AUTO_INSTALL_ELECTRON=1` 确认从官方 npm registry 下载 `electron@37`。

## 所需权限

本 skill 运行需以下本地权限,均限定在最小范围:

| 权限 | 范围 | 说明 |
|------|------|------|
| 本地代码执行 | 仅本 skill 的 `checkin.sh/.ps1`、`decrypt-token
Confidence
75% confidence
Finding
YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill clearly describes capabilities to execute shell/PowerShell scripts, read environment variables, access local credential files, and make network requests, but the front matter does not declare an explicit tool scope such as permissions or allowed-tools. This creates a security transparency gap: a user or host platform cannot easily enforce least privilege or compare the declared permissions against the actual behavior, which is especially important here because the skill handles high-value access tokens.

Session Persistence

Medium
Category
Rogue Agent
Content
### macOS launchd(长期后台)

创建 `~/Library/LaunchAgents/com.user.workbuddy-checkin.plist`,`StartCalendarInterval` 用数组配置多时间点:
```xml
<key>StartCalendarInterval</key>
<array>
Confidence
75% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Session Persistence

Medium
Category
Rogue Agent
Content
### macOS launchd(长期后台)

创建 `~/Library/LaunchAgents/com.user.workbuddy-checkin.plist`,`StartCalendarInterval` 用数组配置多时间点:
```xml
<key>StartCalendarInterval</key>
<array>
Confidence
75% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Session Persistence

Medium
Category
Rogue Agent
Content
<dict><key>Hour</key><integer>21</integer><key>Minute</key><integer>0</integer></dict>
</array>
```
然后 `launchctl load ~/Library/LaunchAgents/com.user.workbuddy-checkin.plist`。

### 在 WorkBuddy 内(Agent 自动化)
Confidence
75% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The document explicitly states that the skill reads local login tokens and, for newer versions, consumes a plaintext authentication file, but it does not provide strong warnings about the sensitivity of those credentials or precautions to avoid exposing them in logs, troubleshooting output, or downstream scripts. In a skill whose core function depends on harvesting local auth state, missing handling guidance materially increases the chance of credential leakage or misuse, especially because the same workflow also writes logs.

Session Persistence

Medium
Category
Rogue Agent
Content
#   WB_CHECKIN_NODE=<path> ./checkin.sh
#   WB_CHECKIN_ELECTRON=<path> ./checkin.sh
# 定时(示例,每天 09:00):
#   crontab -e
#   0 9 * * * /path/to/checkin.sh >> /path/to/logs/checkin.log 2>&1
#
# 运行时策略:
Confidence
85% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Session Persistence

Medium
Category
Rogue Agent
Content
#   WB_CHECKIN_NODE=<path> ./checkin.sh
#   WB_CHECKIN_ELECTRON=<path> ./checkin.sh
# 定时(示例,每天 09:00):
#   crontab -e
#   0 9 * * * /path/to/checkin.sh >> /path/to/logs/checkin.log 2>&1
#
# 运行时策略:
Confidence
85% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Session Persistence

Medium
Category
Rogue Agent
Content
#   WB_CHECKIN_NODE=<path> ./checkin.sh
#   WB_CHECKIN_ELECTRON=<path> ./checkin.sh
# 定时(示例,每天 09:00):
#   crontab -e
#   0 9 * * * /path/to/checkin.sh >> /path/to/logs/checkin.log 2>&1
#
# 运行时策略:
Confidence
85% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Session Persistence

Medium
Category
Rogue Agent
Content
#   WB_CHECKIN_NODE=<path> ./checkin.sh
#   WB_CHECKIN_ELECTRON=<path> ./checkin.sh
# 定时(示例,每天 09:00):
#   crontab -e
#   0 9 * * * /path/to/checkin.sh >> /path/to/logs/checkin.log 2>&1
#
# 运行时策略:
Confidence
85% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

External Transmission

Medium
Category
Data Exfiltration
Content
API="https://copilot.tencent.com"

# ---------- 2. 查询签到状态 ----------
STATUS=$(curl -s -m 15 -X POST "$API/billing/meter/checkin-status" \
  -H "Content-Type: application/json" -H "Accept: application/json" \
  -H "Authorization: Bearer $TOKEN" -d '{}' 2>/dev/null || echo "")
Confidence
90% confidence
Finding
The script transmits a decrypted local access token in an Authorization header to a remote service. Even though the destination appears to be the official WorkBuddy/Tencent endpoint and the stated purpose is签到, this is still a credential exfiltration path from local protected storage to the network, and the token is described by the script itself as equivalent to the account password.

External Transmission

Medium
Category
Data Exfiltration
Content
fi

# ---------- 3. 执行签到 ----------
RESULT=$(curl -s -m 15 -X POST "$API/billing/meter/daily-checkin" \
  -H "Content-Type: application/json" -H "Accept: application/json" \
  -H "Authorization: Bearer $TOKEN" -d '{}' 2>/dev/null || echo "")
Confidence
90% confidence
Finding
This second request uses the same decrypted bearer token to perform an authenticated remote action. In context, the skill automates use of locally harvested credentials against an external API, so compromise of the script, endpoint handling, or user misunderstanding could expose full account access or enable unauthorized account actions.

Context-Inappropriate Capability

Medium
Confidence
85% confidence
Finding
The manifest describes a skill that decrypts a local login token and calls the official check-in API. In addition to local file/database access, this code can spawn an external process via `execFileSync("python3", ...)`, which is a broader capability and not obviously required by the declared purpose, even if gated by an environment variable.

Natural-Language Policy Violations

Low
Confidence
96% confidence
Finding
The file is entirely written in Chinese, including headings, operational notes, and compliance guidance, with no indication that users may choose another language or that the skill is intentionally limited to a Chinese-speaking audience. Under the stated policy, forcing a specific language without user opt-in is a natural-language policy concern.

Natural-Language Policy Violations

Low
Confidence
97% confidence
Finding
The file’s header comments, safety warnings, and operational instructions are written entirely in Chinese, and later runtime messages are also emitted only in Chinese. This creates a language-policy concern because the skill imposes a specific language on users without documenting a choice, opt-in, or region-specific justification.

Static analysis

No suspicious patterns detected.