mirror of
https://github.com/CyberMind-FR/secubox-deb.git
synced 2026-07-01 03:17:32 +00:00
Compare commits
No commits in common. "6160ec9aaae87779910eaf4acb93238648fa7cad" and "f69384f1e0cb84215540be2326713b76553829c1" have entirely different histories.
6160ec9aaa
...
f69384f1e0
|
|
@ -1,18 +1,3 @@
|
||||||
secubox-toolbox (2.6.56-1~bookworm1) bookworm; urgency=medium
|
|
||||||
|
|
||||||
* fix(#653): banner reliability — the injected loader now carries the
|
|
||||||
per-client bundle inline (`data-bundle` attr) and renders WITHOUT a second
|
|
||||||
`fetch('/__toolbox/bundle')`: faster (one less round-trip) and no
|
|
||||||
`connect-src` CSP dependency. Fetch retained as back-compat fallback.
|
|
||||||
* fix(#653): loader re-asserts the banner across SPA navigations
|
|
||||||
(pushState/replaceState/popstate) and if the DOM drops it — render() stays
|
|
||||||
idempotent (guards on #sbx-banner). NOTE: genuinely strict-CSP sites
|
|
||||||
(script-src 'none' / strict style-src) still can't be served from the page
|
|
||||||
without weakening their CSP — that's the browser-extension's job (separate),
|
|
||||||
we deliberately do NOT rewrite site CSP headers.
|
|
||||||
|
|
||||||
-- Gerald KERMA <devel@cybermind.fr> Thu, 18 Jun 2026 16:30:00 +0200
|
|
||||||
|
|
||||||
secubox-toolbox (2.6.55-1~bookworm1) bookworm; urgency=medium
|
secubox-toolbox (2.6.55-1~bookworm1) bookworm; urgency=medium
|
||||||
|
|
||||||
* perf(#651): broaden the media SNI-splice seed (11 → 35 video/image/audio
|
* perf(#651): broaden the media SNI-splice seed (11 → 35 video/image/audio
|
||||||
|
|
|
||||||
|
|
@ -702,20 +702,8 @@ def _stream_enabled() -> bool:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def _attr_escape(s: str) -> str:
|
|
||||||
"""Escape a string for an HTML double-quoted attribute value."""
|
|
||||||
return (s.replace("&", "&").replace("<", "<").replace(">", ">")
|
|
||||||
.replace('"', """).replace("'", "'"))
|
|
||||||
|
|
||||||
|
|
||||||
def _loader_script(flow) -> bytes:
|
def _loader_script(flow) -> bytes:
|
||||||
"""Tiny loader <script> tag carrying the client identity + WG flag.
|
"""Tiny loader <script> tag carrying the client identity + WG flag."""
|
||||||
|
|
||||||
#653 — inline the per-client bundle as a data- attribute so the loader
|
|
||||||
renders the banner WITHOUT a second `fetch('/__toolbox/bundle')`: faster
|
|
||||||
(one less round-trip) and no `connect-src` CSP dependency. Best-effort; the
|
|
||||||
loader falls back to the fetch path when the attribute is absent.
|
|
||||||
"""
|
|
||||||
mh, wg = "", "0"
|
mh, wg = "", "0"
|
||||||
try:
|
try:
|
||||||
ip = flow.client_conn.peername[0] if flow.client_conn.peername else None
|
ip = flow.client_conn.peername[0] if flow.client_conn.peername else None
|
||||||
|
|
@ -725,17 +713,8 @@ def _loader_script(flow) -> bytes:
|
||||||
mh = mac_hash_of(ip) or ""
|
mh = mac_hash_of(ip) or ""
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
bundle_attr = ""
|
tag = ('<script src="/__toolbox/loader.js" data-mh="%s" data-wg="%s" async></script>'
|
||||||
if _HAS_LEVEL:
|
% (mh, wg))
|
||||||
try:
|
|
||||||
import json as _json
|
|
||||||
from secubox_toolbox import bundle as _b
|
|
||||||
j = _json.dumps(_b.get_bundle(mh, wg == "1"), separators=(",", ":"))
|
|
||||||
bundle_attr = ' data-bundle="%s"' % _attr_escape(j)
|
|
||||||
except Exception:
|
|
||||||
bundle_attr = ""
|
|
||||||
tag = ('<script src="/__toolbox/loader.js" data-mh="%s" data-wg="%s"%s async></script>'
|
|
||||||
% (mh, wg, bundle_attr))
|
|
||||||
return b"<!-- " + _GUARD + b" -->" + tag.encode("ascii", "ignore")
|
return b"<!-- " + _GUARD + b" -->" + tag.encode("ascii", "ignore")
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -150,31 +150,9 @@ LOADER_JS = r"""(function(){
|
||||||
var btn = bar.querySelector("button");
|
var btn = bar.querySelector("button");
|
||||||
if (btn) btn.onclick = function(){ try { document.body.style.paddingTop = ""; } catch (_) {} bar.remove(); };
|
if (btn) btn.onclick = function(){ try { document.body.style.paddingTop = ""; } catch (_) {} bar.remove(); };
|
||||||
}
|
}
|
||||||
// #653 — re-assert the banner across SPA navigations / DOM wipes. render()
|
|
||||||
// is idempotent (guards on #sbx-banner), so re-calling is safe.
|
|
||||||
function setupReassert(b){
|
|
||||||
if (window.__SBX_REASSERT__) return; window.__SBX_REASSERT__ = 1;
|
|
||||||
function reassert(){ ready(function(){ if (!document.getElementById("sbx-banner")) render(b); }); }
|
|
||||||
["pushState","replaceState"].forEach(function(m){
|
|
||||||
var orig = history[m];
|
|
||||||
if (typeof orig === "function") {
|
|
||||||
history[m] = function(){ var r = orig.apply(this, arguments); setTimeout(reassert, 60); return r; };
|
|
||||||
}
|
|
||||||
});
|
|
||||||
window.addEventListener("popstate", function(){ setTimeout(reassert, 60); });
|
|
||||||
}
|
|
||||||
function go(b){ if (!b) return; ready(function(){ render(b); }); setupReassert(b); }
|
|
||||||
// #653 — prefer the inlined bundle (no fetch → faster, no connect-src dep);
|
|
||||||
// fall back to the fetch when the data- attribute is absent (back-compat).
|
|
||||||
var inb = null;
|
|
||||||
try { if (ds.bundle) inb = JSON.parse(ds.bundle); } catch (_) { inb = null; }
|
|
||||||
if (inb) {
|
|
||||||
go(inb);
|
|
||||||
} else {
|
|
||||||
fetch("/__toolbox/bundle?mh=" + encodeURIComponent(mh) + "&wg=" + encodeURIComponent(wg), {credentials:"omit"})
|
fetch("/__toolbox/bundle?mh=" + encodeURIComponent(mh) + "&wg=" + encodeURIComponent(wg), {credentials:"omit"})
|
||||||
.then(function(r){ return r.json(); })
|
.then(function(r){ return r.json(); })
|
||||||
.then(go)
|
.then(function(b){ ready(function(){ render(b); }); })
|
||||||
.catch(function(){});
|
.catch(function(){});
|
||||||
}
|
|
||||||
})();
|
})();
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
# SPDX-License-Identifier: LicenseRef-CMSD-1.0
|
|
||||||
import sys, pathlib, importlib, re
|
|
||||||
ADDON_DIR = pathlib.Path(__file__).resolve().parents[1] / "mitmproxy_addons"
|
|
||||||
sys.path.insert(0, str(ADDON_DIR))
|
|
||||||
from mitmproxy.test import tflow # noqa: E402
|
|
||||||
|
|
||||||
|
|
||||||
def test_attr_escape():
|
|
||||||
import inject_banner
|
|
||||||
assert inject_banner._attr_escape('a"b<c>&\'') == 'a"b<c>&''
|
|
||||||
|
|
||||||
|
|
||||||
def test_loader_script_inlines_bundle():
|
|
||||||
import inject_banner; importlib.reload(inject_banner)
|
|
||||||
out = inject_banner._loader_script(tflow.tflow()).decode("ascii", "ignore")
|
|
||||||
assert 'src="/__toolbox/loader.js"' in out
|
|
||||||
assert 'data-bundle="' in out # bundle inlined (no fetch needed)
|
|
||||||
m = re.search(r'data-bundle="([^"]*)"', out)
|
|
||||||
assert m and """ in m.group(1) # JSON quotes attr-escaped
|
|
||||||
|
|
||||||
|
|
||||||
def test_loader_js_uses_inline_then_fetch_fallback():
|
|
||||||
from secubox_toolbox import bundle
|
|
||||||
js = bundle.LOADER_JS
|
|
||||||
assert "ds.bundle" in js and "JSON.parse" in js # reads inlined bundle
|
|
||||||
assert "setupReassert" in js # SPA re-assert present
|
|
||||||
assert 'fetch("/__toolbox/bundle' in js # fetch retained as fallback
|
|
||||||
|
|
@ -48,11 +48,6 @@ def test_get_bundle_caches(monkeypatch):
|
||||||
|
|
||||||
|
|
||||||
def test_loader_js_is_served_string():
|
def test_loader_js_is_served_string():
|
||||||
# Initial render must NOT depend on a load/DOMContentLoaded event — it uses
|
assert "addEventListener" not in bundle.LOADER_JS # uses currentScript pattern
|
||||||
# currentScript + ready() polling so it works even when injected mid-stream.
|
assert "__toolbox/bundle" in bundle.LOADER_JS
|
||||||
# (#653: the popstate listener is for SPA re-assert, not initial render, so a
|
|
||||||
# blanket "no addEventListener" ban is too broad — assert the real intent.)
|
|
||||||
assert "DOMContentLoaded" not in bundle.LOADER_JS
|
|
||||||
assert 'addEventListener("load"' not in bundle.LOADER_JS
|
|
||||||
assert "__toolbox/bundle" in bundle.LOADER_JS # fetch retained as fallback
|
|
||||||
assert bundle.LOADER_JS.strip().startswith("(function()")
|
assert bundle.LOADER_JS.strip().startswith("(function()")
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user