T09 · Insecure Skill Coding Practices
Warning
- Location
- SKILL.md:19
- Finding
- Database credentials stored in a plaintext file without enforced access controls<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 19–22; related credential-storage guidance at lines 64–68 **Vulnerability Type**: Plaintext storage of sensitive credentials and unsafe file permissions **Risk Level**: Medium ### Vulnerable Code ```bash curl -s -X POST https://zero.tidbapi.com/v1alpha1/instances \ -H "Content-Type: application/json" \ -d '{"tag":"sql-smoke-test"}' \ | tee tidb-zero.json ``` Related guidance: ```text Agent note: After provisioning succeeds, save the instance details to a local file (for example, tidb-cloud-zero.json) and remind the user to store the file securely because it contains sensitive credentials. ``` ### Technical Analysis The API response contains the database username, password, host, and complete connection URI. Piping the response through `tee tidb-zero.json` stores all of these credentials in plaintext. The file's permissions depend on the process's current `umask`. The example does not enforce owner-only access, verify the destination, prevent symbolic-link attacks, exclude the file from version control, or remove it when the database is no longer needed. A general reminder to store the file securely does not technically enforce these protections. The database is ephemeral, which limits the exposure period, but the credentials remain usable until the instance expires. Copies may also persist in source-control history, backups, CI artifacts, or logs after expiration. ### Attack Path 1. A user or agent follows the documented smoke-test instructions. 2. The provisioning endpoint returns active database credentials. 3. `tee` writes the complete response to `tidb-zero.json` under ambient filesystem permissions. 4. Another local account, process, CI artifact collector, backup process, or repository user obtains the file. 5. The attacker extracts `instance.connectionString` or the individual username and password. 6. The attacker connects to the database before expiration and accesses ...[truncated 551 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Avoid writing the provisioning response to disk unless persistence is necessary. - If a file is required, enforce restrictive permissions before creation: ```bash umask 077 response_file="$(mktemp "${TMPDIR:-/tmp}/tidb-zero.XXXXXX.json")" chmod 600 "$response_file" curl --fail-with-body --silent --show-error \ -X POST https://zero.tidbapi.com/v1alpha1/instances \ -H "Content-Type: application/json" \ -d '{"tag":"sql-smoke-test"}' > "$response_file" ``` - Register cleanup with `trap` and remove the file as soon as it is no longer required: ```bash trap 'rm -f -- "$response_file"' EXIT ``` - Do not use a predictable filename in a shared temporary directory. - Add credential-response filenames to `.gitignore` and prevent their collection as CI artifacts. - Avoid backups and logging of the response file. - Prefer extracting required values in memory or passing them through a protected secret-management mechanism. - Clearly document that the response is a secret and should be deleted when the instance expires. ]]>
