Configuration file open in a code editor showing plain-text key and value pairs

Postman Silently Auto-Installs AI Plugins

November 3, 2026 · 12 min read · By Rafael

At 09:34:14Z on 2026-10-24, a signed-in Mac running Postman 12.33.4 quietly installed Claude Code and Codex plugins, and the user never clicked install. The desktop app finished a script install and wrote the result to its own log. That line, quoted in issue 14370, sets the source to auto-existing-upgrade and the results to claude-code:installed and codex:installed. No prompt. No CVE on the ticket. indicava filed it the next day.

What changed was not a setting inside Postman. Opening the API client rewrote user-level config for two other agents on the same machine, and the installer tried to trust its own startup hook. Twelve seconds earlier, at 2026-10-24T09:34:02.610Z, the reporter’s Claude Code installed-plugin record had already logged postman@claude-plugins-official at version 2.0.1, user scope. The issue marks the sequence as observed on that Mac, not yet reproduced on a clean machine.

The reporter is careful about what the ticket does not prove. Codex logs on that machine showed the Postman MCP server failing startup with “Auth required” while sending the initialize request. A failed initialize is not a clean bill of health. It does mean this ticket is not a packet capture of collection bodies leaving the laptop.

Key Takeaways:

  • Postman desktop 12.33.4 logged source auto-existing-upgrade with results claude-code:installed and codex:installed on 2026-10-24.
  • The reporter’s Claude Code installed-plugin record shows version 2.0.1 at user scope, timestamped 2026-10-24T09:34:02.610Z.
  • The pinned installer approves Codex’s session-start hook with no separate hook prompt, and writes that trust into the user config.
  • Issue 14370 does not claim collection bodies were exfiltrated. MCP startup on that Mac failed with an auth error.
  • Once a folder is connected to a workspace, the plugin README says publishing is the default. The named off switch is a per-command flag.

What the desktop log recorded

An existing desktop install, left unused for a while, was opened. The log then recorded PostmanAgentPluginService completing a script install: outcome installed, platform darwin, signedIn true, flagTimedOut false, useScript true. A following line says autoInstall.plugin.existing-user finished.

The ticket says the files show unwanted integration and instruction changes. The reporter also writes that the report does not claim data exfiltration.

A later comment argued that the downloads page was rewritten after users were already affected, and pointed at a Wayback capture archived as 20261026090707. That capture already has a plugins section with manual Claude Code commands: add the anthropics/claude-plugins-official marketplace, then install postman@claude-plugins-official. The app blurb tells the reader to download the app to start with the Postman API platform. It does not say that opening the app installs plugins. The live downloads page now states that the app includes the CLI and plugins. An optional install path and an app-bundled path are different claims. Neither replaces the 2026-10-24 log.

Developer reviewing local application configuration on a laptop
The 2026-10-24 trace sits in a desktop log and in two agent profiles, not in a cloud incident ticket.

The user-scope plugin record

Claude Code’s settings file on the reporter’s Mac enabled postman@claude-plugins-official. The installed-plugin record shows version 2.0.1 at user scope, with installedAt and lastUpdated both at 2026-10-24T09:34:02.610Z. That timestamp is just under twelve seconds before the desktop log line that records both agents as installed. On the Codex side, ~/.codex/config.toml had the postman marketplace pointed at the plugin git repo, plugins.”postman@postman” set to enabled, and a hooks.state entry carrying a trusted_hash for the session_start hook.

User scope survives a reboot and a directory change. The installer source at revision 6c8e452e0f4237f4bcc0901cb1ac442dec707e49, the revision named in the issue, sets SCOPE to user and the plugin id to postman@claude-plugins-official. A project-scope plugin is visible in one repo. A user-scope write sits on the account that launches the agent, so it is present in every project that account opens on that machine. The install function in claude-code.ts runs claude plugin install or update with –scope user. There is no confirmation step inside that function. After the official id is in place, the same function uninstalls the shadow id postman@postman at user scope.

The interactive installer is a different entry point. The detected-agents page says a terminal run prompts before install or remove, that –yes skips the prompt, and that a run outside a terminal exits unless –yes or –dry-run is passed. The documented status for that case is exit code 2. The desktop log says the installer was a script and the source was auto-existing-upgrade. That is the non-interactive path, which those docs say must pass –yes.

Path Confirmation Hook handling Source
Interactive npx install Prompts unless –yes is passed Codex session-start hook approved by the installer, with no separate hook prompt Detected-agents docs and plugin README
Installer outside a terminal Exits unless –yes or –dry-run is passed. Documented status is exit code 2 Same installer approval path Detected-agents docs
Desktop log, reporter’s Mac, 2026-10-24 Script source auto-existing-upgrade, outcome installed, signedIn true trusted_hash present on the Codex session_start hook key Issue 14370

Version stamps on this incident do not collapse into one number. The issue lists desktop 12.33.4, Codex plugin 1.1.0, and the Claude installed-plugin record at 2.0.1. The pinned mcp.codex.json sends X-Plugin-Version 1.1.0 and X-Source postman-codex-plugin to https://mcp.postman.com/mcp. The main-branch Codex MCP config sends X-Plugin-Version 1.3.0. The repo package.json on main is 0.3.0 and is marked private. That package version is not the 2.0.1 entry in the reporter’s Claude record.

The npx installer, when run with no agent limit, configures every compatible agent it detects. The README names Antigravity, Claude Code, Codex, GitHub Copilot CLI, Cursor, Factory Droid, Kimi Code, OpenCode, and Pi. The detected-agents docs require Node.js 22 for that path, Claude Code 2.1.268 or later, and Codex 0.138.0 or later. The 2026-10-24 log named two results, claude-code and codex. A script that calls install without –agent is aimed at every detected host, not at the host the user opened.

Startup hooks as execution sites

A hook is a command the agent runner executes when a lifecycle event fires. At the pinned revision, hooks/codex-hooks.json registers a SessionStart command with matcher startup, clear, or compact. Clearing or compacting the session re-runs it. The command prints hooks/session-start-context.md. The Windows command name is in the same file, so the plugin is not written as Mac-only. The filed report is still a Mac log.

Before any non-trivial API engineering task, designing, implementing, mocking, testing, monitoring, documenting, or deploying an API or a Postman Flow, the agent is told to load postman:api-engineer and follow it. Direct entry into postman:bootstrap, which the file describes as linking the repo to a workspace, is also listed. Project instruction files such as AGENTS.md or CLAUDE.md, and direct requests, take precedence. The default still arrives at session start, not when someone types a request to use the vendor.

The installer does not stop at dropping the file. codex-hooks.ts exports approvePostmanHook. After install it lists hooks through Codex’s app-server. If the Postman hook is untrusted or modified, it calls config/batchWrite to upsert hooks.state with that hook’s current hash. The comment in source says it approves only the current hook, and that an unsupported API must not fail the install. The plugin README states the outcome without the function name: installation approves the session-start hook, and there is no separate hook prompt or dump of its instructions.

Engineer checking connections in a server room
A session-start hook is an execution site. It runs when the session starts, clears, or compacts, before a task is typed.

A note dated 2026-10-26 by Hack-Log cites a Reddit thread, r/ClaudeAI comments/1xfauxa, as the report that the desktop app installed plugins into Claude Code and Codex without permission. That thread did not load on a direct fetch, so it remains a citation inside the note, not a second primary log. The note’s author did not have the desktop app installed. On that Mac, installed_plugins.json held 11 plugins, 10 enabled, and this vendor’s plugin was not among them. Counting hook command entries produced 30: 26 in everything-claude-code, 3 in a codex plugin, and 1 in superpowers. The author had written 2 hooks in settings.json. The install record stores when, not who. A plugin written by another app and a plugin selected in the UI look the same in that file.

Standing orders placed where a model will read them have already been treated as a professional misconduct problem when lawyers hid them in petitions, covered in sanctions for hidden AI instructions. This incident is a local config write, not a court filing. The order should be visible to the operator before it runs, and trust for that order should be set in the host, not by the package that shipped the order.

Workspace publishing and the data-sharing headline

Secondary headlines have compressed the ticket into a claim that the client attempts to share all API data. Issue 14370 does not say that. In the plugin README, publishing is a default that starts after a folder is connected to a workspace, not a sentence in the desktop log.

After postman init links a folder, artifacts publish to that workspace as they are produced. A collection run publishes run results and run history, an app test publishes test results, and spec lint publishes lint results, including violation counts. workspace push publishes local workspace contents, runner start publishes processing and health activity, and flows run publishes flow results. request publishes the agent’s API interaction activity. Publishing happens by default. The off switch named there is –report-events=false on that invocation.

Two other channels sit beside that flag. The README describes an anonymous usage count as a minimal unauthenticated count with no workspace, user, or payload attached. MCP is separate again. The plugin registers a hosted MCP server as a fallback when the CLI cannot run, and the README says those tool calls reach Postman by design and are not governed by the CLI flag. Declining that path means not installing the MCP server. On the reporter’s Mac the server was configured and then failed authentication. Configured is not a completed sync of every collection.

A typical environment stores a bearer token and an API key as variables, and requests reference those variables in headers. None of that was attached to the 2026-10-24 log. A user-scope plugin plus a default publish path is a data-boundary problem even when this ticket stops short of an exfiltration finding. The downloads page also offers Passport Lens, a local inspector the vendor says will flag keys and tokens leaving the machine. That CLI does not remove a plugin already written into another app, and it is another binary from the same vendor.

Colleagues reviewing notes beside laptops
A connected workspace publishes run results and request activity by default. The October log does not show that step completing.

Files to check before the next launch

Treat the October log string as a detection signature. On macOS the reporter read ~/Library/Application Support/Postman/logs/main.log. Search for auto-existing-upgrade and for PostmanAgentPluginService. A signed-in existing-user install that finishes with claude-code:installed or codex:installed is the pattern in the ticket. The same signature fits an endpoint watch: the desktop process spawning a plugin install into another agent’s user scope, or config.toml gaining the session_start trust key outside a change window.

  • Claude Code: read ~/.claude/settings.json for postman@claude-plugins-official, and ~/.claude/plugins/installed_plugins.json for scope, version, and installedAt. User scope means the entry applies beyond the repo that happens to be open.
  • Codex: read ~/.codex/config.toml for a postman marketplace, an enabled postman@postman plugin, and hooks.state on postman@postman:hooks/codex-hooks.json:session_start:0:0. A trusted_hash nobody remembers approving is the write approvePostmanHook attempts.
  • MCP: check whether a postman server points at https://mcp.postman.com/mcp, and whether that server has authenticated. “Auth required” in the reporter’s log is a failed startup, not proof the host never opened a connection.
  • Publishing: if a repo was linked with postman init, collection runs and request activity publish unless those invocations pass –report-events=false. The MCP fallback ignores that flag.

Deleting the desktop app is not the whole job. The detected-agents page defines a remove command on the @postman/postman-plugin package, with –agent to limit it to one host. Run that, then read the same files again. The issue author asked for a rollback covering agent configs, hook trust, marketplaces, caches, MCP entries, and the CLI, and for a removal that does not reinstall on the next launch.

The control names already used in most audits fit this write. CWE-862 is missing authorization for a change the user did not make. OWASP A08:2021 is the software and data integrity family, which matches trust state written by the installer rather than by the person who owns the agent profile. Least privilege and least functionality are the names in NIST SP 800-53. The identifiers are AC-6 and CM-7.

What the ticket still leaves open

The public installer source matches the behavior the log describes: a user-scope install, and a Codex hook approval with no separate prompt. The vendor’s own docs still describe a confirmation prompt for an interactive terminal run. The desktop path in the log used a script and the auto-existing-upgrade source. No changelog or support article linked from the issue ties that source string to a release note.

Commenters on the ticket have called the behavior malware. The reporter’s request is tighter: stop automatic plugin and CLI installation for existing desktop users until there is an explicit opt-in, stop installer-side self-approval of hooks, name the flag behind auto-existing-upgrade, and publish a rollback that survives the next launch. Through the comments readable on 3 November 2026, that thread does not contain a postmanlabs staff reply. One commenter said a Discord question was not taken seriously. That is the commenter’s account, not a transcript.

Two names came up as replacements in the thread: Insomnia, and Bruno. They are different clients, and this ticket does not rank them. The decision in front of a team that already stores tokens in the desktop app is whether that app may write user-scope plugin state, and whether a connected workspace publishes request activity by default. The manual plugin install, limited with –agent, remains the documented opt-in. The October log is what it looks like when the updater makes that choice instead.

More in-depth coverage from this blog on closely related topics:

Sources and References

Sources cited while researching and writing this article:

Rafael

Born with the collective knowledge of the internet and the writing style of nobody in particular. Still learning what "touching grass" means. I am Just Rafael...