mirror of
https://github.com/Anarios/return-youtube-dislike.git
synced 2026-10-28 07:44:31 +01:00
5d01972c3c
Refresh workflow CA trust and add an opt-in filtered Node launcher. Preserve inherited TLS settings in website commands and set the native language for Linux locale tests. Validated with hosted lint, 2351 Jest tests, 112 extension browser tests, 151 userscript browser tests, generated-artifact checks, and successful browser artifact builds.
177 lines
7.3 KiB
JavaScript
177 lines
7.3 KiB
JavaScript
/** @jest-environment node */
|
|
const fs = require("node:fs");
|
|
const path = require("node:path");
|
|
const tls = require("node:tls");
|
|
const { X509Certificate } = require("node:crypto");
|
|
const { spawnSync } = require("node:child_process");
|
|
const { filterCertificates, readCertificates, prepareEnvironment, main } = require("./with-trusted-node.cjs");
|
|
|
|
const root = path.resolve(__dirname, "../.private/node-trust-tests");
|
|
const blocked = tls.rootCertificates.find((pem) =>
|
|
new X509Certificate(pem).subject.includes("CN=AAA Certificate Services"),
|
|
);
|
|
const allowed = tls.rootCertificates.filter(
|
|
(pem) => !new X509Certificate(pem).subject.includes("emSign") && pem !== blocked,
|
|
);
|
|
const npmConfig = { ca: null, cafile: null, strictSsl: true, nodeOptions: null };
|
|
let temporary;
|
|
|
|
beforeEach(() => {
|
|
fs.mkdirSync(root, { recursive: true });
|
|
temporary = fs.mkdtempSync(path.join(root, "run-"));
|
|
});
|
|
|
|
afterEach(() => {
|
|
const resolved = fs.realpathSync(temporary);
|
|
expect(path.dirname(resolved)).toBe(fs.realpathSync(root));
|
|
fs.rmSync(resolved, { recursive: true, force: true });
|
|
});
|
|
|
|
test("excludes an affected root by public key and retains unrelated roots without duplicates", () => {
|
|
expect(blocked).toBeDefined();
|
|
const result = filterCertificates([allowed[0], blocked, allowed[0]]);
|
|
expect(result).toBe(new X509Certificate(allowed[0]).toString());
|
|
expect(() => filterCertificates([blocked])).toThrow(/No trusted certificates/);
|
|
expect(() => filterCertificates(["invalid"])).toThrow();
|
|
});
|
|
|
|
test("preserves extra custom certificates absent from the default set and leaves the parent environment unchanged", () => {
|
|
const extra = path.join(temporary, "extra.pem");
|
|
fs.writeFileSync(extra, [allowed[1], blocked].join("\n"));
|
|
const original = { NODE_EXTRA_CA_CERTS: extra, NODE_OPTIONS: "--max-old-space-size=512", UNRELATED: "preserved" };
|
|
const env = prepareEnvironment(temporary, original, [allowed[0]]);
|
|
expect(readCertificates(env.SSL_CERT_FILE)).toHaveLength(2);
|
|
expect(fs.readFileSync(env.SSL_CERT_FILE, "utf8")).toContain(new X509Certificate(allowed[1]).toString().trim());
|
|
expect(fs.readFileSync(env.SSL_CERT_FILE, "utf8")).not.toContain(new X509Certificate(blocked).toString().trim());
|
|
expect(env.NODE_EXTRA_CA_CERTS).toBeUndefined();
|
|
expect(env.NODE_OPTIONS).toBe("--max-old-space-size=512 --use-openssl-ca");
|
|
expect(env.UNRELATED).toBe("preserved");
|
|
expect(fs.readdirSync(env.SSL_CERT_DIR)).toEqual([]);
|
|
expect(original).toEqual({
|
|
NODE_EXTRA_CA_CERTS: extra,
|
|
NODE_OPTIONS: "--max-old-space-size=512",
|
|
UNRELATED: "preserved",
|
|
});
|
|
});
|
|
|
|
test("filters npm-specific custom trust without adding it to other Node clients", () => {
|
|
const cafile = path.join(temporary, "custom.pem");
|
|
fs.writeFileSync(cafile, [allowed[1], blocked].join("\n"));
|
|
const env = prepareEnvironment(temporary, {}, [allowed[0]], {
|
|
...npmConfig,
|
|
cafile,
|
|
nodeOptions: "--max-old-space-size=512",
|
|
});
|
|
expect(fs.readFileSync(env.npm_config_cafile, "utf8")).toBe(new X509Certificate(allowed[1]).toString());
|
|
expect(fs.readFileSync(env.SSL_CERT_FILE, "utf8")).not.toContain(new X509Certificate(allowed[1]).toString().trim());
|
|
expect(env.npm_config_node_options).toBe("--max-old-space-size=512 --use-openssl-ca");
|
|
expect(env.npm_config_strict_ssl).toBe("true");
|
|
});
|
|
|
|
test.each([
|
|
{ NODE_OPTIONS: "--use-system-ca" },
|
|
{ NODE_OPTIONS: "--use_openssl_ca" },
|
|
{ NODE_OPTIONS: "--use-bundled-ca" },
|
|
{ NODE_OPTIONS: "--no-use-openssl-ca" },
|
|
{ NODE_OPTIONS: "--no_use_openssl_ca" },
|
|
{ NODE_OPTIONS: "--experimental-config-file=existing.json" },
|
|
{ NODE_OPTIONS: "--openssl-config=config.cnf" },
|
|
{ SSL_CERT_FILE: "existing.pem" },
|
|
{ SSL_CERT_DIR: "existing-directory" },
|
|
{ OPENSSL_CONF: "existing.cnf" },
|
|
{ NODE_USE_SYSTEM_CA: "1" },
|
|
{ NODE_TLS_REJECT_UNAUTHORIZED: "0" },
|
|
])("rejects unsupported trust overrides %p", (env) => {
|
|
expect(() => prepareEnvironment(temporary, env, [allowed[0]])).toThrow();
|
|
});
|
|
|
|
test.each([
|
|
{ ...npmConfig, strictSsl: false },
|
|
{ ...npmConfig, ca: "inline" },
|
|
])("rejects unsupported npm TLS configuration %p", (config) =>
|
|
expect(() => prepareEnvironment(temporary, {}, [allowed[0]], config)).toThrow(),
|
|
);
|
|
|
|
test.each(["--no-use-openssl-ca", "--no-use_openssl_ca"])("rejects npm lifecycle trust overrides %s", (nodeOptions) => {
|
|
expect(() => prepareEnvironment(temporary, {}, [allowed[0]], { ...npmConfig, nodeOptions })).toThrow();
|
|
});
|
|
|
|
test.each([
|
|
"--no-use-openssl-ca",
|
|
"--no-use_openssl_ca",
|
|
"--env-file=existing.env",
|
|
"--env-file-if-exists=existing.env",
|
|
"--experimental-config-file=existing.json",
|
|
"--experimental-default-config-file",
|
|
])("rejects child Node trust/configuration overrides %s", (option) => {
|
|
expect(() => main(["node", option, "-e", "process.exit(0)"])).toThrow(/CA-store/);
|
|
});
|
|
|
|
test.each(["--use-openssl-ca", "--no-use-openssl-ca", "--no-use_openssl_ca"])(
|
|
"rejects trust overrides on the wrapper's own Node process %s",
|
|
(option) => {
|
|
const env = { ...process.env };
|
|
for (const key of Object.keys(env)) {
|
|
if (/^(NODE_OPTIONS|SSL_CERT_FILE|SSL_CERT_DIR|NODE_EXTRA_CA_CERTS)$/i.test(key)) delete env[key];
|
|
}
|
|
const result = spawnSync(
|
|
process.execPath,
|
|
[option, path.join(__dirname, "with-trusted-node.cjs"), "node", "-e", "process.exit(0)"],
|
|
{ env, encoding: "utf8" },
|
|
);
|
|
expect(result.status).toBe(1);
|
|
expect(result.stderr).toContain("CA-store");
|
|
},
|
|
);
|
|
|
|
test("fails on incomplete custom bundles rather than silently dropping custom trust", () => {
|
|
const filename = path.join(temporary, "broken.pem");
|
|
fs.writeFileSync(filename, `${allowed[0]}\n-----BEGIN CERTIFICATE-----\nbroken`);
|
|
expect(() => readCertificates(filename)).toThrow(/incomplete/);
|
|
});
|
|
|
|
test.each([
|
|
"--prefix=Website",
|
|
"--userconfig=other.npmrc",
|
|
"-g",
|
|
"--cafile=other.pem",
|
|
"--ca=inline",
|
|
"--pref=Website",
|
|
])("rejects npm configuration-selection overrides %s before inspecting npm", (option) =>
|
|
expect(() => main(["npm", option, "test"])).toThrow(/Unsupported npm option/),
|
|
);
|
|
|
|
test("applies the replacement store in a native Node child and propagates its exit status", () => {
|
|
const env = { ...process.env };
|
|
for (const key of Object.keys(env)) {
|
|
if (/^(NODE_OPTIONS|SSL_CERT_FILE|SSL_CERT_DIR|NODE_EXTRA_CA_CERTS)$/i.test(key)) delete env[key];
|
|
}
|
|
const result = spawnSync(
|
|
process.execPath,
|
|
[path.join(__dirname, "with-trusted-node.cjs"), "node", "-e", "require('https').createServer(); process.exit(17)"],
|
|
{
|
|
env,
|
|
encoding: "utf8",
|
|
},
|
|
);
|
|
expect(result.stderr).toBe("");
|
|
expect(result.status).toBe(17);
|
|
});
|
|
|
|
test("reads real npm custom CA paths with spaces and lifecycle options without treating them as JSON", () => {
|
|
const cafile = path.join(temporary, "custom CA.pem");
|
|
fs.writeFileSync(cafile, [allowed[0], blocked].join("\n"));
|
|
const env = { ...process.env, npm_config_cafile: cafile, npm_config_node_options: "--max-old-space-size=256" };
|
|
for (const key of Object.keys(env)) {
|
|
if (/^(NODE_OPTIONS|SSL_CERT_FILE|SSL_CERT_DIR|NODE_EXTRA_CA_CERTS)$/i.test(key)) delete env[key];
|
|
}
|
|
const result = spawnSync(
|
|
process.execPath,
|
|
[path.join(__dirname, "with-trusted-node.cjs"), "npm", "--no-update-notifier", "--version"],
|
|
{ env, encoding: "utf8" },
|
|
);
|
|
expect(result.stderr).toBe("");
|
|
expect(result.status).toBe(0);
|
|
expect(result.stdout.trim()).toMatch(/^\d+\.\d+\.\d+$/);
|
|
});
|