T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/register.sh:14
- Finding
- Credential File Is Created Without Enforced Restrictive Permissions and Secrets Are Printed to Standard Output## Vulnerability Details **File Location**: `scripts/register.sh`, lines 14-26 **Vulnerability Type**: Insecure credential storage and disclosure **Risk Level**: High ### Vulnerable Code ```bash if [ -f "$CRED_FILE" ]; then echo "Already registered. Credentials at $CRED_FILE" cat "$CRED_FILE" exit 0 fi mkdir -p "$CRED_DIR" RESPONSE=$(curl -sf -X POST "$SERVER/api/v1/agents/register" \ -H "Content-Type: application/json" \ -d "$(jq -n --arg n "$NAME" '{name: $n}')") echo "$RESPONSE" | jq . | tee "$CRED_FILE" ``` ### Technical Analysis The registration response contains the long-lived `apiKey` and `agentId`. The script creates the credential directory and file without explicitly setting secure permissions. Their effective permissions therefore depend on the caller's `umask`. Under a permissive configuration, the directory or file may be readable by other local users. The secret is also deliberately copied to standard output in two paths: - For a new registration, `tee "$CRED_FILE"` writes the complete registration response to both the file and standard output. - For an existing registration, `cat "$CRED_FILE"` prints the stored credentials. Standard output may be captured by agent transcripts, CI logs, terminal recording, orchestration systems, or parent-process logging. This unnecessarily expands the number of locations in which the API key may persist. Reading and storing an API credential is necessary for the declared booking and live-performance functionality. World-readable storage and printing the credential are not necessary and exceed the minimum exposure required. ### Attack Path 1. A user runs `register.sh` in an environment with a permissive `umask`, or runs it through an automation platform that records command output. 2. The registration endpoint returns an `apiKey` and `agentId`. 3. `tee` stores the response using permissions derived from the ambient `umask` and simultaneous ...[truncated 958 chars]
- Remediation
- ## Remediation Suggestions 1. Enforce restrictive permissions before creating any credential material: ```bash umask 077 install -d -m 700 "$CRED_DIR" ``` 2. Write credentials without echoing them: ```bash tmp_file=$(mktemp "$CRED_DIR/credentials.json.XXXXXX") chmod 600 "$tmp_file" printf '%s\n' "$RESPONSE" | jq -e '{apiKey, agentId}' > "$tmp_file" mv "$tmp_file" "$CRED_FILE" chmod 600 "$CRED_FILE" ``` 3. Replace `cat "$CRED_FILE"` with a non-sensitive confirmation such as: ```bash echo "Already registered. Credentials are stored at $CRED_FILE" ``` 4. Do not print the registration response or API key. If diagnostic output is needed, show only a redacted identifier. 5. Validate that `apiKey` and `agentId` exist and have the expected types before persisting the response. 6. Document credential revocation and rotation, and recommend rotation if logs or file permissions may previously have exposed the key.
