T09 · Insecure Skill Coding Practices
Error
- Location
- SKILL.md:55
- Finding
- Long-Lived Bearer Token Stored in a Predictable Plaintext File## Vulnerability Details **File Location**: `SKILL.md`, lines 55–59 and 89 **Vulnerability Type**: Plaintext storage of sensitive authentication credentials **Risk Level**: High ### Vulnerable Code Snippet ```markdown **目标**:准确识别"谁在指挥"——授权绑定平台真实用户(含 tenant_id),全程不接触密码;一次授权 30 天有效,到期自动重认证。 **凭证存储约定(跨对话复用)**: - 本 skill 的 token 持久化到 Agent 本机文件 **`~/.gts-operator.json`**(JSON:`{"token": "<jwt>", "saved_at": <unix>, "tenant_id": <int>, "user": {...}}`)。 - 每次会话开始/首次操作前先**检测是否已认证**(见 SOP-O0),避免重复授权。 ``` The token-writing instruction later appears as follows: ```markdown - `data.status == "authorized"` → 成功!`data.token` = **30 天 token**。`data` 仅含 `token`/`tenant_id`/`user_id`(无 name/tenant_slug——别从这里取);把 token 写入 `~/.gts-operator.json`(user/tenant_id 等信息可随后经 `/oauth/me` 一次补齐再存,见 SOP-O0 的响应形状),继续操作。 ``` ### Technical Analysis The Skill instructs the Agent to persist a bearer token with a 30-day lifetime directly in the predictable file `~/.gts-operator.json`. The documented procedure does not require: - Restrictive file permissions such as mode `0600` - Verification that the file is owned by the current user - Protection against symbolic-link attacks - Atomic, no-follow file creation - Encryption through an operating-system credential store - Minimization of sensitive metadata stored beside the token - Rotation or renewal with a shorter-lived access token A bearer token grants access based solely on possession. A local process or user that can read this file can copy the token and submit authenticated requests without knowing the account password or repeating the OAuth authorization flow. The predictable path also creates a possible symlink risk if an attacker can prepare or replace the target before the Agent writes it. Depending on the Agent's filesystem privileges and write implementation, this could expose the token through an attacker-controlled target or overwrite another user-accessible file. ### Attack Path 1. A victim authorizes the `gts-operator` S ...[truncated 1843 chars]
- Remediation
- ## Remediation Suggestions 1. **Use an operating-system credential manager** - Store the token in facilities such as macOS Keychain, Windows Credential Manager, or Linux Secret Service. - Keep only a non-sensitive credential reference in the JSON state file. 2. **Harden fallback file storage** - Create a dedicated configuration directory with mode `0700`. - Create the credential file atomically with mode `0600`. - Reject existing symbolic links and use no-follow file-opening semantics where supported. - Verify that the directory and file are owned by the current user. - Refuse to use credentials if permissions are broader than intended. 3. **Reduce credential exposure** - Prefer short-lived access tokens backed by a securely stored, revocable refresh mechanism. - Avoid storing unnecessary user and tenant metadata with the token. - Rotate tokens after suspicious activity and authorization changes. 4. **Improve revocation** - Provide a user-accessible server-side session management interface that can revoke active OAuth grants without requiring the original `device_code`. - Revoke tokens immediately on logout, user disablement, role changes, or suspected compromise. 5. **Prevent accidental disclosure** - Exclude credential files from backups, diagnostics, telemetry, logs, and support bundles. - Never print bearer tokens in errors or audit output. - Document secure deletion behavior when authorization expires or is revoked. 6. **Validate credentials on every session** - Continue validating the token through `/oauth/me`. - Delete invalid local credentials securely and require fresh authorization after rejection.
