A disabled extension was skipped before any lookup, on the reasoning that code
which does not execute is not a live risk. Wrong call: the vulnerable code is
still in the user's profile, and a click, a policy push or a profile sync puts
it back in the browser. Latent, not absent.
It also made the tool inconsistent with itself. Wazuh reports every installed
Linux kernel, including ones the machine has never booted, and nobody argues
those should be hidden for not running right now — same situation, same answer.
The finding carries the state in its name ("… [disabled]") so whoever picks it
up can weigh it, and enabled/disabled are tracked separately, so an extension
present in one profile and switched off in another shows both.
72 lines
3.2 KiB
Python
72 lines
3.2 KiB
Python
"""Browser extensions as their own product — run: python tests/test_browser_extensions.py
|
|
|
|
Nothing else inventories them: syscollector lists applications, not what runs
|
|
inside a browser. The Acrobat extension ships its own CVEs (CVE-2026-48294,
|
|
Chrome, up to 26.5.2.2) which therefore went nowhere — or, until c88eb45,
|
|
onto the desktop application, whose CPE NVD shares with it.
|
|
|
|
Data below is verbatim from the tester's IT Hygiene index.
|
|
"""
|
|
import os
|
|
import sys
|
|
|
|
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
|
|
from app.services.app_cve_scanner_service import _platform_ok, resolve_extension
|
|
|
|
# One row per real installation in the test estate.
|
|
FLEET = [
|
|
{"id": "efaidnbmnnnibpcajpcglclefindmkaj", "browser": "chrome",
|
|
"version": "23.8.1.0", "enabled": False, "agent": "n2"},
|
|
{"id": "efaidnbmnnnibpcajpcglclefindmkaj", "browser": "chrome",
|
|
"version": "25.5.4.1", "enabled": True, "agent": "555"},
|
|
{"id": "elhekieabhbkpmcefcoobjddigjcaadp", "browser": "edge",
|
|
"version": "26.7.1.0", "enabled": True, "agent": "17"},
|
|
{"id": "web2pdfextension.17@acrobat.adobe.com", "browser": "firefox",
|
|
"version": "18.0.10", "enabled": True, "agent": "555"},
|
|
]
|
|
|
|
|
|
def demo():
|
|
# Keyed by store id — the display name is localised and changes with
|
|
# marketing, the id does not.
|
|
chrome = resolve_extension(FLEET[0])
|
|
assert chrome["key"] == "ext:adobe:acrobat:chrome"
|
|
assert resolve_extension(FLEET[2])["key"] == "ext:adobe:acrobat:edge"
|
|
# Unknown extensions are ignored rather than guessed at, same rule as the
|
|
# package registry. The Firefox one has no CVEs on record yet.
|
|
assert resolve_extension(FLEET[3]) is None
|
|
assert resolve_extension({"id": "somethingelse"}) is None
|
|
|
|
# Chrome and Edge are separate keys — their versions are unrelated, so
|
|
# sharing a lookup would compare one store's numbering against the other's.
|
|
assert resolve_extension(FLEET[0])["key"] != resolve_extension(FLEET[2])["key"]
|
|
|
|
# target_sw here is the BROWSER. That field is the only thing separating
|
|
# the extension's CVEs from the desktop application's.
|
|
assert _platform_ok(["chrome"], "chrome") is True
|
|
assert _platform_ok(["chrome"], "edge") is False # Chrome CVE, Edge install
|
|
assert _platform_ok(["edge"], "edge") is True
|
|
assert _platform_ok(["*"], "chrome") is True
|
|
|
|
# A disabled extension IS reported. The code sits in the user's profile
|
|
# and one click puts it back in the browser — latent, not absent. Wazuh
|
|
# reports every installed Linux kernel for the same reason, booted or not.
|
|
# The name carries the state so the risk can still be judged.
|
|
off = FLEET[0]
|
|
assert off["enabled"] is False
|
|
entry = resolve_extension(off)
|
|
assert entry, "a disabled extension must still resolve to its product"
|
|
label = entry["label"] + (" [disabled]" if off.get("enabled") is False else "")
|
|
assert label.endswith(" [disabled]")
|
|
on = FLEET[2]
|
|
assert on["enabled"] is True
|
|
label_on = resolve_extension(on)["label"] + ("" if on.get("enabled") else " [disabled]")
|
|
assert "[disabled]" not in label_on
|
|
|
|
print("browser extensions OK")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
demo()
|