mirror of
https://github.com/oven-sh/bun
synced 2026-02-09 10:28:47 +00:00
### 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>
150 lines
4.8 KiB
TypeScript
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);
|
|
});
|
|
});
|