Build1 publisher3 min readPublished
A Deleted API Key Kept Authenticating Because The Editor Froze It At Boot
A clean-room env check confirmed three credentials were gone from the profile. One of them was still signing live requests, held in a parent process that had started days earlier.
The Engineer · Build desk
Drafted by a language model from the sources cited here and checked against its claim ledger before publication. How we use AISend a correction
What happened
- The author deleted three ambient API keys from their shell profile.
- The author ran the clean-room check env -i HOME="$HOME" /bin/zsh -lc 'echo "${VARNAME:-unset}"' and read back unset for all three variables.
- A shell started with an empty environment can only see what the current profile puts there, so if it reports a variable missing, the profile is clean.
- Minutes after the check, the author reconnected a review tool used for cross-vendor sanity checks; it reported healthy with eight providers registered, one of them authenticated with a key that had just been deleted.
- The authentication was not a cached credential from an old response but a live, working authentication using a value that no longer existed anywhere on disk.
Compiled by The EngineerSomething wrong?How this is made
Why it matters
An engineer deleted three ambient API keys from a shell profile, then ran the standard clean-room check - `env -i HOME="$HOME" /bin/zsh -lc 'echo "${VARNAME:-unset}"'` - and read back `unset` for all three [1][2]. Minutes later, according to a writeup published on dev.to, a reconnected review tool came back healthy with eight providers registered, one of them authenticated with a key that had just been deleted [4]. That was not a cached response; it was a live, working authentication using a value that no longer existed anywhere on disk [5].
The check was not wrong. It answered a different question than the one being asked. A shell spawned with an empty environment can only see what the current profile puts there, so `unset` is a reliable verdict about the file [3]. It says nothing about any process that already existed, because it only tests a brand-new one [6]. Every process running before the edit read the profile once at its own startup, copied what it found into memory, and has not looked at the file since - at that point it stops being a reader of your profile and becomes a cache of it [7].
The holder of the stale value here was the editor itself: the long-lived process hosting the coding sessions and managing tool connections over MCP [8]. The author compared two timestamps, process start time against profile mtime, and found the process had started days before the edit, with the gap running to the better part of a week [9]. The parent had frozen its environment at launch and had been reinjecting that snapshot into every child it spawned since, including the review tool on reconnect [10]. Reconnecting a tool through that parent does not re-read the profile; it re-reads the parent's memory [10].
This is a class of bug, not an incident. Any process that starts once and lives a long time qualifies: editors, IDEs, scheduler daemons, an old shell or a terminal multiplexer session left open [11]. The practical decomposition in the writeup is three layers, not one. Layer one is the profile on disk, which is what `env -i` checks [12]. Layer two is the live parent, and specifically whether its start time predates your edit - if it does, it is guaranteed to be carrying the old value regardless of what the file says [13]. Layer three is the child in practice: what the consuming process actually receives when spawned right now, which is the only layer that describes reality and is downstream of the other two [14].
Layer two is cheap to inspect. `ps eww -p <PID> | tr ' ' '\n' | grep -c "^VARNAME="` counts whether the variable is present in the running process, and `ps -o lstart= -p <PID>` gives the start time to compare against the profile's mtime [16]. If the start time is earlier than the edit, layer two is already answered [17].
The reporting discipline matters more than the commands. Passing layer one and calling it fixed reports one third of the answer as the whole thing [15]. Until all three layers are checked, the honest status line is "profile cleaned up; not yet confirmed in effect" [15].
What to watch: credential rotation and revocation runbooks that end at the file. If a key is being retired because it leaked, deleting it from the profile and verifying with a fresh shell leaves it live in every long-running parent that booted before the change [7][10] - and, per this account, live in the children those parents spawn afterwards [10]. Restarting the parent, or revoking server-side rather than locally, is the part that actually closes the loop.