mirror of
https://github.com/CyberMind-FR/secubox-deb.git
synced 2026-06-30 10:00:52 +00:00
Compare commits
3 Commits
981acc4b44
...
2f6ca5478b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2f6ca5478b | ||
| 1d4b137dad | |||
| 90512da938 |
|
|
@ -1,3 +1,12 @@
|
|||
secubox-toolbox (2.6.49-1~bookworm1) bookworm; urgency=medium
|
||||
|
||||
* Banner fix (#639): inject the transparency banner only into top-level
|
||||
documents (Sec-Fetch-Dest: document, or absent for old UAs) — skip iframes
|
||||
/ sub-documents / sub-resources so a visit gets ONE banner, not one per
|
||||
frame. Gates both the stream_inject and legacy buffer paths.
|
||||
|
||||
-- Gerald KERMA <devel@cybermind.fr> Wed, 17 Jun 2026 21:00:00 +0200
|
||||
|
||||
secubox-toolbox (2.6.48-1~bookworm1) bookworm; urgency=medium
|
||||
|
||||
* R3 banner fix (#636): the mitm now serves /__toolbox/loader.js +
|
||||
|
|
|
|||
|
|
@ -404,6 +404,14 @@ def _detect_csp_strict(flow: http.HTTPFlow) -> bool:
|
|||
return False
|
||||
|
||||
|
||||
def _is_top_level_document(flow: http.HTTPFlow) -> bool:
|
||||
"""True if the response is a top-level navigation (so the banner belongs).
|
||||
Skip iframes/sub-documents/sub-resources so we inject ONE banner per visit.
|
||||
Sec-Fetch-Dest absent (old UAs) → assume top-level (best-effort, prior behavior)."""
|
||||
dest = (flow.request.headers.get("sec-fetch-dest", "") or "").lower()
|
||||
return dest in ("", "document")
|
||||
|
||||
|
||||
# Per-level visual theme (#545). R3 — and the planned R4 — get the
|
||||
# neon-tube treatment (dark glass bar, glowing tube border + neon
|
||||
# text-shadow). R2 keeps the original amber flat bar. All values are inline
|
||||
|
|
@ -800,6 +808,10 @@ class InjectBanner:
|
|||
# that survives strict CSP.
|
||||
if _detect_csp_strict(flow):
|
||||
return
|
||||
# #639 — only inject into top-level navigations; iframes/sub-documents
|
||||
# each get their own responseheaders call → multiple banners per visit.
|
||||
if not _is_top_level_document(flow):
|
||||
return
|
||||
try:
|
||||
resp.stream = _LoaderInjector(_loader_script(flow))
|
||||
flow.metadata["sbx_streamed"] = True
|
||||
|
|
@ -832,6 +844,10 @@ class InjectBanner:
|
|||
return
|
||||
except Exception:
|
||||
pass
|
||||
# #639 — only inject into top-level navigations; iframes/sub-documents
|
||||
# share the same buffer path and would each get a banner.
|
||||
if not _is_top_level_document(flow):
|
||||
return
|
||||
# Phase 10 perf : cheap pre-flight check on Content-Length to avoid
|
||||
# reading multi-MB bodies into RAM just to discover we'd skip them.
|
||||
# `flow.response.content` would buffer the whole body before returning.
|
||||
|
|
|
|||
48
packages/secubox-toolbox/tests/test_banner_toplevel.py
Normal file
48
packages/secubox-toolbox/tests/test_banner_toplevel.py
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
# SPDX-License-Identifier: LicenseRef-CMSD-1.0
|
||||
import sys, pathlib, importlib, json
|
||||
ADDON_DIR = pathlib.Path(__file__).resolve().parents[1] / "mitmproxy_addons"
|
||||
sys.path.insert(0, str(ADDON_DIR))
|
||||
|
||||
from mitmproxy.test import tflow, tutils # noqa: E402
|
||||
from secubox_toolbox import filters # noqa: E402
|
||||
|
||||
|
||||
def _addon(monkeypatch, tmp_path):
|
||||
fp = tmp_path / "filters.json"
|
||||
fp.write_text(json.dumps({"banner": True, "stream_inject": True}))
|
||||
monkeypatch.setattr(filters, "FILTERS_PATH", str(fp))
|
||||
filters.get_filters(force=True)
|
||||
import inject_banner
|
||||
importlib.reload(inject_banner)
|
||||
monkeypatch.setattr(inject_banner, "_client_level", lambda flow: "r3")
|
||||
return inject_banner
|
||||
|
||||
|
||||
def _html(dest=None):
|
||||
f = tflow.tflow(resp=tutils.tresp())
|
||||
f.response.headers["content-type"] = "text/html; charset=utf-8"
|
||||
f.response.status_code = 200
|
||||
if dest is not None:
|
||||
f.request.headers["sec-fetch-dest"] = dest
|
||||
return f
|
||||
|
||||
|
||||
def test_iframe_not_streamed(monkeypatch, tmp_path):
|
||||
ib = _addon(monkeypatch, tmp_path)
|
||||
f = _html(dest="iframe")
|
||||
ib.InjectBanner().responseheaders(f)
|
||||
assert not f.metadata.get("sbx_streamed") # iframe → no banner
|
||||
|
||||
|
||||
def test_document_streamed(monkeypatch, tmp_path):
|
||||
ib = _addon(monkeypatch, tmp_path)
|
||||
f = _html(dest="document")
|
||||
ib.InjectBanner().responseheaders(f)
|
||||
assert f.metadata.get("sbx_streamed") is True # top-level → banner
|
||||
|
||||
|
||||
def test_missing_dest_streamed(monkeypatch, tmp_path):
|
||||
ib = _addon(monkeypatch, tmp_path)
|
||||
f = _html(dest=None)
|
||||
ib.InjectBanner().responseheaders(f)
|
||||
assert f.metadata.get("sbx_streamed") is True # absent → assume top-level
|
||||
Loading…
Reference in New Issue
Block a user