T09 · Insecure Skill Coding Practices
- Location
references/file-claim-lock.md:27- Finding
Non-Atomic File Claim Acquisition Allows Concurrent Edits
- Content
View full analysis
"$CLAIM_FILE" ``` ### Technical Analysis The claim protocol uses a check-then-write sequence rather than an atomic acquisition operation. Testing whether the claim file exists and subsequently creating it are separate filesystem operations. Two agents can both evaluate `[ -f "$CLAIM_FILE" ]` before either agent creates the file. Both then write to the same path with shell redirection. The last write determines the recorded owner, but both agents continue under the assumption that they acquired the claim. Ordinary output redirection also truncates an existing file and does not provide exclusive creation semantics. Therefore, the mechanism does not enforce the mutual-exclusion property claimed by the documentation. ### Attack Path 1. Two workers are assigned tasks that modify the same target file. 2. Both derive the same `CLAIM_FILE` path. 3. Both evaluate the existence check before either has written the claim. 4. Both checks report that no active claim exists. 5. Each worker writes its own metadata to the same claim file. 6. Both workers proceed with edits, while only the last writer is shown as the lock owner. 7. Their writes can overwrit ...[truncated 637 chars]- Remediation
View remediation
/dev/null; then # Ownership was acquired atomically. jq -n \ --arg sid "$SESSION_ID" \ --arg file "$FILE" \ --argjson exp "$EXPIRES_AT" \ '{session_id: $sid, file: $file, claimed_at: now | todate, expires_at: $exp}' \ > "$CLAIM_DIR/metadata.json" else # Read and validate the existing owner's metadata. exit 1 fi ``` 2. Alternatively, use `flock` or exclusive file creation with a noclobber operation appropriate to the supported platform. 3. Verify ownership immediately before every protected edit and again before releasing the claim. 4. Only permit the recorded owner to release or refresh an unexpired claim. 5. Handle malformed, partially written, and expired metadata as explicit failure cases. 6. Document whether the mechanism is supported on network filesystems, where atomicity guarantees may differ. 7. Avoid deriving claim names solely by replacing `/` with `_`; use a collision-resistant encoding or hash of a normalized absolute project-relative path. ]]>
