T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/auth.sh:69
- Finding
- JWT cached in predictable shared temporary files without restrictive permissions<![CDATA[ ## Vulnerability Details **File Location**: `scripts/auth.sh:69-73` **Vulnerability Type**: Insecure temporary-file handling and sensitive token exposure **Risk Level**: High ### Vulnerable Code ```bash # Cache token and expiry echo "$token" > "$TOKEN_FILE" local expiry expiry=$(decode_jwt_expiry "$token") echo "$expiry" > "$EXPIRY_FILE" ``` The destination paths are statically defined at `scripts/auth.sh:9-10`: ```bash TOKEN_FILE="/tmp/food402-token" EXPIRY_FILE="/tmp/food402-token-expiry" ``` ### Technical Analysis The authentication JWT is written under globally shared `/tmp` using predictable filenames. The script does not: - Set a restrictive `umask`. - Create the files atomically. - Verify file ownership or type. - Reject symbolic links. - Explicitly set mode `0600`. - Separate caches by user or session. The resulting permissions depend on the caller's existing `umask`. Under a common `022` configuration, newly created files may be readable by other local users. Predictable names also create symlink and file-collision risks. Processes running under the same account can replace or poison the cached token, while permissive host configurations may expose it across accounts. The JWT is a bearer credential. Possession is sufficient to invoke the account, address, cart, order-history, and payment-related APIs until expiration. ### Attack Path 1. A victim invokes `auth.sh get-token`, which authenticates to TGO. 2. The returned bearer token is written to `/tmp/food402-token`. 3. A local attacker monitors or reads the predictable file if host permissions allow it. 4. The attacker submits the stolen JWT in an `Authorization: Bearer` header to the documented TGO APIs. 5. The attacker can access account data or modify the victim's cart and delivery settings within the token's server-side authorization scope. A same-account malicious process can also replace the cached file before a later API call, causing requests to execute under a different acc ...[truncated 539 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Store the cache in a user-private runtime directory such as `${XDG_RUNTIME_DIR}`. - If a fallback is necessary, use a per-user directory under `/tmp` created with mode `0700`. - Set `umask 077` before creating any credential-bearing files. - Create files atomically with `mktemp`, verify ownership, and reject symbolic links. - Set token-file permissions explicitly to `0600`. - Include the effective user ID in the cache location and do not share tokens between users. - Prefer an operating-system credential store or keychain where available. - Remove both files on logout and consider avoiding persistent token storage entirely. Example hardening pattern: ```bash umask 077 CACHE_DIR="${XDG_RUNTIME_DIR:-/tmp}/food402-${UID}" mkdir -p "$CACHE_DIR" chmod 700 "$CACHE_DIR" TOKEN_FILE="$CACHE_DIR/token" EXPIRY_FILE="$CACHE_DIR/token-expiry" tmp_token=$(mktemp "$CACHE_DIR/token.XXXXXX") printf '%s\n' "$token" > "$tmp_token" chmod 600 "$tmp_token" mv -f "$tmp_token" "$TOKEN_FILE" ``` ]]>
