@dshn/agent 0.3.1 → 0.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.js +24 -6
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -4624,7 +4624,15 @@ var SHIM_BODY = String.raw`
|
|
|
4624
4624
|
let resolveReady
|
|
4625
4625
|
const ready = new Promise((r) => { resolveReady = r })
|
|
4626
4626
|
const hexToBytes = (hx) => { const a = new Uint8Array(hx.length / 2); for (let i = 0; i < a.length; i++) a[i] = parseInt(hx.substr(i * 2, 2), 16); return a }
|
|
4627
|
-
|
|
4627
|
+
// Same host as the page, over http(s) OR ws(s). A wss: URL has the origin
|
|
4628
|
+
// "wss://host", which never equals the page's "https://host", so comparing
|
|
4629
|
+
// origins would leave every event socket undecrypted.
|
|
4630
|
+
const isApi = (url) => {
|
|
4631
|
+
try {
|
|
4632
|
+
const u = new URL(url, location.href)
|
|
4633
|
+
return u.host === location.host && /^(https?|wss?):$/.test(u.protocol) && u.pathname.startsWith('/api')
|
|
4634
|
+
} catch { return false }
|
|
4635
|
+
}
|
|
4628
4636
|
|
|
4629
4637
|
async function deriveKey(password, saltHex) {
|
|
4630
4638
|
const base = await crypto.subtle.importKey('raw', enc.encode(password), 'PBKDF2', false, ['deriveKey'])
|
|
@@ -4704,7 +4712,9 @@ var SHIM_BODY = String.raw`
|
|
|
4704
4712
|
: data instanceof Blob ? new Uint8Array(await data.arrayBuffer())
|
|
4705
4713
|
: new Uint8Array(await new Blob([data]).arrayBuffer())
|
|
4706
4714
|
const opened = await openBytes(key, raw)
|
|
4707
|
-
|
|
4715
|
+
// slice, not subarray: subarray(1).buffer is the WHOLE decrypted
|
|
4716
|
+
// buffer, type byte included, and would hand the app one extra byte.
|
|
4717
|
+
data = opened[0] === 0 ? new TextDecoder().decode(opened.subarray(1)) : opened.slice(1).buffer
|
|
4708
4718
|
} catch { return } // drop messages we can't decrypt
|
|
4709
4719
|
}
|
|
4710
4720
|
}
|
|
@@ -4838,6 +4848,13 @@ function e2eBootstrapTag(info) {
|
|
|
4838
4848
|
const json = JSON.stringify({ salt: info.salt, device: info.device }).replace(/</g, "\\u003c");
|
|
4839
4849
|
return `<script>(function (__dshnInfo) {${SHIM_BODY}})(${json})</script>`;
|
|
4840
4850
|
}
|
|
4851
|
+
function credentialManifestLinks(html) {
|
|
4852
|
+
return html.replace(/<link\b[^>]*>/gi, (tag) => {
|
|
4853
|
+
if (!/\brel\s*=\s*["']?manifest\b/i.test(tag) || /\bcrossorigin\b/i.test(tag))
|
|
4854
|
+
return tag;
|
|
4855
|
+
return tag.replace(/\s*\/?>$/, (end) => ` crossorigin="use-credentials"${end.trim() === "/>" ? " />" : ">"}`);
|
|
4856
|
+
});
|
|
4857
|
+
}
|
|
4841
4858
|
function injectE2EBootstrap(html, info) {
|
|
4842
4859
|
const tag = e2eBootstrapTag(info);
|
|
4843
4860
|
const head = /<head(\s[^>]*)?>/i.exec(html);
|
|
@@ -5615,16 +5632,17 @@ var AgentTunnel = class {
|
|
|
5615
5632
|
return;
|
|
5616
5633
|
}
|
|
5617
5634
|
const wantsDocument = method === "GET" && headers.some(([k, v]) => k.toLowerCase() === "accept" && v.includes("text/html"));
|
|
5618
|
-
|
|
5619
|
-
if (injectBootstrap)
|
|
5635
|
+
if (wantsDocument)
|
|
5620
5636
|
outHeaders["accept-encoding"] = "identity";
|
|
5621
5637
|
const req = http.request({ host: this.config.localHost, port: this.localPort(), method, path, headers: outHeaders }, (res) => {
|
|
5622
5638
|
const contentType = String(res.headers["content-type"] ?? "");
|
|
5623
|
-
if (
|
|
5639
|
+
if (wantsDocument && res.statusCode === 200 && /^text\/html\b/i.test(contentType)) {
|
|
5624
5640
|
const chunks = [];
|
|
5625
5641
|
res.on("data", (c) => chunks.push(c));
|
|
5626
5642
|
res.on("end", () => {
|
|
5627
|
-
|
|
5643
|
+
let html = credentialManifestLinks(Buffer.concat(chunks).toString("utf8"));
|
|
5644
|
+
if (this.e2eKey !== null)
|
|
5645
|
+
html = injectE2EBootstrap(html, { salt: this.e2eSalt, device: this.deviceId });
|
|
5628
5646
|
const body = Buffer.from(html, "utf8");
|
|
5629
5647
|
const resHeaders = filterHeaders(headerListFromRaw(res.rawHeaders), /* @__PURE__ */ new Set([...HOP_BY_HOP, "content-length", "content-encoding"]));
|
|
5630
5648
|
resHeaders.push(["content-length", String(body.length)]);
|