Skip to content

Support loading custom CAs (--ca-cert, --ca-path) - #2891

Merged
krichprollsch merged 24 commits into
mainfrom
nikneym/custom-cert-load
Jul 23, 2026
Merged

Support loading custom CAs (--ca-cert, --ca-path)#2891
krichprollsch merged 24 commits into
mainfrom
nikneym/custom-cert-load

Conversation

@nikneym

@nikneym nikneym commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Addresses #2877, custom CA certs and directories can be provided via --ca-cert and --ca-path.

In order to test, you can grab Mozilla CA store in PEM format from curl's website; then execute this:

lightpanda fetch "https://lightpanda.io/" --ca-cert <PEM> --dump > output.html

@nikneym
nikneym force-pushed the nikneym/custom-cert-load branch from e042e4c to 63d96c3 Compare July 6, 2026 10:02
Comment thread src/network/Network.zig Outdated
Comment thread src/help.zon Outdated
Comment thread src/Config.zig Outdated
@nikneym
nikneym force-pushed the nikneym/custom-cert-load branch 2 times, most recently from 6ad0702 to 50c5977 Compare July 8, 2026 11:49
@nikneym
nikneym requested a review from karlseguin July 8, 2026 11:49
@nikneym nikneym changed the title Custom CAs (--ca-cert, --ca-path) + flag for disabling root CA Support loading custom CAs (--ca-cert, --ca-path) Jul 8, 2026
Comment thread src/network/Network.zig Outdated
// Report back if no certificates loaded.
defer {
const num_of_certs = crypto.getCertCount(store);
if (num_of_certs == 0) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If --ca-path is hash directory, this will incorrectly warn.

Comment thread src/network/Network.zig Outdated
}
}

load_custom_ca: switch (config.mode) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the end, did we decide that if --ca-path or -ca-cert was specified, we'd continue to load the system certs too?

@nikneym nikneym Jul 15, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we didn't, loading only what's provided would probably be the desired behavior.

Comment thread src/Config.zig Outdated
.{ .name = "v8_flags_unsafe", .type = ?[]const u8 },
.{ .name = "v8_max_heap_mb", .type = ?u32 },
.{ .name = "ca_cert", .type = [:0]const u8, .multiple = true },
.{ .name = "ca_path", .type = [:0]const u8, .multiple = true, .validator = caPathValidator },

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a bit inconsistent that a bad ca_path stops the app from starting, but a bad ca_cert only warns at a later time.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. I think we can either try parsing ca_cert in Config and store or make both warn at a later time.

Parsing before creating the store requires us to store the X509 pointers in somewhere though; so, if we can add something like this to Config, we can distinguish internal representation and CLI expectation.

.{
    .name = "ca_cert",
    .type = .{
        .cli = [:0]const u8,
        .memory = *crypto.X509,
    },
    .multiple = true,
},

Which would expect [:0]const u8 from CLI but prefer std.ArrayList(*crypto.X509) in internal store.

Or, we can just parse 2 times; one in Config and the other at X509 store creation time.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We still have inconsistency here:

  • invalid ca-path: the process doesn't start
  • invalid ca-cert: the process starts w/ a warning "Invalid CA cert" but idk if we loaded the system's cert or if we disabled tls validation.

I think we should stop in both cases.

@nikneym nikneym Jul 21, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should stop in both cases.

Agreed, will match the behavior of both.

Comment thread src/Config.zig Outdated
return error.InvalidArgument;
}

return list.append(allocator, dir);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in cli.zig, the documentation says that strings are "duped from argv". So I assume if they have to be duped there, it has to be duped here?

@karlseguin

karlseguin commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator

zig build run -- fetch --ca-path ca-test https://example.com crashes

@nikneym
nikneym force-pushed the nikneym/custom-cert-load branch from 50c5977 to e279307 Compare July 15, 2026 12:24
@nikneym
nikneym requested a review from karlseguin July 15, 2026 12:24
Comment thread src/network/Network.zig Outdated
},
.help => unreachable,
.version => {}, // Don't load custom CA for version command.
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move the switch into a Config's accessors instead keeping it in Network.
Somehting like caCerts and caCertDirs.

Comment thread src/sys/libcrypto.zig Outdated
comp: OPENSSL_sk_cmp_func,
};
pub const _STACK = struct_stack_st;
pub extern fn sk_num(sk: [*c]const _STACK) usize;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude complaints about this use:

  2. The sk_num binding is unmodified translate-c output and uses a deprecated symbol. (src/sys/libcrypto.zig:356-368, 395-404)

  - struct_stack_st is declared but never dereferenced — only used as a @ptrCast target. It's a silent trap if someone later reads a field and the layout has drifted. Delete it.
  - sk_X509_OBJECT_num is Zig-only but declared callconv(.c) with a pointless const sk = arg_sk;. Compare findDigest at the bottom of the same file for the hand-written style.
  - sk_num is OPENSSL_DEPRECATED (stack.h:302). OPENSSL_sk_num (stack.h:257) is the supported name with the identical size_t signature, and returns 0 for NULL — so the whole thing is
  three lines with no null check needed.

WDYT?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can do counting by ourselves, though there shouldn't be any deprecation notice on sk_num on BoringSSL.

Comment thread src/Config.zig Outdated
.{ .name = "v8_flags_unsafe", .type = ?[]const u8 },
.{ .name = "v8_max_heap_mb", .type = ?u32 },
.{ .name = "ca_cert", .type = [:0]const u8, .multiple = true },
.{ .name = "ca_path", .type = [:0]const u8, .multiple = true, .validator = caPathValidator },

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We still have inconsistency here:

  • invalid ca-path: the process doesn't start
  • invalid ca-cert: the process starts w/ a warning "Invalid CA cert" but idk if we loaded the system's cert or if we disabled tls validation.

I think we should stop in both cases.

@nikneym
nikneym force-pushed the nikneym/custom-cert-load branch from e279307 to 3e8a0e1 Compare July 21, 2026 19:56
@nikneym
nikneym marked this pull request as draft July 22, 2026 12:53
@nikneym
nikneym force-pushed the nikneym/custom-cert-load branch from ec80029 to efc0c26 Compare July 22, 2026 14:55
@nikneym
nikneym marked this pull request as ready for review July 22, 2026 14:55
@nikneym
nikneym requested a review from krichprollsch July 22, 2026 14:55
@nikneym
nikneym marked this pull request as draft July 22, 2026 14:58
@nikneym
nikneym force-pushed the nikneym/custom-cert-load branch from 689248c to a4ba95b Compare July 22, 2026 15:29
@nikneym
nikneym marked this pull request as ready for review July 22, 2026 15:29
@krichprollsch
krichprollsch merged commit 1d3e961 into main Jul 23, 2026
26 checks passed
@krichprollsch
krichprollsch deleted the nikneym/custom-cert-load branch July 23, 2026 09:33
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 23, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants