Skip to content

TLS and certificates

Fetchpier ships its own trust configuration. The operating system trust store is intentionally not consulted, so a corporate root that lives only in the OS keychain has to be imported into Fetchpier before HTTPS calls into that environment succeed.

Certificates live in one of two scopes:

  • App-global — applies to every workspace on this machine. Stored alongside other app settings.
  • Workspace — applies only to the currently-open workspace. Stored inside .fetchpier/ so it travels with the workspace in Git.

Both scopes are managed from the same UI: a Certificates tab in the global Settings dialog and one in the Workspace Settings dialog. CA certificates and client certificates are listed separately, each with enable/disable toggles, descriptions, and delete actions. A client certificate’s matching metadata — host pattern, port — and its passphrase can be edited in place; the certificate files themselves are immutable, so changing them means removing the entry and adding a new one.

When a certificate file is imported, Fetchpier copies it into the canonical scope directory under a sanitised, content-hashed filename — arbitrary user paths are never stored, only file names. This means deleting a file outside the app does not corrupt settings, and the workspace folder stays self-contained.

Every enabled CA is added to a bundle that also includes the default trusted roots, and that bundle is used for every HTTPS request. Multiple CAs from both scopes can be enabled simultaneously.

A client certificate is associated with a host pattern (literal host or single-label wildcard like *.example.com) and an optional port. For each request, Fetchpier picks the single best matching certificate by specificity:

  1. literal host + explicit port,
  2. literal host, any port,
  3. wildcard host + explicit port,
  4. wildcard host, any port.

Within the same tier, workspace scope beats app scope; further ties fall back to document order.

Supported formats are PEM (cert + key) and PFX. The passphrase behaves differently by scope:

  • Workspace-scope certificates: the passphrase can be a literal or a {{variable}} reference resolved against the active environment — plain, secret, or local per-machine override, exactly like every other interpolatable field. A secret-valued passphrase is decrypted only at send time and used for the handshake; it never travels on the wire and appears in no log, report, or run snapshot. The input adapts to what you type: a literal passphrase is a real credential, so it is masked (each character shown only briefly as you type, to help confirm what was entered), while a {{…}} reference stays visible — the variable name is not the secret — with token highlighting and {{-triggered suggestion of the active environment’s variable names, secrets included by name. A non-empty literal passphrase on a workspace certificate shows a per-row warning: it is committed in clear text in the workspace settings file, and a secret variable is recommended instead.
  • App-global certificates: the passphrase is literal-only. Entering a {{…}} reference is rejected when saving, because an app-global certificate is machine-scoped and outlives any workspace, so a workspace-scoped variable could not resolve there.

CA composition and client-cert selection happen regardless of whether verifySsl is on — turning verification off only relaxes the verification step, it does not disable the custom material.

When a request URL changes, the per-request Settings panel previews which client certificate (if any) would be selected and from which scope, so you can verify your host matchers before sending.