Files
bun.sh/test/js/node/tls/test-system-ca-https.test.ts
Ciro Spaciari 7798e6638b Implement NODE_USE_SYSTEM_CA with --use-system-ca CLI flag (#22441)
### What does this PR do?
Resume work on https://github.com/oven-sh/bun/pull/21898
### How did you verify your code works?
Manually tested on MacOS, Windows 11 and Ubuntu 25.04. CI changes are
needed for the tests

---------

Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2025-09-24 21:55:57 -07:00

150 lines
4.8 KiB
TypeScript

import { spawn } from "bun";
import { describe, expect, test } from "bun:test";
import { readFileSync } from "fs";
import { bunEnv, bunExe, tempDirWithFiles } from "harness";
// Gate network tests behind environment variable to avoid CI flakes
// TODO: Replace with hermetic local TLS fixtures in a follow-up
const networkTest = process.env.BUN_TEST_ALLOW_NET === "1" ? test : test.skip;
describe("system CA with HTTPS", () => {
// Skip test if no system certificates are available
const skipIfNoSystemCerts = () => {
if (process.platform === "linux") {
// Check if common certificate paths exist on Linux
const certPaths = [
"/etc/ssl/certs/ca-certificates.crt",
"/etc/pki/tls/certs/ca-bundle.crt",
"/etc/ssl/ca-bundle.pem",
"/etc/pki/tls/cacert.pem",
"/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem",
];
const hasSystemCerts = certPaths.some(path => {
try {
readFileSync(path);
return true;
} catch {
return false;
}
});
if (!hasSystemCerts) {
return "no system certificates available on Linux";
}
}
return null;
};
networkTest("HTTPS request with system CA", async () => {
const skipReason = skipIfNoSystemCerts();
if (skipReason) {
test.skip(skipReason);
return;
}
// Test that we can make HTTPS requests to well-known sites with system CA
const testCode = `
const https = require('https');
// Test against a well-known HTTPS endpoint
https.get('https://www.google.com', (res) => {
console.log('STATUS:', res.statusCode);
process.exit(res.statusCode === 200 || res.statusCode === 301 || res.statusCode === 302 ? 0 : 1);
}).on('error', (err) => {
console.error('ERROR:', err.message);
process.exit(1);
});
`;
const dir = tempDirWithFiles("test-system-ca", {
"test.js": testCode,
});
// Test with --use-system-ca flag
await using proc1 = spawn({
cmd: [bunExe(), "--use-system-ca", "test.js"],
env: bunEnv,
cwd: dir,
stdout: "pipe",
stderr: "pipe",
});
const [stdout1, stderr1, exitCode1] = await Promise.all([proc1.stdout.text(), proc1.stderr.text(), proc1.exited]);
expect(exitCode1).toBe(0);
expect(stdout1).toContain("STATUS:");
// Test with NODE_USE_SYSTEM_CA=1
await using proc2 = spawn({
cmd: [bunExe(), "test.js"],
env: { ...bunEnv, NODE_USE_SYSTEM_CA: "1" },
cwd: dir,
stdout: "pipe",
stderr: "pipe",
});
const [stdout2, stderr2, exitCode2] = await Promise.all([proc2.stdout.text(), proc2.stderr.text(), proc2.exited]);
expect(exitCode2).toBe(0);
expect(stdout2).toContain("STATUS:");
});
networkTest("HTTPS fails without system CA for custom root cert", async () => {
// This test verifies that without system CA, connections to sites
// with certificates not in the bundled list will fail
const testCode = `
const https = require('https');
// Test against a site that typically uses a custom or less common CA
// Using a government site as they often have their own CAs
https.get('https://www.irs.gov', (res) => {
console.log('SUCCESS');
process.exit(0);
}).on('error', (err) => {
if (err.code === 'UNABLE_TO_VERIFY_LEAF_SIGNATURE' ||
err.code === 'CERT_HAS_EXPIRED' ||
err.code === 'SELF_SIGNED_CERT_IN_CHAIN' ||
err.message.includes('certificate')) {
console.log('CERT_ERROR');
process.exit(1);
}
// Other errors (network, DNS, etc)
console.error('OTHER_ERROR:', err.code);
process.exit(2);
});
`;
const dir = tempDirWithFiles("test-no-system-ca", {
"test.js": testCode,
});
// Test WITHOUT system CA - might fail for some sites
await using proc1 = spawn({
cmd: [bunExe(), "test.js"],
env: { ...bunEnv, NODE_USE_SYSTEM_CA: "0" },
cwd: dir,
stdout: "pipe",
stderr: "pipe",
});
const [stdout1, stderr1, exitCode1] = await Promise.all([proc1.stdout.text(), proc1.stderr.text(), proc1.exited]);
// This might succeed or fail depending on whether the site's CA is bundled
// We just verify the test runs without crashing
expect([0, 1, 2]).toContain(exitCode1);
// Test WITH system CA - should have better success rate
await using proc2 = spawn({
cmd: [bunExe(), "--use-system-ca", "test.js"],
env: bunEnv,
cwd: dir,
stdout: "pipe",
stderr: "pipe",
});
const [stdout2, stderr2, exitCode2] = await Promise.all([proc2.stdout.text(), proc2.stderr.text(), proc2.exited]);
// With system CA, we expect either success or non-cert errors
expect([0, 2]).toContain(exitCode2);
});
});