Skip to content

Watcher re-indexed oauth_creds.json despite post-#252 engine guard (investigation) #261

@memtomem

Description

@memtomem

Observation

On 2026-04-18, a running memtomem-server started after the PR #252 merge re-indexed ~/.gemini/oauth_creds.json at approximately 21:48, following a Gemini CLI token refresh (mtime change on the file). The server process was started at ~21:05 that same day, which is after PR #252 had been merged to main and installed via editable install.

The file matches both:

Both were intended to block it. It still appeared in mem_list source_filter=oauth after the observation.

Single-instance observation; not yet confirmed reproducible in a fresh test environment. Filing now to invite investigation before 0.1.10 reaches PyPI.

What we ruled out

The entry-point guard itself blocks oauth_creds.json when index_file is invoked directly with inputs shaped like what the watcher produces. The regression test test_index_file_entry_point_blocks_excluded in packages/memtomem/tests/test_indexing_engine.py exercises this exact call shape and passes on current main. So the guard logic for this filename shape is not the cause.

Candidate hypotheses

  • Stale watcher config reference. The watcher component captures a _config reference at startup. If the session's config is mutated during the run (CLI mm config set, hand-edit of ~/.memtomem/config.json) without a server reload, the watcher may be matching user_spec against stale state while the engine reads live state. The specific session saw two config mutations between server start and the re-index event without a reload in between.
  • Watcher event-type variance. watcher._reindex enqueues on any watchdog event without distinguishing create vs. modify vs. move. A specific event variant may reach the engine via a code path that skips the guard. Needs inspection of the watchdog handler → queue → index_file chain.
  • Pre-existing chunk surfaced via readback. The mem_list query that observed the entry may have returned a chunk that predated the post-fix(indexing): apply built-in + user excludes at index_file entry point and against absolute paths #252 server restart, not a freshly written one. Compare the chunk's created_at timestamp against the restart time to rule this out.

Reproduction recipe (not yet confirmed reproducible)

  1. Start memtomem-server with ~/.memtomem/config.json: indexing.exclude_patterns = [] (or with the field omitted), and no config.d fragment contributing excludes beyond defaults.
  2. Ensure ~/.gemini exists (auto-discovered when present).
  3. Confirm no existing entry: mem_list source_filter=oauth should return empty.
  4. touch ~/.gemini/oauth_creds.json (simulates a token refresh).
  5. Wait for the fs watcher debounce window + re-index cycle (~a few seconds).
  6. Expected: mem_list source_filter=oauth still returns empty. Observed on 2026-04-18: 1 file indexed.

Not a blocker for 0.1.10

The upcoming 0.1.10 release (in progress on main; tag + PyPI publish pending) closes the watcher vulnerability that existed across 0.1.0–0.1.9, where IndexEngine.index_file had no exclude guard at all. This issue is a narrower investigation into whether some residual path bypasses the newly-added guard. If reproduction confirms a real bypass, a follow-up patch will ship and this issue will move into security advisory territory.

Disclosure note

This issue discusses a possible residual on the same code area as the 0.1.10 security fix. Publishing it alongside (rather than after) that release is a deliberate trade-off: the project's small user base makes silent investigation less valuable than public invitation for reproduction attempts.

Related

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