Skip to content

fix: skip Accept-Language injection for non-routable/local hosts#77

Merged
ormidales merged 3 commits into1.0.4from
copilot/fix-local-accept-language-header
Mar 5, 2026
Merged

fix: skip Accept-Language injection for non-routable/local hosts#77
ormidales merged 3 commits into1.0.4from
copilot/fix-local-accept-language-header

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 5, 2026

The onBeforeSendHeaders handler was unconditionally spoofing Accept-Language on all HTTP(S) requests, including localhost, .local domains, and private IP ranges — breaking localization tests in local dev environments with no privacy benefit.

Changes

  • New isNonRoutableHost(hostname) helper — returns true for:

    • localhost and *.local hostnames
    • IPv4 unspecified (0.0.0.0), loopback (127.x.x.x), private RFC 1918 (10.*, 172.16–31.*, 192.168.*), and link-local (169.254.*)
    • IPv6 loopback (::1), link-local (fe80::), and unique-local ULA (fc00::/7)
  • Early-return guard in onBeforeSendHeaders — placed after the existing exceptionDomains check:

if (isNonRoutableHost(host)) {
  return {};
}

Requests to local or non-routable addresses pass through unmodified, preserving the browser's native Accept-Language.

Original prompt

This section details on the original issue you should resolve

<issue_title>Injection inutile de l'en-tête Accept-Language sur les requêtes locales</issue_title>
<issue_description>## Contexte
Le background.js intercepte les requêtes réseau (onBeforeSendHeaders) pour injecter un en-tête Accept-Language masqué en fonction du domaine de premier niveau (TLD) identifié.

Problème

La fonction buildAcceptLanguage applique par défaut en-US pour les hôtes inconnus, y compris localhost et les domaines finissant par .local. Cette altération systématique n'apporte aucune protection en matière de vie privée sur des environnements de développement locaux et peut casser des tests de localisation lors du développement d'applications web.

Scénario de Reproduction

  1. Lancer un serveur local répondant à http://localhost:3000.
  2. Consulter la page et inspecter les en-têtes de la requête entrante sur le serveur.
  3. Constater que Accept-Language a été forcé à en-US,en;q=0.9 au lieu de conserver la configuration par défaut du navigateur.

Comportement Attendu

L'extension ne doit pas modifier l'en-tête Accept-Language si le domaine est localhost, se termine par .local, ou correspond à une adresse IP locale non routable.

Pistes Techniques

Fichier concerné : background.js.
Dans browser.webRequest.onBeforeSendHeaders.addListener, ajouter une vérification pour les environnements de loopback avant la modification des requestHeaders.</issue_description>

Comments on the Issue (you are @copilot in this section)


🔒 GitHub Advanced Security automatically protects Copilot coding agent pull requests. You can protect all pull requests by enabling Advanced Security for your repositories. Learn more about Advanced Security.

Co-authored-by: ormidales <46538211+ormidales@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix unnecessary injection of Accept-Language header on local requests fix: skip Accept-Language injection for local/loopback hosts Mar 5, 2026
@ormidales ormidales added this to the v1.0.4 milestone Mar 5, 2026
@ormidales ormidales marked this pull request as ready for review March 5, 2026 09:13
Copilot AI review requested due to automatic review settings March 5, 2026 09:13
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR prevents the extension’s onBeforeSendHeaders handler from spoofing Accept-Language on local/non-routable destinations (e.g., localhost and private address space), preserving normal browser locale behavior in local dev environments.

Changes:

  • Adds an isLocalHost(hostname) helper to detect localhost / .local and various non-routable IP ranges.
  • Adds an early-return guard in onBeforeSendHeaders to skip header mutation when the request host is local.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread background.js
parts[0] === 10 ||
(parts[0] === 172 && parts[1] >= 16 && parts[1] <= 31) ||
(parts[0] === 192 && parts[1] === 168) ||
(parts[0] === 169 && parts[1] === 254)
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isLocalHost does not treat 0.0.0.0 (IPv4 “unspecified” address commonly used as a localhost alias in dev URLs) as local/non-routable, so Accept-Language spoofing would still apply for http://0.0.0.0:… and can continue to break local localization tests. Consider including 0.* (or at least 0.0.0.0) in the IPv4 early-return set if the intent is to skip all non-routable/local destinations.

Suggested change
(parts[0] === 169 && parts[1] === 254)
(parts[0] === 169 && parts[1] === 254) ||
(parts[0] === 0 && parts[1] === 0 && parts[2] === 0 && parts[3] === 0)

Copilot uses AI. Check for mistakes.
Comment thread background.js
Comment on lines +49 to +76
/**
* Returns true if the hostname is a local or non-routable address that should
* not have its Accept-Language header modified.
* Covers: localhost, .local TLD, loopback/private IPv4, loopback/link-local IPv6.
* @param {string} hostname Hostname to test.
* @returns {boolean}
*/
const isLocalHost = (hostname) => {
if (!hostname) return false;
const h = hostname.toLowerCase();

if (h === "localhost" || h.endsWith(".local")) return true;

if (IPV4_REGEX.test(h)) {
const parts = h.split(".").map(Number);
return (
parts[0] === 127 ||
parts[0] === 10 ||
(parts[0] === 172 && parts[1] >= 16 && parts[1] <= 31) ||
(parts[0] === 192 && parts[1] === 168) ||
(parts[0] === 169 && parts[1] === 254)
);
}

if (IPV6_REGEX.test(h)) {
const bare = h.replace(/^\[|\]$/g, "").split("%")[0].toLowerCase();
return bare === "::1" || bare.startsWith("fe80:") || bare.startsWith("fc") || bare.startsWith("fd");
}
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The JSDoc/summary says IPv6 handling covers only loopback/link-local, but the implementation also treats ULA (fc00::/7 via fc/fd) as local. Please update the comment to match the actual behavior (or narrow the behavior to match the documented scope).

Copilot uses AI. Check for mistakes.
Comment thread background.js Outdated
Comment on lines +56 to +60
const isLocalHost = (hostname) => {
if (!hostname) return false;
const h = hostname.toLowerCase();

if (h === "localhost" || h.endsWith(".local")) return true;
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The helper name isLocalHost is a bit misleading since it returns true for private RFC1918 ranges and IPv6 ULA as well, not just localhost/loopback. Consider renaming to something like isLocalOrPrivateHost / isNonRoutableHost to better reflect what it matches.

Copilot uses AI. Check for mistakes.
@ormidales
Copy link
Copy Markdown
Owner

@copilot apply changes based on the comments in this thread

Co-authored-by: ormidales <46538211+ormidales@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 5, 2026

@copilot apply changes based on the comments in this thread

Applied all three review suggestions in commit 09d5fec:

  • Renamed isLocalHostisNonRoutableHost to better reflect its scope (covers localhost, private RFC 1918, link-local, and ULA ranges — not just loopback).
  • Added parts[0] === 0 to the IPv4 check to treat 0.0.0.0 (unspecified address) as non-routable.
  • Updated the JSDoc to accurately list all covered cases, including ULA (fc00::/7).

Copilot AI changed the title fix: skip Accept-Language injection for local/loopback hosts fix: skip Accept-Language injection for non-routable/local hosts Mar 5, 2026
@ormidales ormidales merged commit b6e2668 into 1.0.4 Mar 5, 2026
@ormidales ormidales deleted the copilot/fix-local-accept-language-header branch March 5, 2026 09:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Injection inutile de l'en-tête Accept-Language sur les requêtes locales

3 participants