Skip to content

bug: gateway add --local unconditionally overwrites mTLS certificates on repeated invocation #2560

Description

@sabre1041

Agent Diagnostic

  • Skills loaded: create-github-issue
  • OpenShell version tested: v0.0.91 (latest tag on main)
  • Latest release checked: v0.0.91 — no related fixes in changelog or commit history
  • Known fixes reviewed: git log --grep for store_pki_bundle, import_local_package_mtls_bundle, mtls.*overwrite found no relevant patches
  • Possible duplicates reviewed: bug: gateway add silently overwrites certificates when shadowing system-provisioned gateway #2481 covers the system-gateway shadowing entry point to the same store_pki_bundle overwrite. This issue covers a different trigger: repeated --local invocations without --oidc-issuer, where no system gateway is involved.
  • Findings: import_local_package_mtls_bundle() unconditionally calls store_pki_bundle() every time it finds certs in a package-managed directory, with no comparison against existing user-config certs. The OIDC code path returns early before reaching the mTLS branch, acting as an accidental guard.
  • Remaining reason for filing: No guard exists in import_local_package_mtls_bundle to skip the import when a valid bundle already exists.

Description

Actual behavior: Running openshell gateway add --local without --oidc-issuer atomically replaces the entire ~/.config/openshell/<gateway>/mtls/ directory, regardless of whether the existing certificates are valid or identical to the source.

import_local_package_mtls_bundle() (crates/openshell-cli/src/commands/gateway.rs:634) searches package-managed TLS directories and calls store_pki_bundle() (crates/openshell-bootstrap/src/mtls.rs:15) without checking whether a valid bundle already exists in the user config directory. store_pki_bundle() writes to a temp directory, backs up the existing mtls/ directory, renames the temp into place, then deletes the backup — an unconditional atomic replace.

When --oidc-issuer IS specified, the OIDC branch returns early (gateway.rs:984) before reaching the mTLS import code, so certificates are never touched. The OIDC flag acts as an accidental guard against the overwrite.

Additionally, the gateway server's certgen subcommand (crates/openshell-server/src/certgen.rs:515) also calls store_pki_bundle("openshell", &bundle) unconditionally in local mode, so server restarts that regenerate PKI will also overwrite the CLI's client certs.

Expected behavior: If a valid mTLS bundle already exists in the user config directory and matches the package-managed source (or is otherwise still valid), gateway add --local should skip the import rather than silently replacing it.

Reproduction Steps

  1. Manually place valid mTLS certificates (ca.crt, tls.crt, tls.key) into ~/.config/openshell/gateways/<gateway>/mtls/
  2. Run openshell gateway add https://localhost:8443 --local — the existing certificates are silently replaced with certs imported from the package-managed TLS directory

Environment

Related

Relevant Code Paths

  • crates/openshell-cli/src/commands/gateway.rs:634import_local_package_mtls_bundle()
  • crates/openshell-cli/src/commands/gateway.rs:987-993 — mTLS branch calling the import
  • crates/openshell-bootstrap/src/mtls.rs:15store_pki_bundle() atomic replace
  • crates/openshell-server/src/certgen.rs:515 — server-side store_pki_bundle() call (also overwrites unconditionally)

Proposed Fix

Add a comparison in import_local_package_mtls_bundle() that reads the existing user-config bundle (if present), compares it byte-for-byte (or by cert fingerprint) against the package-managed source, and skips the store_pki_bundle() call when they match. This keeps store_pki_bundle itself unconditional — it is a low-level storage primitive — and puts the "should we reimport?" decision where the context exists.

Metadata

Metadata

Assignees

No one assigned

    Labels

    state:triage-neededOpened without agent diagnostics and needs triage

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions