Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

91 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

HeaderWright

Chrome Web Store

A small, dependency-free Chrome extension for setting, appending, and removing HTTP request headers, built on Manifest V3's declarativeNetRequest API only. No webRequest permission, ever. HeaderWright receives no request or response events: it hands declarative rules to Chrome, and Chrome applies them internally. That's verifiable by reading the manifest rather than trusting a description.

What it does

  • Header profiles: set / append / remove request headers
  • Per-profile domain scoping (subdomains included)
  • Master on/off toggle with a badge showing that toggle's state, plus a distinct state when Chrome rejects a rule registration
  • Deterministic JSON import/export — canonical key-sorted, byte-stable output, so configs can be shared and versioned in git

What it deliberately does not do (yet)

  • No response header modification — a later version
  • No account, no sync, no backend — profiles live in local extension storage
  • No telemetry

Install

Install from the Chrome Web Store

To run from source instead, see Development.

Permissions

HeaderWright does not request access to any site at install time. When you add a profile scoped to a domain, the browser prompts for permission on that domain only — one extra click per new domain, not once for everything.

Why:

  • Bounded blast radius. If the extension is ever compromised — a bad update, a hijacked account, a supply-chain slip — the damage is limited to domains you've actually granted, not every site you visit.

  • Revocable per site. Deleting a profile, editing its domains, or importing a config that drops a domain all release that domain's permission — unless another profile still references it. Verified against chrome.permissions.getAll(): the grant is gone immediately, not deferred.

  • What you see is what's true. HeaderWright's own popup is the honest display: a green dot means the grant is currently held, a gray dot means it isn't and the headers will not apply. Both are read from Chrome at render time rather than remembered.

    One caveat, found while verifying this: the site list under chrome://extensions → Details is not a reliable view of what is currently granted. It has been observed listing a domain that chrome.permissions.getAll() reports as not granted. Trust the popup, or the API, over that panel.

  • Lighter store review. Broad host permissions draw more scrutiny from the Chrome Web Store; asking for nothing until it's needed avoids that by construction, not by explanation.

This costs one extra permission prompt the first time you scope a profile to a new domain. That's the tradeoff, made deliberately.

A note on the prompt's wording: Chrome phrases every host grant as "read and change your data" on the site. That describes the permission class, not this extension — with declarativeNetRequest only, the browser applies the rules itself and no extension code observes any request. The manifest is the proof.

A note on prompts that don't appear: re-adding a domain you previously removed may produce no dialog at all. The grant is still acquired — Chrome appears to suppress the prompt for a host you have already consented to for this extension. Nothing is hidden from you when this happens: the popup's dot, chrome.permissions.contains() and chrome.permissions.getAll() all agree that the grant is held.

How far that suppression reaches is only partly established. Uninstalling the extension does clear it — reinstalling and granting the same host prompts again, observed twice. Whether it is scoped to the browsing session or persists indefinitely for an install that stays in place is not yet verified; settling it needs a fresh browser profile, and it is recorded here as open rather than guessed at. The practical consequence either way is that the absence of a prompt is not evidence that a grant was skipped — read the dot.

Development

No build step — the extension/ directory is the extension. Load it unpacked from chrome://extensions with Developer mode on.

Run the selftests with node test/selftest.mjs from the repo root (no dependencies). The suite covers rule construction and the canonical export format, and ends with a check-count tripwire: adding or removing checks requires updating EXPECTED_CHECKS in the same commit.

The suite verifies construction, not application — a rule can be built correctly and still no-op on a domain without a permission grant, so release verification also includes a manual smoke test against a live endpoint. Those steps are written down in test/SMOKE.md rather than left to memory.

Versioning

Each minor version adds exactly one feature; patch versions are fixes only, never features.

License

MIT — see LICENSE.

About

A small Chrome extension for setting, appending, and removing HTTP request headers by profile. Built entirely on Manifest V3's declarativeNetRequest — no webRequest permission, so nothing in it can read your traffic. Permissions are requested per-site, not all at once at install.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages