From c0ecda69c10e222a72a9f1ed1b3a5c4216d12875 Mon Sep 17 00:00:00 2001 From: zhom <2717306+zhom@users.noreply.github.com> Date: Fri, 31 Jul 2026 22:15:56 +0400 Subject: [PATCH] chore: linting --- e2e/lib/app.mjs | 4 ++-- e2e/tests/entities.test.mjs | 12 +++++++++++- e2e/tests/network.test.mjs | 12 +++++++++--- scripts/generate-licenses.mjs | 11 ++++++++--- src-tauri/src/remote_session.rs | 19 ++++++++++--------- 5 files changed, 40 insertions(+), 18 deletions(-) diff --git a/e2e/lib/app.mjs b/e2e/lib/app.mjs index 2cea3b6..1459b42 100644 --- a/e2e/lib/app.mjs +++ b/e2e/lib/app.mjs @@ -485,7 +485,7 @@ export class AppSession { // The validated response is intentionally persisted in an isolated test directory. await writeFile( path.join(this.root, "artifacts", `${safe}.png`), - artifact, // codeql[js/http-to-file-access] + artifact, ); } catch { // Best-effort diagnostics must never hide the original test failure. @@ -495,7 +495,7 @@ export class AppSession { // Escaping makes the saved HTML inert while preserving it for diagnostics. await writeFile( path.join(this.root, "artifacts", `${safe}.html`), - artifact, // codeql[js/http-to-file-access] + artifact, ); } catch { // Best-effort diagnostics must never hide the original test failure. diff --git a/e2e/tests/entities.test.mjs b/e2e/tests/entities.test.mjs index 921de07..3613bb2 100644 --- a/e2e/tests/entities.test.mjs +++ b/e2e/tests/entities.test.mjs @@ -364,10 +364,20 @@ test("extensions, extension groups, VPN storage, DNS rules, and event-backed ass allowlistMode: false, }); assert.deepEqual(dns.block_domains, ["ads.example.com", "tracker.example"]); + assert.deepEqual(dns.allow_domains, ["safe.example"]); const textExport = await app.invoke("export_custom_dns_rules", { format: "txt", }); - assert.match(textExport, /ads\.example\.com/); + assert.equal( + textExport, + [ + `! source: ${process.env.DONUT_E2E_FIXTURE_URL}/dns.txt`, + "@@safe.example", + "ads.example.com", + "tracker.example", + "", + ].join("\n"), + ); await app.invoke("import_custom_dns_rules", { format: "txt", content: "||malware.example^\n@@||allowed.example^\n", diff --git a/e2e/tests/network.test.mjs b/e2e/tests/network.test.mjs index 5966cbf..b5fb03a 100644 --- a/e2e/tests/network.test.mjs +++ b/e2e/tests/network.test.mjs @@ -436,6 +436,12 @@ async function createXrayProfile(app, version) { }); } +// Matches a whole Xray-core access log line whose destination is exactly +// api.ipify.org:443 ("... accepted tcp:api.ipify.org:443 [outbound]"). The +// leading delimiter keeps a lookalike host such as notapi.ipify.org:443 from +// passing the assertion. +const XRAY_ACCESS_LOG_TARGET = /^.*[\s:]api\.ipify\.org:443(?:\s.*)?$/; + test("VLESS Reality persists, imports, routes through Xray-core, records traffic, and cleans up", async () => { const vlessUri = process.env.DONUT_E2E_VLESS_URI; const accessLog = process.env.DONUT_E2E_XRAY_ACCESS_LOG; @@ -654,9 +660,9 @@ test("VLESS Reality persists, imports, routes through Xray-core, records traffic await app.waitFor( async () => - (await readFile(accessLog, "utf8").catch(() => "")).includes( - "api.ipify.org:443", - ), + (await readFile(accessLog, "utf8").catch(() => "")) + .split("\n") + .some((line) => XRAY_ACCESS_LOG_TARGET.test(line)), { timeoutMs: 15_000, description: "request in Xray-core server access log", diff --git a/scripts/generate-licenses.mjs b/scripts/generate-licenses.mjs index 57bb6a8..bcfe18e 100644 --- a/scripts/generate-licenses.mjs +++ b/scripts/generate-licenses.mjs @@ -152,12 +152,17 @@ export function prepareLicenseInventory(entries) { } function commandOutput(command, args) { - const executable = - process.platform === "win32" && command === "pnpm" ? "pnpm.cmd" : command; - return execFileSync(executable, args, { + // pnpm ships only a `pnpm.cmd` batch shim on Windows, and Node refuses to + // spawn batch files without a shell (CVE-2024-27980), so `execFileSync` + // fails with EINVAL there. Every argument below is a literal from this file, + // so routing that one call through cmd.exe interpolates nothing. + const needsShell = process.platform === "win32" && command === "pnpm"; + return execFileSync(needsShell ? "pnpm.cmd" : command, args, { cwd: PROJECT_ROOT, encoding: "utf8", maxBuffer: MAX_COMMAND_OUTPUT, + shell: needsShell, + windowsHide: true, }); } diff --git a/src-tauri/src/remote_session.rs b/src-tauri/src/remote_session.rs index e0a7d00..e0b661b 100644 --- a/src-tauri/src/remote_session.rs +++ b/src-tauri/src/remote_session.rs @@ -74,11 +74,12 @@ pub fn classify_backend_status(status: u16, body: &str) -> RemoteSessionError { /// Build the idempotency key for one launch attempt. /// -/// Derived from the profile and a caller-supplied nonce rather than random, so -/// a retry of the SAME user action de-duplicates while a genuinely new launch -/// does not. -pub fn idempotency_key(profile_id: &str, nonce: &str) -> String { - format!("run-remote:{profile_id}:{nonce}") +/// Derived from the profile and a caller-supplied attempt id rather than +/// random, so a retry of the SAME user action de-duplicates while a genuinely +/// new launch does not. The attempt id is a plain uniqueness token, not a +/// cryptographic value. +pub fn idempotency_key(profile_id: &str, attempt: &str) -> String { + format!("run-remote:{profile_id}:{attempt}") } /// Ask donutbrowser-infra to start a remote session for this profile. @@ -224,9 +225,9 @@ mod tests { #[test] fn idempotency_key_is_stable_for_one_attempt_and_distinct_across_attempts() { - let a = idempotency_key("p1", "nonce-1"); - assert_eq!(a, idempotency_key("p1", "nonce-1")); - assert_ne!(a, idempotency_key("p1", "nonce-2")); - assert_ne!(a, idempotency_key("p2", "nonce-1")); + let a = idempotency_key("p1", "attempt-1"); + assert_eq!(a, idempotency_key("p1", "attempt-1")); + assert_ne!(a, idempotency_key("p1", "attempt-2")); + assert_ne!(a, idempotency_key("p2", "attempt-1")); } }