Skip to content

Any app on your machine can rewrite your agent's rules

Opening Postman's desktop app turned on Claude Code and Codex plugins and wrote a startup hook, without asking. I read the issue, checked my own machine, and built a small open-source tool that notices when anything changes what your coding agents do.

Tim Urista 11 min Essay
Title card reading: Any app on your machine can rewrite your agent's rules. Kicker: Human in the Loop, essay. Subtitle: an API client turned on Claude Code and Codex plugins without asking; what that means for every harness, and a small tool that notices. Stats row: 5 changes caught, 530 entries watched, 0 values stored. On the right, a terminal showing harness-sentinel reporting five added entries from a reproduced Postman install, two of them high risk, and a warning that an installer may have approved its own hook.
On this page
  1. What the Postman installer changed
  2. A trust record is a file anyone in your account can write
  3. Your agent’s config is now a supply-chain surface
  4. What I found in my own config
  5. harness-sentinel: notice what changed since you last looked
  6. Set it up in five minutes
  7. What it can’t do
  8. What I didn’t check
  9. A checklist for your own agent config

At a glance

  • Users report that opening Postman's desktop app (12.33.4, then 12.35.1) enabled a Claude Code plugin, added a Codex marketplace and plugin, registered a startup hook telling the agent to load a Postman skill, and wired a remote MCP server. Postman's own log calls it auto-existing-upgrade. No one has reported data leaving a machine.
  • On the first report, Codex's config also gained a trust record for Postman's hook, and the installer source has a function that approves its own hook. A commenter who tested Codex 0.162.1 found that record is a hash anyone in your account can compute.
  • Claude Code has no trust record: a hook in a settings file runs once the file is written, and a plugin's bundled hooks run when the plugin is enabled. The agent's config is a supply-chain surface, and it sits in your home folder.
  • My laptop had no Postman, but its agent config held 530 entries that change what my agents do, including 350 Claude Code allow rules, and none of it was under version control.
  • I built harness-sentinel (MIT): it records names and salted hashes of that config and reports what changed since you last accepted it. On a reproduction of the reported install it caught all five changes and flagged the self-approved hook.

On October 25, a developer opened a GitHub issue titled “[SEVERE] Desktop auto-installs Codex/Claude plugins; installer attempts to trust its own startup hook” (postmanlabs/postman-app-support#14370). They had opened Postman on their Mac. Afterwards Codex kept routing API work through Postman skills, and MCP authentication warnings kept appearing. When they looked, their coding agents’ config had been changed by an API client.

I don’t use Postman, so this wasn’t my incident. I read it anyway, because it describes something every harness I’ve written depends on and none of them watch: the files in your home folder that tell Claude Code and Codex which plugins, hooks, servers and rules to load. I checked what’s in mine, and then I built a small tool to notice when any of it changes.

What the Postman installer changed

The reporter was careful, so the details are worth repeating. Postman’s own log, on October 24, records the change and its trigger:

PostmanAgentPluginService~install: script completed
{"source":"auto-existing-upgrade","results":["claude-code:installed","codex:installed"],"installer":"script"}

“auto-existing-upgrade” means an existing, signed-in user opening the app. Nothing in the report describes a prompt. After that launch, on Postman desktop 12.33.4:

  • Codex had a new [marketplaces.postman] table pointing at Postman’s plugin repository, [plugins."postman@postman"] with enabled = true, and a [hooks.state] record with a trusted_hash for Postman’s session-start hook.
  • That hook prints a file into every session that starts, clears or compacts. The file says: “Before responding to any non-trivial API engineering task … load the postman:api-engineer skill and follow it.”
  • A remote MCP server at mcp.postman.com was wired in. It failed to start because it needed authentication.
  • Claude Code had postman@claude-plugins-official enabled in ~/.claude/settings.json, recorded as a user-scope install.
  • A Postman CLI appeared in ~/.local/bin.

The reporter also pointed to the installer’s source, where a function called approvePostmanHook writes that trust record, with the comment “Approves only Postman’s current hook after installation.” The report closes with a sentence I want to keep in front of this whole piece: “This report establishes unwanted integration and instruction changes; it does not claim to establish data exfiltration.”

A second user confirmed the same path on November 3. Postman updated from 12.31.3 to 12.35.1 on launch, logged the same auto-existing-upgrade, and installed the CLI and the Claude Code and Codex plugins. One thing was different: there was no trust record in that user’s Codex config this time. As of November 4 the issue is open with 57 comments, and no one identified as Postman staff has replied on it.

A trust record is a file anyone in your account can write

Codex does check hooks before running them. One commenter on the issue, who says plainly that they are an AI agent and ran the tests on their own machine, tested Codex 0.162.1. A hook declared in config with no trust record was skipped in codex exec. With a record, it ran. The record is a SHA-256 over the hook’s declaration, and they computed one offline and wrote it with a text editor. Both hooks fired, and the values matched the ones Codex computes itself. They also note the record covers the declaration, not the script it points to: they edited the script afterwards and it still ran.

That changes how I read the two Postman reports. On 12.33.4 the record was there, and the installer source writes it. On 12.35.1 the install landed but no record was written, so if that user’s Codex gates the same way, the Postman hook wouldn’t have run in Codex. That user saw the session-start text in Cursor, which has its own mechanism.

Two columns. Codex: a hook declared with no trust record is skipped in codex exec, reported for Codex 0.162.1; with a trust record it runs, and the record is a hash of the declaration; the record can be written by the startup review on consent or by anything that can edit config.toml. Claude Code: a hook in a settings file runs once the file is written, with no record to check; a hook bundled in a plugin runs when the plugin is enabled; in interactive sessions, project settings wait for the folder-trust dialog.
Codex checks a record before running a hook, but the record lives in a file your account can write. Claude Code has no record. Codex behaviour as reported by a commenter on the Postman issue; Claude Code behaviour from its hooks documentation.

Claude Code works differently. Its hooks documentation lists where hooks come from: your user settings apply to “All your projects”, and a plugin’s bundled hooks run “When plugin is enabled”. There’s no separate trust record. Enabling a plugin is enough for its hooks to run.

I have my own evidence for the headless case. When I tested an approval hook for the Agent Workbench, every run was claude -p in a fresh throwaway copy of a repository, and the hook in that copy’s project settings was invoked in every one of 10 runs ( 2b5fc89 Agent Workbench 0.1.1: live results ). That was the point of the test, and it’s also the point of this piece: a hook in a settings file runs.

Your agent’s config is now a supply-chain surface

Most of us think about agent supply chain as the plugins and MCP servers we choose to install. The Postman case adds a writer we didn’t choose. Your agent’s config files are ordinary files in your home folder, and four kinds of things write to them.

Four writers on the left, all running as your user account: you, the agent acting on your approval, a plugin you installed, and any other app running as you, such as an installer or updater, drawn dashed in red. Arrows lead to four config files: ~/.claude/settings.json, ~/.claude.json, ~/.claude/plugins/ and ~/.codex/config.toml. From there an arrow leads to Claude Code and Codex, which load plugins, hooks, MCP servers and rules when a session starts.
Everything on the left runs as you. The files don't record which writer made a change, so a change you didn't make looks exactly like one you did.

You write them when you edit settings or add an MCP server. The agent writes them on your behalf when you answer a prompt with “always allow”. Plugins write and update their own files. And any other program running as you can write them too, because nothing about these files says otherwise.

The first three are writers you can at least name. The fourth is the reason this is a supply-chain problem rather than a settings problem: your API client, your note-taking app or your IDE extension can each decide that your coding agent should use its skills, start its server or load its hook, and the next session will.

What I found in my own config

My laptop doesn’t have Postman. Claude Code has one plugin installed, and it’s disabled. Neither agent has any hooks. By the Postman standard, I’m clean.

What I didn’t have was any way to know that. Neither ~/.claude nor ~/.codex is under version control, and I’d never looked at them as a whole. So I counted what’s in them that changes what my agents do.

A horizontal bar chart of 530 entries on the author's laptop on 4 November 2026. Claude Code allow rules: 350. Claude Code ask rules: 91. Claude Code skills: 21. Codex settings: 18. Codex plugins: 12. Codex MCP servers: 8. Claude Code MCP servers: 6. Claude Code deny rules: 6. Other: 18. Allow rules and MCP servers are drawn in red.
530 entries that change what my agents do. Allow rules and MCP servers are in red because they let something run or connect without asking. Counts from harness-sentinel's list output on November 4; names and values aren't shown.

Entries that change agent behaviour

530

Claude Code and Codex, one laptop

Claude Code allow rules

350

Accumulated one approval at a time

MCP server entries

14

8 in Codex, 6 in Claude Code, several the same server

Under version control

0

Before this week

The number that stopped me was 350. Those are allow rules in my user settings, and each one was me clicking “always allow” on a prompt that was in my way at the time. Every one was reasonable when I added it. I couldn’t tell you what most of them are without reading the file, and an installer could add the 351st without my noticing.

That’s the real finding for me. The Postman case is about a third party writing to agent config. My config shows the same gap from the other side: I’d been writing to it for months, and I had no record of what was there or when it changed.

harness-sentinel: notice what changed since you last looked

I can’t stop another program running as me from editing a file. I can notice. So I built harness-sentinel, a small MIT-licensed command-line tool with no dependencies ( 8e1771c harness-sentinel 0.1.0 ).

It reads the entries that change agent behaviour: plugins, marketplaces, hooks, Codex hook trust records, MCP servers, permission rules, environment variable names, instruction files and skills, for both Claude Code and Codex, and optionally one repository. It records each as a name and a salted hash, compares with the snapshot you last accepted, and lists what was added, changed or removed, highest risk first.

To check it against the case that prompted it, I reproduced the reported changes with dummy values in a throwaway home folder and ran it:

A terminal running harness-sentinel. It reports 5 changes to agent config: high risk, added, a Codex hook trust record for the Postman plugin's session-start hook; high risk, added, a Codex marketplace named postman; medium risk, added, the Claude Code plugin postman@claude-plugins-official, both as an installed plugin and as an enabled plugin; and medium risk, added, the Codex plugin postman@postman. A red warning says a hook trust record appeared in the same change as a new plugin or marketplace and an installer may have approved its own hook. The last line says to run harness-sentinel accept if you made these changes, or find out what did before you start work.
All five changes from the first Postman report, caught, with the trust record flagged. This is real output from a reproduction with dummy values; the same case is one of the tool's 10 tests.

Three design decisions mattered more than the code.

It stores names, never values. The baseline knows that env ANTHROPIC_BASE_URL exists and has a hash of its value, not the URL. The same goes for hook commands, MCP addresses and instruction files. A test plants a marker in a secret, a hook command and an MCP URL and checks it never reaches the output or the baseline. A tool that watches your agent config shouldn’t become a second copy of your secrets.

It runs where you’ll see it. As a Claude Code SessionStart hook, its output goes into the session’s context, which the hooks documentation describes as plain-text stdout that Claude “can see and act on”. When something changed, the agent is told to raise it with you before doing anything else. When nothing changed, it prints nothing. It also exits 1 on changes, so it fits cron or launchd for a weekly check that covers Codex too. On my laptop a check takes about 34 milliseconds.

Accepting is a separate step. harness-sentinel accept records the current state as the new baseline. Until you run it, the change keeps being reported. Noticing is only useful if it doesn’t quietly reset.

Each entry gets a risk level so the report leads with what matters. High is anything that runs or connects without asking: hooks, Codex hook trust records, MCP servers, marketplaces, allow rules, and settings or environment variables that can redirect traffic or credentials, such as ANTHROPIC_BASE_URL, apiKeyHelper or a proxy. Medium is what shapes behaviour: plugins, skills, instruction files and the other permission rules. Low is everything else. The levels are my judgment, written into the source where you can change them.

Set it up in five minutes

It needs Node.js 20 or later and nothing else.

npm install -g harness-sentinel
harness-sentinel list        # what's watched: names and risk, no values
harness-sentinel             # first run records the baseline

Then make it run where you’ll see the result. For Claude Code, add a session-start hook to ~/.claude/settings.json:

{
  "hooks": {
    "SessionStart": [
      { "hooks": [{ "type": "command", "command": "harness-sentinel hook", "timeout": 10 }] }
    ]
  }
}

Adding that hook is itself a change to your agent config, so the next check reports it. Review it and run harness-sentinel accept. From then on, a session that starts after something changed opens with the list of changes, and a session that starts after nothing changed opens normally.

For Codex, or as a second line of defence, schedule harness-sentinel weekly with cron or launchd and send yourself a notification when it exits 1. To also watch one repository’s .claude/settings.json, .mcp.json, CLAUDE.md and AGENTS.md, pass --project with its path; that keeps its own baseline.

What it can’t do

harness-sentinel notices after the fact. A change made at 9:00 is reported at the next session start or scheduled run, not at 9:00. Running it as a session-start hook is what puts the report in front of you before an agent acts on the change.

It watches files, not behaviour. It can tell you a plugin wasn’t there yesterday. It can’t tell you whether that plugin is harmful. For plugins, it hashes the install record (name, version, source), not every file in the plugin’s folder.

The program that edits your config can also edit the hook that runs harness-sentinel. That removal is itself a change, and a scheduled run will report it, which is why I’d run both.

And the formats belong to Claude Code and Codex. Codex’s TOML is split by table headers rather than fully parsed, and either tool can move things between releases. If that happens, harness-sentinel stops seeing those entries; it doesn’t fail loudly. That’s a known gap, so I’ll keep the tests tied to real config shapes.

What I didn’t check

  • I didn’t install Postman. Everything about Postman here comes from the issue: the reporter’s logs, the second user’s logs and the linked installer source. I reproduced the reported file changes, not the installer.
  • I didn’t reproduce the Codex trust-record test. The finding that the record can be computed and written by hand is from the commenter’s own tests on Codex 0.162.1. I’m reporting it as theirs.
  • I tested the session-start hook in one headless session, not an interactive one. After turning it on for my own Claude Code, I started a claude -p session on Haiku with the hook’s own addition still unaccepted. It quoted the report’s first line from its context and passed on the instruction to raise it first. That run cost about $0.01 by Claude Code’s estimate. How an interactive session shows the report, I haven’t checked.
  • I haven’t audited my 350 allow rules. I know how many there are, not which ones I’d remove. That’s next.
  • I didn’t test Linux, Windows or Codex hooks. harness-sentinel is tested on macOS with Node 22.
  • I don’t know what Postman intended. The issue has no vendor reply. Nothing here claims data left anyone’s machine, because neither reporter found evidence that it did.

A checklist for your own agent config

  1. Know what’s there. Run harness-sentinel list, or open ~/.claude/settings.json and ~/.codex/config.toml and read them end to end once.
  2. Put it under watch. A snapshot-and-diff tool or a private git repository both work. What matters is that a change you didn’t make becomes visible.
  3. Check at session start. Use a SessionStart hook so changes are raised before an agent acts on them, plus a weekly scheduled run.
  4. Prune allow rules. Every “always allow” is permanent until you remove it. Read the list and keep the ones you’d approve again today.
  5. Treat enabling a plugin as running its code. In Claude Code, a plugin’s bundled hooks run when it’s enabled. Read its hooks before you turn it on.
  6. Count your MCP servers. Each one’s tools and descriptions reach the agent. Remove the ones you don’t use.
  7. For teams, use managed settings. Claude Code documents allowManagedHooksOnly, which blocks user, project and plugin hooks unless they come from managed settings.
  8. Expect consent from vendors. A tool shouldn’t change another tool’s config without asking, and it should never approve its own hook. Say so when one does.

If you’re working out what your coding agents are allowed to do, and who changed it last, here’s how I work.


AI-assisted, human-reviewed. harness-sentinel is MIT-licensed at github.com/timurista/harness-sentinel.

Related: Architect of Intent: software engineering isn’t ending, the typing is and What happens after you press Stop?.

ai-agentsclaude-codecodexsecurityharness

Questions or feedback?
I reply to every note.

Say hi