T09 · Insecure Skill Coding Practices
Warning
- Location
- WORKFLOW.md:22
- Finding
- Insufficiently protected local credential materialization and persistent secret-manager access<![CDATA[ ## Vulnerability Details **File Location**: `WORKFLOW.md:22-26`; supporting guidance in `FAQ.md:23-26` **Vulnerability Type**: Plaintext credential storage and excessive credential exposure to a persistent service **Risk Level**: Medium ### Vulnerable Documentation ```text 7. fetch the tunnel runtime token and write a local env file 获取 tunnel 运行 token 并写入本地 env 文件 8. start `cloudflared` in Docker 用 Docker 启动 `cloudflared` 9. enable `systemd` if reboot persistence is required 如果要求跨重启持久化,启用 `systemd` ``` The related FAQ states: ```text ## Why must `systemd` use the same `op` binary as the shell? | 为什么 `systemd` 必须使用和 shell 相同的 `op`? Because the working shell command may actually be a wrapper that injects a service-account token before calling the real CLI. 因为 shell 里能工作的命令,实际可能是一个包装器:它先注入 service-account token,再调用真正的 CLI。 ``` ### Technical Analysis The workflow requires a Cloudflare tunnel runtime credential to be written to a local environment file, but it does not define: - A secure file location - Restrictive ownership and permissions - A protected creation procedure such as `umask 077` - Rotation or deletion requirements - Backup and log exclusions - Protection against accidental source-control inclusion - Whether the credential is exposed to other containers or processes The FAQ also contemplates a persistent `systemd` service invoking an `op` wrapper that injects a 1Password service-account token. The documentation does not require that this service-account token be read-only, restricted to one vault item, or removed from the runtime service after initial provisioning. Using a Cloudflare tunnel token is necessary for the declared functionality. Retrieving it from Cloudflare is not, by itself, evidence of exfiltration. The security issue is the unspecified local handling and the possibility of granting a long-lived service access to a more powerful secret-manager credential than it needs. ### Attack Path 1. An authorized operat ...[truncated 1663 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Create the runtime credential file in a dedicated, root-owned directory using `umask 077` and explicit mode `0600`. 2. Restrict ownership to the exact account running `cloudflared`. 3. Do not place credentials directly in shell command arguments, Docker Compose files, systemd unit text, logs, or command transcripts. 4. Prefer Docker secrets, systemd credentials, or an equivalent protected runtime secret mechanism instead of a general-purpose environment file. 5. Ensure only the `cloudflared` process receives the tunnel runtime token. Do not expose it to unrelated containers. 6. Use a dedicated 1Password service account with read-only access to the single required item. 7. Separate provisioning from runtime operation. The persistent tunnel service should receive only its tunnel token and should not routinely access 1Password. 8. Add systemd hardening such as `NoNewPrivileges=yes`, a dedicated service account, filesystem restrictions, and an explicit minimal environment. 9. Document token rotation, revocation, secure deletion, backup exclusions, and source-control exclusions. 10. Require operators to verify file permissions and service credential scope before enabling persistence. ]]>
