Conversation
There was a problem hiding this comment.
Pull request overview
This PR hardens certificate/key ingestion and bundle export paths, tightens PKCS#12/JKS password handling, and standardizes serial / JSON output formatting across the CLI, internal packages, and WASM entrypoints.
Changes:
- Add size-limited input readers and use them for file/stdin ingestion to avoid unbounded reads.
- Harden bundle export directory handling (sanitize folder names, safe join) and require explicit passwords for PKCS#12/JKS outputs.
- Standardize serial formatting (
0x-prefixed hex) and align verify/scan JSON field naming (not_after, scan export JSON).
Reviewed changes
Copilot reviewed 43 out of 43 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| ocsp_test.go | Update serial formatting expectations |
| ocsp.go | Use shared serial formatter |
| internal/verify_test.go | Update chain JSON fields + serial expectations |
| internal/verify.go | Align chain JSON (not_after), bundle API update |
| internal/passwords.go | Wrap file/scan errors with context |
| internal/keygen_test.go | Update GenerateKey call sites to input struct |
| internal/keygen.go | Introduce GenerateKeyInput + wrap keygen errors |
| internal/io.go | Add size-limited read helpers |
| internal/inspect_test.go | Update serial expectations + ResolveInspectAIA signature |
| internal/inspect.go | Size-limited reads + ResolveInspectAIAInput; handle ingest errors |
| internal/exporter_test.go | Update ExportBundles signature and P12 password |
| internal/exporter.go | Safe join for folders; sanitize bundle folders; pass P12 password |
| internal/csr.go | Update GenerateKey usage + wrap CSR parse errors |
| internal/crypto.go | Add size limits + input structs for ProcessFile/ProcessData |
| internal/container.go | Use size-limited file reads |
| internal/certstore/process_test.go | Provide P12 password in round-trip export test |
| internal/certstore/helpers_test.go | Add tests for bundle folder sanitization |
| internal/certstore/helpers.go | Add SanitizeBundleFolder helper |
| internal/certstore/export_test.go | Add P12Password to export inputs; update writer-error assertion; PKCS#12 round-trip password |
| internal/certstore/export.go | Skip .p12 without password; serial formatting in JSON; pass P12Password through export |
| internal/bundleconfig.go | Wrap config read/parse errors |
| internal/archive.go | Pass per-entry size limits into ProcessData |
| connect_test.go | Update OCSP/CRL serial expectations |
| connect.go | Use input struct for AIA fetch; serial formatting in CRL detail |
| cmd/wasm/main.go | Add timeout for addFiles; use shared serial formatter |
| cmd/wasm/inspect.go | Add timeout for inspect; update ResolveInspectAIA signature |
| cmd/certkit/verify.go | Quiet validation errors when emitting JSON |
| cmd/certkit/sign.go | Handle MarkFlagRequired errors explicitly (panic on programmer error) |
| cmd/certkit/scan.go | Use ProcessFileInput; pass P12Password to export; add scan export JSON output |
| cmd/certkit/ocsp.go | Quiet validation errors when emitting JSON |
| cmd/certkit/inspect.go | Update ResolveInspectAIA signature |
| cmd/certkit/errors.go | Add doc comment for Error() |
| cmd/certkit/crl.go | Serial formatting + quiet validation for JSON |
| cmd/certkit/convert.go | Require explicit password for PKCS#12/JKS outputs |
| cmd/certkit/connect.go | Quiet validation errors when emitting JSON; serial formatting via helper |
| cmd/certkit/bundle.go | Bundle API update; require explicit password for p12/jks outputs |
| certkit.go | Add FormatSerialNumber; wrap previously-unwrapped errors |
| bundle_test.go | Update Bundle/FetchLeafFromURL/FetchAIACertificates APIs; add non-https URL error test |
| bundle.go | Convert to input structs; validate URL scheme/hostname; nil guard for AIA fetch; bundle input struct |
| README.md | Update docs for password-required PKCS#12; Bundle API example update |
| EXAMPLES.md | Update examples to require explicit p12/jks password |
| CHANGELOG.md | Document breaking password change, serial formatting, scan export JSON; add PR reference placeholder |
| .claude/rules/adversarial-review-cycle.md | Add automation rule doc for adversarial review cycle |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d3298725ab
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
Addressed the current review feedback in 32aa489:\n\n- Enforced explicit export passwords using user-provided values only (no implicit defaults from decode password list) in bundle/convert/scan.\n- Preserved WASM export behavior by allowing an optional export password arg and defaulting to when omitted.\n- Updated and to wrap read/stat errors with context.\n- Switched export flows to fail fast on hard errors (ERR-6) and kept debug-only continues for intentional skips.\n- Updated export tests for fail-fast behavior.\n\nAll checks pass via no commit to main........................................................Passed |
|
Follow-up with formatting fixed: addressed in commit 32aa489. Implemented explicit export-password selection from user-provided inputs only; preserved WASM PKCS#12 export behavior with optional export password argument; wrapped read/stat errors with context in internal IO helpers; changed export paths to fail fast on hard errors and kept debug-only continues for intentional skips; updated export tests accordingly. pre-commit run all-files passes. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 32aa489d9e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
Addressed latest review comments in 3b43763 and pushed:\n- switched to single-pass password loading ( |
| | `<cn>.root.pem` | Root certificate | | ||
| | `<cn>.key` | Private key (PEM, mode 0600) | | ||
| | `<cn>.p12` | PKCS#12 archive (default password: `changeit`, override via `--passwords`, mode 0600) | | ||
| | `<cn>.p12` | PKCS#12 archive (requires `--passwords`/`--password-file`, mode 0600) | |
There was a problem hiding this comment.
README says .p12 export "requires --passwords/--password-file", but the current export implementation still falls back to the default password ("changeit") when no explicit password is provided. Please align documentation with actual behavior, or change the export path to error/skip .p12 when no user password is given (per PR description).
| p12Password := input.P12Password | ||
| if p12Password == "" { | ||
| // Keep "changeit" as the default PKCS#12 password for interoperability. | ||
| // This mirrors widespread tooling expectations for .p12/.jks artifacts. | ||
| p12Password = "changeit" |
There was a problem hiding this comment.
GenerateBundleFiles defaults an empty P12Password to "changeit", which conflicts with the PR description/README language about requiring an explicit password (or skipping .p12 output when missing). Please pick one behavior and make code + docs consistent (either remove the fallback and conditionally omit/error, or document the fallback clearly).
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b4a5e68e14
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if previousBundle, exists := input.UsedFolders[folder]; exists && previousBundle != input.BundleName { | ||
| return fmt.Errorf("sanitized bundle folder collision: %q and %q both map to %q", previousBundle, input.BundleName, folder) | ||
| } | ||
| input.UsedFolders[folder] = input.BundleName |
There was a problem hiding this comment.
Reserve sanitized folders only for writable bundles
exportBundleCerts records input.UsedFolders[folder] before it checks whether the certificate has a matching private key, so a bundle that is ultimately skipped (keyRec == nil) can still claim a sanitized folder name and cause a later, valid bundle to fail with a collision error. This creates false-positive export failures when two bundle names sanitize to the same path but only one is actually exportable.
Useful? React with 👍 / 👎.
| seen := make(map[string]bool, len(passwords)) | ||
| out := make([]string, 0, len(passwords)) | ||
| for _, password := range passwords { | ||
| password = strings.TrimSpace(password) |
There was a problem hiding this comment.
Preserve user-supplied whitespace in export passwords
deduplicateNonEmptyPasswords calls strings.TrimSpace, which changes explicit passwords before they are used for PKCS#12/JKS export. If a user intentionally provides a password with leading/trailing spaces (via --password or password file), the generated artifact is encrypted with a different password than the user supplied, making later imports fail unless the trimmed variant is used.
Useful? React with 👍 / 👎.
Code reviewIssues foundT-11 + T-2 (MUST):
T-8 (MUST):
See inline comments for details. |
|
[Inline comment on T-11 + T-2: Tests of unexported functions should be behavioralT-11 (MUST): CLAUDE.md states: "If an unexported helper is already exercised through its public caller, do not add a direct test for the helper. Remove direct tests of unexported functions when behavioral coverage exists." Both T-2 (MUST): The fix is to:
|
|
[Inline comment on T-8: Path traversal test coverage missing for
|
Code reviewTwo issues found. CS-5 (MUST):
|
Summary
0xhex) and verify-chain JSON (not_after) for consistent machine parsing.changeit) while preferring user-provided passwords and processing decode/export password sets in a single pass.