T09 · Insecure Skill Coding Practices
Warning
- Location
- SKILL.md:24
- Finding
- Plaintext Persistence of Reusable DingTalk Credentials and Access Tokens## Vulnerability Details **File Location**: `SKILL.md`, lines 24–28, 35–38, 53–60, and 73–75 **Vulnerability Type**: Plaintext sensitive-data storage **Risk Level**: Medium ### Vulnerable Code ```markdown 2. **读取配置** → 用一条 `grep -E '^KEY1=|^KEY2='` 命令一次性读取该通道所需的全部键值,不要分多次查询。 3. **仅收集该通道所需的缺失配置** → 一次性询问,不要逐条问 4. **持久化** → 写入 config,后续无需再问 ``` ```markdown | Webhook | `DINGTALK_WEBHOOK_URL` | 群设置 → 智能群助手 → 添加自定义机器人 | | Webhook(加签) | 额外 `DINGTALK_WEBHOOK_SECRET` | 创建机器人时选择"加签"模式获得 | | 机器人消息 | `DINGTALK_APP_KEY` + `DINGTALK_APP_SECRET` | 开放平台 → 应用管理 → 凭证信息 | ``` ```bash CONFIG=~/.dingtalk-skills/config # 一次性读取所有所需配置 APP_KEY=$(grep '^DINGTALK_APP_KEY=' "$CONFIG" | cut -d= -f2-) APP_SECRET=$(grep '^DINGTALK_APP_SECRET=' "$CONFIG" | cut -d= -f2-) # Token 缓存:有效期内复用,避免重复请求 CACHED_TOKEN=$(grep '^DINGTALK_ACCESS_TOKEN=' "$CONFIG" 2>/dev/null | cut -d= -f2-) TOKEN_EXPIRY=$(grep '^DINGTALK_TOKEN_EXPIRY=' "$CONFIG" 2>/dev/null | cut -d= -f2-) ``` ```bash sed -i '/^DINGTALK_ACCESS_TOKEN=/d;/^DINGTALK_TOKEN_EXPIRY=/d' "$CONFIG" echo "DINGTALK_ACCESS_TOKEN=$TOKEN" >> "$CONFIG" echo "DINGTALK_TOKEN_EXPIRY=$EXPIRY" >> "$CONFIG" ``` ### Technical Analysis The skill instructs the agent to retain DingTalk application secrets, signing secrets, credential-bearing webhook URLs, and access tokens in `~/.dingtalk-skills/config`. These values constitute reusable authentication material: - `DINGTALK_APP_SECRET` can be used with the application key to obtain access tokens. - `DINGTALK_WEBHOOK_SECRET` permits generation of valid webhook signatures. - `DINGTALK_WEBHOOK_URL` embeds a webhook access token. - `DINGTALK_ACCESS_TOKEN` directly authorizes DingTalk API requests until expiration. The documented workflow does not require restrictive directory or file permissions, ownership validation, a secure credential store, or protection from symbolic-link attacks when editing the configuration file. It also persists short-lived access tokens even though they can be obtained when needed ...[truncated 1688 chars]
- Remediation
- ## Remediation Suggestions 1. Store long-lived credentials in an operating-system keychain, managed secret store, or injected environment variables rather than a shared plaintext configuration file. 2. Do not persist access tokens unless operationally necessary. Obtain them when required and retain them only in process memory. 3. If file-based storage is unavoidable: - Create `~/.dingtalk-skills` with mode `0700`. - Create the configuration file with mode `0600`. - Set `umask 077` before creating temporary or configuration files. - Verify that the file is owned by the current user and is not a symbolic link before reading or modifying it. - Reject files with group or world permissions. 4. Separate non-sensitive configuration from secrets and avoid storing webhook URLs in logs, command histories, or backups. 5. Update credentials atomically through a securely created temporary file rather than direct append operations. 6. Document credential rotation and revocation procedures for application secrets, webhook tokens, and signing secrets. 7. Continue redacting credentials in output, but treat this only as an additional safeguard rather than a replacement for secure storage.
