mirror of
https://github.com/CyberMind-FR/secubox-deb.git
synced 2026-07-29 09:14:33 +00:00
- Cookie relay now pokes the avatar credential broker (/api/v1/avatar/cred/poke/youtube, JSON) instead of the PeerTube-specific endpoint — one broker for all services (#402). - content/yt-hook.js (page world) + yt-capture.js (content script): hook YouTube's fetch/XHR to capture the `pot` PO token + visitor_data, stash in extension storage; the relay sends them alongside cookies. EXPERIMENTAL — YouTube obfuscates/rotates these, best-effort (P4). - manifest: content_scripts on youtube.com + web_accessible yt-hook.js.
This commit is contained in:
parent
b9c9b918cc
commit
1dd540e86a
22
packages/secubox-webext/content/yt-capture.js
Normal file
22
packages/secubox-webext/content/yt-capture.js
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
// SecuBox Companion — YouTube PO-token capture (content script, isolated world)
|
||||
// Injects a page-world hook that watches YouTube's own streaming requests for
|
||||
// the `pot` (PO token) param + visitor_data, and stashes them in extension
|
||||
// storage so the popup can relay them to the avatar broker (#402 / #401 P4).
|
||||
// EXPERIMENTAL: YouTube obfuscates + rotates these; best-effort only.
|
||||
const api = globalThis.browser ?? globalThis.chrome;
|
||||
|
||||
try {
|
||||
const s = document.createElement("script");
|
||||
s.src = api.runtime.getURL("content/yt-hook.js");
|
||||
s.async = false;
|
||||
(document.head || document.documentElement).appendChild(s);
|
||||
s.remove();
|
||||
} catch (e) { /* page CSP may block; nothing we can do */ }
|
||||
|
||||
window.addEventListener("message", (e) => {
|
||||
if (e.source !== window || !e.data || e.data.__secubox !== "yt-pot") return;
|
||||
const upd = {};
|
||||
if (e.data.po_token) { upd.yt_po_token = e.data.po_token; upd.yt_po_token_at = Date.now(); }
|
||||
if (e.data.visitor_data) upd.yt_visitor_data = e.data.visitor_data;
|
||||
if (Object.keys(upd).length) api.storage.local.set(upd);
|
||||
});
|
||||
47
packages/secubox-webext/content/yt-hook.js
Normal file
47
packages/secubox-webext/content/yt-hook.js
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
// SecuBox Companion — YouTube PO-token hook (runs in the PAGE/main world).
|
||||
// Wraps fetch + XHR to spot YouTube's streaming requests, which carry the
|
||||
// `pot` (PO token) query param. Relays it (+ visitor_data from ytcfg) to the
|
||||
// content script via window.postMessage. EXPERIMENTAL + YouTube-fragile.
|
||||
(function () {
|
||||
"use strict";
|
||||
let lastSent = "";
|
||||
|
||||
function visitorData() {
|
||||
try {
|
||||
if (window.ytcfg && typeof window.ytcfg.get === "function") {
|
||||
return window.ytcfg.get("VISITOR_DATA") || "";
|
||||
}
|
||||
if (window.ytcfg && window.ytcfg.data_) return window.ytcfg.data_.VISITOR_DATA || "";
|
||||
} catch (e) { /* ignore */ }
|
||||
return "";
|
||||
}
|
||||
|
||||
function grab(url) {
|
||||
if (!url) return;
|
||||
try {
|
||||
const u = new URL(url, location.href);
|
||||
if (!/(googlevideo\.com|youtube\.com)/.test(u.hostname)) return;
|
||||
const pot = u.searchParams.get("pot");
|
||||
if (pot && pot.length > 20 && pot !== lastSent) {
|
||||
lastSent = pot;
|
||||
window.postMessage(
|
||||
{ __secubox: "yt-pot", po_token: pot, visitor_data: visitorData() }, "*");
|
||||
}
|
||||
} catch (e) { /* ignore */ }
|
||||
}
|
||||
|
||||
try {
|
||||
const origFetch = window.fetch;
|
||||
if (origFetch) {
|
||||
window.fetch = function (input) {
|
||||
try { grab(typeof input === "string" ? input : (input && input.url)); } catch (e) {}
|
||||
return origFetch.apply(this, arguments);
|
||||
};
|
||||
}
|
||||
const origOpen = XMLHttpRequest.prototype.open;
|
||||
XMLHttpRequest.prototype.open = function (method, url) {
|
||||
try { grab(url); } catch (e) {}
|
||||
return origOpen.apply(this, arguments);
|
||||
};
|
||||
} catch (e) { /* ignore */ }
|
||||
})();
|
||||
|
|
@ -22,6 +22,20 @@
|
|||
"background": {
|
||||
"scripts": ["background.js"]
|
||||
},
|
||||
"content_scripts": [
|
||||
{
|
||||
"matches": ["https://www.youtube.com/*"],
|
||||
"js": ["content/yt-capture.js"],
|
||||
"run_at": "document_start",
|
||||
"all_frames": true
|
||||
}
|
||||
],
|
||||
"web_accessible_resources": [
|
||||
{
|
||||
"resources": ["content/yt-hook.js"],
|
||||
"matches": ["https://www.youtube.com/*"]
|
||||
}
|
||||
],
|
||||
"options_ui": {
|
||||
"page": "options/options.html",
|
||||
"open_in_tab": true
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ const api = globalThis.browser ?? globalThis.chrome;
|
|||
const DEFAULTS = {
|
||||
hubBase: "",
|
||||
modules: ["hub", "crowdsec", "waf", "wireguard", "peertube", "photoprism", "nextcloud"],
|
||||
cookieEndpoint: "/api/v1/peertube/import/cookies",
|
||||
cookieEndpoint: "/api/v1/avatar/cred/poke/youtube",
|
||||
};
|
||||
|
||||
async function load() {
|
||||
|
|
|
|||
|
|
@ -5,8 +5,9 @@ const DEFAULTS = {
|
|||
hubBase: "", // e.g. "https://admin.gk2.secubox.in"
|
||||
// Modules to probe (name shown + URL slug). Operator can edit in options.
|
||||
modules: ["hub", "crowdsec", "waf", "wireguard", "peertube", "photoprism", "nextcloud"],
|
||||
// PeerTube cookie-intake endpoint (backend lands with #401 P1.5 / #388).
|
||||
cookieEndpoint: "/api/v1/peertube/import/cookies",
|
||||
// Avatar credential-broker poke endpoint (#402): one place to share browser
|
||||
// auth with any backend service. youtube → PeerTube.
|
||||
cookieEndpoint: "/api/v1/avatar/cred/poke/youtube",
|
||||
// SecuBox login endpoint (secubox-core JWT; any module's /auth/login works).
|
||||
loginEndpoint: "/api/v1/peertube/auth/login",
|
||||
};
|
||||
|
|
@ -101,11 +102,19 @@ async function relayCookies(cfg) {
|
|||
status.textContent = "No youtube.com cookies — log into YouTube in this browser first.";
|
||||
return;
|
||||
}
|
||||
const body = toNetscape(cookies);
|
||||
status.textContent = `Sending ${cookies.length} cookies…`;
|
||||
const netscape = toNetscape(cookies);
|
||||
// Optional PO token captured from a youtube.com tab (P4, experimental).
|
||||
const { yt_po_token = "", yt_visitor_data = "" } = await api.storage.local.get(
|
||||
{ yt_po_token: "", yt_visitor_data: "" });
|
||||
status.textContent = `Poking ${cookies.length} cookies` + (yt_po_token ? " + PO token" : "") + "…";
|
||||
const r = await fetch(`${cfg.hubBase}${cfg.cookieEndpoint}`, {
|
||||
method: "POST", credentials: "include",
|
||||
headers: { "Content-Type": "text/plain", ...(await authHeaders()) }, body,
|
||||
headers: { "Content-Type": "application/json", ...(await authHeaders()) },
|
||||
body: JSON.stringify({
|
||||
cookies: netscape,
|
||||
po_token: yt_po_token || undefined,
|
||||
visitor_data: yt_visitor_data || undefined,
|
||||
}),
|
||||
});
|
||||
if (r.status === 401 || r.status === 403) {
|
||||
status.textContent = "SecuBox login required:";
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user