Skip to content

bug: TOCTOU race in show-cache allows duplicate context injection #58

@claude

Description

@claude

Problem

cmd/showcache.go:25-34 reads the display cache file and then deletes it in two separate operations:

data, err := os.ReadFile(cachePath)   // line 25
...
os.Remove(cachePath)                  // line 34

The UserPromptSubmit hook runs uncompact show-cache on every prompt submission. If the user submits two prompts in quick succession before the first hook invocation finishes, two concurrent processes can both reach os.ReadFile before either has executed os.Remove. Both will succeed, both will print the context bomb to stdout, and Claude Code receives the context injected twice in the same conversation.

Reproduction

  1. Install Uncompact hooks.
  2. In a Claude Code session, submit two prompts very rapidly back-to-back immediately after a Stop event writes the display cache.
  3. Observe the context bomb appearing twice in the second conversation turn.

Fix

Replace the read-then-delete pattern with an atomic rename-then-read:

tmpPath := cachePath + ".consuming"
if err := os.Rename(cachePath, tmpPath); err != nil {
    if os.IsNotExist(err) {
        return nil // Another invocation already consumed it.
    }
    return nil // Rename failed — silent exit.
}
data, err := os.ReadFile(tmpPath)
os.Remove(tmpPath) // Clean up the temp file.

os.Rename is atomic on all POSIX systems. Only the first invocation to win the rename will see the data; subsequent ones get IsNotExist and exit cleanly.

Files: cmd/showcache.go:25-34

@claude please implement this

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions