Skip to content

stillunfolding/Headerio

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Header — Secure HTTP Header Editor

A Chrome extension for modifying outgoing HTTP request headers on a per-site basis, built around a strict least-privilege model: it can set, append, or remove headers, but it cannot read your headers or request bodies, and it gains access to a website only after you explicitly grant it — one site at a time.

Manifest V3 Chrome 101+ License: MIT


Table of contents


Why Header

Most header-editing extensions ask for broad, always-on access to every site you visit, and many are built on APIs that can read your traffic. Header takes the opposite approach:

  • It uses Chrome's declarativeNetRequest API, which applies header changes declaratively — Chrome performs the modification internally. The extension never sees your header values, cookies, tokens, or request bodies.
  • It holds access to a site only while you have a rule for that site. Delete the last rule for a site and the extension's permission for it is revoked automatically.

The result is a tool you can use for real work — adjusting Authorization headers for a local API, spoofing a User-Agent, adding a custom header for a staging environment — without handing an extension the keys to your entire browsing session.

Security and privacy model

This is the core of the project, so it is worth stating precisely.

Property Guarantee
Header reading Not possible. The extension declares rules; it never receives header values.
Request/response body access None. The API does not expose bodies to the extension.
Site access Requested per site, on demand, via a Chrome permission prompt.
Least privilege When a site has no rules left, its host permission is revoked automatically.
Data collection None. Rules are stored locally in chrome.storage.local and never leave your machine.
Remote code None. All logic ships in the package; nothing is fetched or evaluated at runtime.

Header deliberately does not request the webRequest permission or the declarativeNetRequestFeedback permission, both of which would allow observing request details. If you audit the source, the absence of these is intentional.

Features

  • Set (replace), append, or remove request headers.
  • Per-site rules, scoped to a host and optionally its subdomains.
  • One-click enable/disable per rule, with automatic re-application on approval.
  • A quick popup for the current tab (or any site you type in), plus a full options page to manage every rule grouped by site.
  • Guardrails that prevent invalid rules — for example, Chrome only allows appending to a fixed set of standard request headers, and the UI enforces that with a dropdown instead of letting you create a rule Chrome would reject.
  • No build step. Vanilla JavaScript ES modules, HTML, and CSS.

Installation

From the Chrome Web Store

Install from the Chrome Web Store: (listing link to be added once published)

Source repository: https://github.com/stillunfolding/Headerio

From source (load unpacked)

  1. Clone or download this repository.
  2. Open chrome://extensions in Chrome (or any Chromium-based browser, version 101+).
  3. Enable Developer mode (top-right).
  4. Click Load unpacked and select the project folder (the one containing manifest.json).

The tools/ directory contains development helpers only and is not required at runtime; it can be excluded when packaging for the store.

Usage

Add a rule from the popup

  1. Click the Header toolbar icon.
  2. If you are on a normal website, its host is shown automatically. If you are on a page Chrome will not let extensions touch (for example chrome:// pages or the New Tab page), type the website into the box instead.
  3. Choose an operation, enter a header name (and value, for set/append), and optionally include subdomains.
  4. Click Add rule. Chrome will ask you to grant access to that site — approve it, and the rule becomes active.

Note: approving a site permission causes Chrome to close the popup. This is expected browser behavior; the rule is saved regardless, and it activates the moment you approve. Reopen the popup to see it listed.

Manage all rules

Open the options page (via Manage all rules in the popup, or the extension's Details page). There you can add, edit, enable/disable, and delete rules across all sites, grouped by host. Removing all of a site's rules — or using Remove site & access — revokes the extension's permission for that site.

Supported operations

Operation Effect Notes
Set Replaces the header, or adds it if absent. Works for any valid header name.
Append Adds a value to an existing multi-value header. Restricted by Chrome (see below).
Remove Removes the header from the request. Works for any valid header name.

The append restriction

Chrome only permits the append operation on a fixed allowlist of standard request headers that support multiple values in a single entry. When you choose Append, the header field becomes a dropdown limited to these headers:

accept, accept-encoding, accept-language, access-control-request-headers, cache-control, connection, content-language, cookie, forwarded, if-match, if-none-match, keep-alive, range, te, trailer, transfer-encoding, upgrade, user-agent, via, want-digest, x-forwarded-for.

For any other header, use Set instead. This mirrors Chrome's own declarativeNetRequest validation, so rules never fail silently.

Permissions explained

Permission Why it is needed
declarativeNetRequestWithHostAccess Apply header rules, but only to sites you have granted access to. This is the privacy-preserving variant; it does not permit reading traffic.
storage Persist your rules locally (chrome.storage.local).
activeTab Read the current tab's host when you open the popup, so it can prefill the site.
optional_host_permissions: *://*/* Lets the extension request access to any site you choose — but only at the moment you add a rule, and only for that specific site. No site access is granted at install time.

A note on the broad optional pattern: declaring *://*/* as optional is what makes per-site, ask-first access possible for arbitrary websites. It does not grant blanket access. If you ever set the extension's site access to "On all sites" from chrome://extensions, that is a manual choice you can revert there; the extension itself never asks for all sites at once.

How it works

  • Rules you create are stored as plain objects in chrome.storage.local.
  • The background service worker translates each enabled, permitted rule into a declarativeNetRequest dynamic rule and keeps Chrome's rule set in sync through a single reconcile() function.
  • A rule becomes active only when it is enabled and the extension currently holds host permission for its site. Invalid rules are skipped so a single bad rule cannot disable the rest.
  • Permission sync runs whenever rules change, on startup, and when the service worker wakes: any granted host permission no longer needed by a rule is released, and any newly granted permission activates its pending rules via chrome.permissions.onAdded.

Because the whole design is declarative, the extension has no code path that can observe the contents of a request or response.

Project structure

manifest.json         Extension manifest (MV3)
icons/                Toolbar and store icons (16/32/48/128)
src/
  background.js       Service worker: rule/permission reconciliation, messaging
  common.js           Shared model: validation, storage, rule/permission helpers
  ui.js               Shared rule-card renderer
  popup.html/.css/.js Popup: quick rules for the current or typed site
  options.html/.css/.js  Options: manage all rules grouped by site
  rules.css           Shared rule-card styling
tools/
  make_icons.py       Regenerates the PNG icons (Pillow)
  balance_check.py    Lightweight bracket-balance sanity check for the JS

Development

There is no build step or bundler; the extension runs the source directly.

  • Load it: follow Installation → From source.
  • Iterate: edit files under src/, then click the reload icon on the extension's card in chrome://extensions.
  • Inspect the background: on the extension card, use Inspect views: service worker to open its console and logs.
  • Regenerate icons: python3 tools/make_icons.py (requires Pillow).
  • Sanity-check the scripts: python3 tools/balance_check.py.

Roadmap

  • Response-header modification (behind clear warnings for security-sensitive headers such as CSP, CORS, HSTS, and Set-Cookie).
  • Import/export of rules.
  • Optional per-rule resource-type scoping.

Privacy policy

Header does not collect, transmit, or sell any data. All rules are stored locally on your device using chrome.storage.local and never leave your machine. The extension makes no network requests of its own and includes no analytics, tracking, or remote code. Host access is granted per site by you and can be revoked at any time from chrome://extensions or by deleting the rules for that site.

Contributing

Contributions are welcome. When proposing changes:

  • Keep the least-privilege model intact — do not introduce webRequest, declarativeNetRequestFeedback, or broad install-time host permissions.
  • Prefer small, dependency-free changes; the project intentionally ships without a build step.
  • Run python3 tools/balance_check.py and manually load the extension to verify the popup, options page, and permission flows before opening a pull request.

License

Released under the MIT License.

About

A Chrome extension for modifying **outgoing HTTP request headers** on a per-site basis, built around a strict least-privilege model: it can **set, append, or remove** headers, but it **cannot read** your headers or request bodies, and it gains access to a website only after you explicitly grant it — one site at a time.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages