Skip to content

[bug] EnsureGitignore: TOCTOU race between read-check and append-write #286

Description

@lugassawan

Audit findings — fileutil

Scope: reliability · Severity range: Low–Low
Source: codebase audit

reliability

Severity File:Line Symptom Suggested fix
Low internal/fileutil/gitignore.go:14 Two concurrent rimba processes can both see a .gitignore entry as absent and both append it, producing duplicate entries Use syscall.Flock advisory lock, or write to a temp file and rename atomically; alternatively document the single-writer invariant

Root cause: There is no file lock or atomic compare-and-append between the os.ReadFile check (line 19) and the os.OpenFile O_APPEND write (line 38). The check-then-act is a classic TOCTOU race. Both the trust.Record path and the init path call EnsureGitignore. EnsureLocalGlobIgnored also calls RemoveGitignoreEntry followed by EnsureGitignore in two separate steps, which is not atomic and widens the TOCTOU window.

Reasoning chain:

  1. gitignore.go:19os.ReadFile; line 26–29 — checks for entry; line 38 — os.OpenFile O_APPEND if not found. Three separate syscalls, no lock.
  2. rimba exec --all or parallel CI scripts could trigger concurrent rimba add calls on the same repo root.
  3. Both processes see the entry as absent → both append → duplicate entry in .gitignore.
  4. EnsureLocalGlobIgnored calls RemoveGitignoreEntry + EnsureGitignore in sequence (not atomic), further widening the race window.
  5. Result is a duplicate .gitignore entry — semantically harmless, but shows as a diff in git status.

Counter-evidence considered: Duplicate .gitignore entries have no security or functional impact — git applies all matching lines, and for gitignore semantics all matches are valid. The race requires two processes running simultaneously against the same repo — unlikely in interactive CLI use. The failure mode is cosmetic only. Severity is Low because the race cannot cause a security-relevant entry to be dropped.


Provenance

Filed by workflow-audit-emit-issues from an in-session codebase audit.
Re-running re-files — check for duplicates before confirming.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions