Skip to content
Back to skills

Native Messaging Host Conflicts

ASecurity

Use when a browser extension native messaging host fails, times out, or the wrong host spawns. Not for network, browser-install, or unrelated extension failures.

  • 52 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 3, 2026
ai-agentsgoshell

Works with

  • terminal
  • cli

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned September 20, 2026

npx -y skills add OutlineDriven/outline-driven-development --skill native-messaging-host-conflicts --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Native Messaging Host Conflicts?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Native Messaging Host Conflicts
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/outlinedriven-native-messaging-host-conflicts-outline-driven-development/badge)](https://www.skillsdirectory.com/skills/outlinedriven-native-messaging-host-conflicts-outline-driven-development)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: native-messaging-host-conflicts
description: 'Use when a browser extension native messaging host fails, times out, or the wrong host spawns. Not for network, browser-install, or unrelated extension failures.'
disable-model-invocation: true
---

# Native messaging host conflicts

## Contract

| Field | Bound contract |
|---|---|
| Trigger | A browser extension's native messaging fails: disconnected extension, tool timeouts, or the wrong host answers after two clients for the same host name were installed or switched between. |
| Authority | Reversible local: mutates only native-messaging manifests, the host wrapper, stale host processes, and sockets; rollback is renaming the `.disabled` manifest back and restoring the backed-up wrapper. No remote mutation. |
| Side effect | Native-messaging manifest selection, host wrapper, host process, and socket state. |
| Done | Exactly one intended host is active, its expected socket exists, and a freshly restarted client connects through the extension. |

## How the mechanism breaks

A browser launches whichever binary its NativeMessagingHosts manifest names for the host id an extension requests. When two client applications ship a manifest for the same host name (a CLI and a desktop app being the common pair), the browser can spawn either, both can run, and each client can connect to the other one's socket. A client connects only at startup, so a client that starts against the wrong or absent host fails for its whole session. Reconciliation is therefore: diagnose, keep exactly one manifest active, clear stale processes and sockets, restart the browser, then restart the client.

Manifest locations for the Chrome family; other Chromium browsers use the same layout under their own user-data directory:

- macOS: `~/Library/Application Support/Google/Chrome/NativeMessagingHosts/`
- Linux: `~/.config/google-chrome/NativeMessagingHosts/`
- Windows: registry key `HKCU\Software\Google\Chrome\NativeMessagingHosts\<host-name>`, whose default value points at the manifest path.

## Inputs

- Which client is intended to own the host. Both cannot run simultaneously.
- The host name and the manifest file names each client installs, visible as distinct JSON files (often vendor-prefixed) in the manifest directory.
- Optional: the browser profile that has the extension installed.

## Procedure

1. Diagnose the active conflict before mutating anything:
   - List running host processes with `ps aux | grep <host-binary-name>` and note each binary path; a versioned install path means a wrapper may pin a stale version.
   - Find the socket. Native hosts talk over a socket in the temp dir (`$TMPDIR`; on macOS `$(getconf DARWIN_USER_TEMP_DIR)`). One client may use a single file, another per-PID files under a shared directory. `lsof -U | grep <socket-prefix>` shows the holder.
   - List active manifests with `ls <manifest-dir>/<prefix>*.json` (on Windows, read the registry key).
   Done when: the active host process, socket holder, and active manifests are named.
2. Keep exactly one host. Rename the unintended client's manifest to `<name>.json.disabled` (rollback: rename it back). Both active at once is the defect this skill fixes. Done when: exactly one manifest is active and the other is `.disabled`.
3. If the surviving wrapper pins a hardcoded versioned binary, back the wrapper up and rewrite it to exec the latest installed version (`ls -t <versions-dir> | head -1`), then `chmod +x`. Rollback: restore the backup. Done when: the wrapper resolves the latest binary, or is skipped because it is already version-independent.
4. Clear stale state: kill the host processes (`pkill -f <host-binary-name>`), then remove stale socket files and per-PID socket directories. Done when: no stale host process or socket remains.
5. Restart the browser, then trigger the extension once (open its popup or click its icon) so the intended host spawns. Done when: the browser restarted and the extension was triggered.
6. Verify the intended host process is running and its expected socket exists at the location diagnosis found. Done when: the host runs and the socket exists.
7. Restart the client last. Native-messaging clients connect at startup only; a client that starts before the bridge is ready fails for the session's whole lifetime. Done when: the restarted client connects.
8. If the failure persists, check secondary causes:
   - One extension install per browser profile; each extra profile with the extension spawns a competing host and socket.
   - One client session at a time; close other sessions or reconnect from the surviving one.
   - `TMPDIR` set and consistent with the socket path the client expects (`echo $TMPDIR`); if unset, the client looks in the wrong place, so export it in the shell rc.
   Done when: secondary causes are resolved, or the done predicate holds.

## Failure and recovery

- Wrong host still active after the rename: the browser caches manifests until restart. Repeat step 5 and re-verify. Never leave both manifests active.
- Socket missing after restart: the extension was not triggered, or the wrong manifest is active. Re-run step 1 and confirm exactly one manifest is present.
- Stale wrapper version: a hardcoded path points at a removed versioned binary. Apply step 3.
- Non-mutation rule: if the host OS is not covered by the manifest locations above, or the failure is unrelated to native messaging (network, browser install, desktop-app shell), stop without mutating anything.
- Blocked: report the active manifest, the running binary, whether the socket exists, and the `TMPDIR` value. Never report done while the socket is absent or the wrong host is running.

## Output

A terminal classification stating which host is active, whether its expected socket exists, and whether a restarted client connects, with the one active manifest and the one `.disabled` manifest named. No partial success is reported as done.

Files in this skill

  • SKILL.md6 KB
  • agents/openai.yaml312 B

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.