518 lines
20 KiB
Markdown
518 lines
20 KiB
Markdown
# Browsec Certificate Investigator
|
|
|
|
Status: initial design proposal
|
|
Date: 2026-08-16
|
|
|
|
> This document explores detailed certificate-investigation behavior. The
|
|
> shorter [coarse-grained concept](CONCEPT.md) defines the current project goals
|
|
> and architectural boundaries and takes precedence where the documents differ.
|
|
|
|
## 1. Summary
|
|
|
|
Browsec is a Firefox-based research browser for investigating HTTPS sites whose
|
|
certificates cannot be validated under the browser's current trust policy. It
|
|
must explain the failure, show the available certificate chains, and let the
|
|
user make narrow, auditable trust decisions without weakening their normal
|
|
browser profile.
|
|
|
|
The first implementation should be a privileged WebExtension Experiment for
|
|
Firefox Developer Edition or Nightly. It can use Firefox's internal certificate
|
|
interfaces while the product and policy model are being developed. Features
|
|
that must affect certificate verification before an HTTP request is sent,
|
|
especially domain-constrained CA trust, should later move into a small,
|
|
maintained Firefox patch.
|
|
|
|
This is not intended to make a broken connection appear safe. It is intended to
|
|
make the failure intelligible and let an informed user define a precise local
|
|
trust policy.
|
|
|
|
## 2. Goals
|
|
|
|
1. Replace an opaque certificate failure with a useful investigation page.
|
|
2. Explain where and why certificate-path validation failed.
|
|
3. Serve both ordinary users and PKI/security engineers without presenting two
|
|
inconsistent versions of the truth.
|
|
4. Allow narrowly scoped exceptions for a leaf certificate, public key, or CA.
|
|
5. Support temporary and persistent decisions with unambiguous lifetimes.
|
|
6. Preserve Firefox protections by default and clearly identify decisions that
|
|
weaken them.
|
|
7. Keep all decisions inspectable, revocable, exportable, and attributable.
|
|
8. Isolate research browsing from the user's everyday browser data.
|
|
|
|
## 3. Non-goals
|
|
|
|
- Silently accepting every invalid certificate.
|
|
- Treating encryption as proof that the remote party is trustworthy.
|
|
- Replacing TLS or implementing a new browser engine.
|
|
- Teaching users that all certificate errors are harmless.
|
|
- Globally trusting a CA when the user intended to trust it only for one site.
|
|
- Allowing a WebExtension to simulate pre-request enforcement when Firefox did
|
|
not actually enforce the decision during the TLS handshake.
|
|
|
|
## 4. Users
|
|
|
|
### 4.1 General user
|
|
|
|
The general user needs to know:
|
|
|
|
- whether communication is encrypted;
|
|
- whether the site's identity could be verified;
|
|
- the most likely reason verification failed;
|
|
- what can go wrong if they continue;
|
|
- the narrowest sensible way to continue, if one exists.
|
|
|
|
### 4.2 Engineer or investigator
|
|
|
|
The engineer additionally needs:
|
|
|
|
- raw Firefox/NSS error codes;
|
|
- the server-presented chain and Firefox-constructed chain;
|
|
- certificate and SPKI fingerprints;
|
|
- certificate fields and parsed extensions;
|
|
- TLS, revocation, Certificate Transparency, DNS, and connection metadata;
|
|
- alternate paths Firefox considered;
|
|
- a machine-readable report;
|
|
- exact scope, lifetime, and error classes of every override.
|
|
|
|
Both views must be generated from the same underlying investigation record.
|
|
The technical view expands the summary rather than contradicting it.
|
|
|
|
## 5. Threat model
|
|
|
|
Browsec assumes that any of the following may be true:
|
|
|
|
- the site is merely misconfigured;
|
|
- a private or regional CA is legitimate locally but unknown to Mozilla;
|
|
- a network intermediary is replacing certificates;
|
|
- a trusted public or operating-system CA is malicious or compromised;
|
|
- DNS or routing has been redirected;
|
|
- the server is actively hostile;
|
|
- an old certificate that was once accepted has been replaced;
|
|
- the local machine or browser policy has been modified.
|
|
|
|
Consequently, continuing past a certificate error must not grant the page
|
|
access to the user's normal cookies, saved passwords, client certificates, or
|
|
ambient authenticated sessions. The research browser uses a separate Firefox
|
|
profile. An optional isolated container is useful but is not a substitute for a
|
|
separate profile.
|
|
|
|
## 6. Design principles
|
|
|
|
### 6.1 Separate encryption, identity, and local trust
|
|
|
|
The UI must report these as separate properties:
|
|
|
|
- **Transport:** Was a TLS connection negotiated, and with what parameters?
|
|
- **Identity:** Does the certificate identify the requested host?
|
|
- **Path validation:** Can signatures and constraints be validated to an anchor?
|
|
- **Local policy:** Does this Browsec profile permit that anchor and use?
|
|
|
|
Avoid a single red/green "secure" verdict that obscures these distinctions.
|
|
|
|
### 6.2 Use the narrowest scope by default
|
|
|
|
The first suggested exception should normally bind:
|
|
|
|
- the exact hostname;
|
|
- the effective port;
|
|
- the exact leaf certificate or public key;
|
|
- only the error classes the user deliberately overrides;
|
|
- the selected lifetime;
|
|
- the current research profile or container.
|
|
|
|
Broadening from a leaf to a CA, from a host to subdomains, or from a namespace to
|
|
global trust requires a separate explicit action.
|
|
|
|
### 6.3 Never hide residual failures
|
|
|
|
If a user permits an unknown issuer but the certificate also has a hostname
|
|
mismatch, the hostname failure remains blocked. An exception is a set of
|
|
specific permitted validation failures, not a blanket "ignore TLS errors" flag.
|
|
|
|
### 6.4 Prefer decisions that can be reversed
|
|
|
|
Every decision has a visible expiration, can be revoked immediately, and is
|
|
written to a local audit log. The investigation report stores fingerprints and
|
|
metadata, never private keys or page contents.
|
|
|
|
## 7. Investigation page
|
|
|
|
### 7.1 Page structure
|
|
|
|
The initial screen uses progressive disclosure:
|
|
|
|
1. **Outcome:** one sentence explaining what Firefox could and could not prove.
|
|
2. **Broken link:** a compact chain diagram focused on the failure location.
|
|
3. **Risk:** a specific consequence, not a generic warning.
|
|
4. **Actions:** block, inspect, or create a narrowly scoped exception.
|
|
5. **Technical details:** expandable evidence and raw data.
|
|
|
|
Example summary:
|
|
|
|
> The connection is encrypted, but Firefox cannot verify that the server is
|
|
> `library.village`. The server certificate leads to "Village Network CA",
|
|
> which this profile does not currently trust.
|
|
|
|
Example risk:
|
|
|
|
> Someone controlling this network could present another certificate from the
|
|
> same untrusted authority. Continuing with this exact certificate is narrower
|
|
> than trusting the authority.
|
|
|
|
### 7.2 Chain representation
|
|
|
|
The primary diagram is vertical because it works at narrow window widths and
|
|
maps naturally from the requested identity to a trust anchor:
|
|
|
|
```text
|
|
library.village Requested identity
|
|
| name matches
|
|
v
|
|
library.village certificate Leaf
|
|
| signature valid
|
|
v
|
|
Village Services CA Intermediate
|
|
| signature valid
|
|
v
|
|
Village Network CA Root candidate
|
|
x not trusted by this profile
|
|
Firefox trust policy Validation stopped here
|
|
```
|
|
|
|
Each node displays a short name, role, validity state, and shortened SHA-256
|
|
fingerprint. Selecting it opens the full certificate panel.
|
|
|
|
Edges represent checks, not merely containment. Each edge should say, for
|
|
example, "signature valid", "issuer not supplied", "name constraints reject
|
|
this host", or "no trusted path found". The failed edge is emphasized by icon,
|
|
label, and shape as well as color.
|
|
|
|
When the server-presented and Firefox-constructed chains differ, the page first
|
|
shows the chain Firefox used and labels it **Validation path**. A switch exposes
|
|
**Presented by server** and **Other paths considered**. Roots are often not sent
|
|
by servers, so the UI must not imply that every displayed root came from the
|
|
network.
|
|
|
|
### 7.3 Certificate detail panel
|
|
|
|
The general section contains:
|
|
|
|
- subject and issuer display names;
|
|
- DNS names covered;
|
|
- valid-from and valid-until dates in local time and UTC;
|
|
- certificate SHA-256 fingerprint;
|
|
- whether it was supplied by the server, cached, fetched, or found locally.
|
|
|
|
The engineering section additionally contains:
|
|
|
|
- serial number;
|
|
- subject and issuer distinguished names;
|
|
- SPKI SHA-256 fingerprint;
|
|
- signature and public-key algorithms and sizes;
|
|
- basic constraints, key usage and extended key usage;
|
|
- name constraints and policy constraints;
|
|
- Authority/Subject Key Identifiers;
|
|
- AIA, CRL, OCSP and SCT information;
|
|
- PEM and DER export.
|
|
|
|
### 7.4 Failure explanation
|
|
|
|
The page maps the internal error to:
|
|
|
|
- a stable Browsec failure category;
|
|
- the original Firefox/NSS error code;
|
|
- the affected certificate or chain edge;
|
|
- a plain-language explanation;
|
|
- evidence supporting the explanation;
|
|
- whether Firefox considers the failure overridable;
|
|
- what an override would and would not permit.
|
|
|
|
Initial failure categories:
|
|
|
|
- unknown issuer or no trusted path;
|
|
- explicitly distrusted certificate or CA;
|
|
- missing or incorrect intermediate;
|
|
- expired or not-yet-valid certificate;
|
|
- hostname mismatch;
|
|
- invalid signature or malformed certificate;
|
|
- invalid CA constraints, key usage, or name constraints;
|
|
- revoked certificate or revocation-status failure;
|
|
- Certificate Transparency failure;
|
|
- weak or prohibited cryptography;
|
|
- HSTS, pinning, or browser policy prohibits an override;
|
|
- internal or network failure preventing a conclusion.
|
|
|
|
The page must distinguish "not checked", "check failed", and "check found a
|
|
negative result". For example, an OCSP timeout is not the same as revocation.
|
|
|
|
## 8. Trust and continuation actions
|
|
|
|
### 8.1 Terminology
|
|
|
|
Do not use **Trust once** in the UI. "Once" is ambiguous: it could mean one TLS
|
|
connection, one top-level load, one tab, one origin visit, or one browser
|
|
session. The precise single-use behavior will be defined after prototyping
|
|
Firefox's connection reuse, redirects, subresources, workers, and HTTP/2 or
|
|
HTTP/3 connection coalescing.
|
|
|
|
Until then, use explicit labels:
|
|
|
|
- **Continue for this browser session**
|
|
- **Allow until…**
|
|
- **Always allow under this rule**
|
|
|
|
A possible future one-operation action should be named after its actual scope,
|
|
such as **Continue for this tab visit**, and not be shipped until that scope can
|
|
be enforced reliably.
|
|
|
|
### 8.2 Decision target
|
|
|
|
The user chooses what is being accepted:
|
|
|
|
1. **Exact certificate for this host** — binds the leaf DER fingerprint.
|
|
2. **Public key for this host** — permits certificate renewal with the same key;
|
|
this has different operational and compromise risks and is an advanced
|
|
option.
|
|
3. **CA for this host or DNS namespace** — permits chains anchored at that CA
|
|
only for the declared host scope.
|
|
4. **CA globally in this research profile** — advanced and high impact.
|
|
|
|
The UI recommends the first applicable, narrowest option. Trusting an
|
|
intermediate or root never appears as an incidental checkbox on the leaf action.
|
|
|
|
### 8.3 Host scope
|
|
|
|
Available scopes are:
|
|
|
|
- exact host and port;
|
|
- exact host on any port;
|
|
- explicit wildcard/subdomain namespace;
|
|
- global, for a CA only.
|
|
|
|
Internationalized domain names are displayed in both Unicode and ASCII/Punycode
|
|
when confusable characters are possible. Wildcard expansion is previewed in
|
|
plain language before confirmation.
|
|
|
|
### 8.4 Lifetime
|
|
|
|
Available lifetimes are:
|
|
|
|
- current browser session;
|
|
- a fixed duration, expressed with its resulting expiration timestamp;
|
|
- until a chosen date and time;
|
|
- persistent until revoked.
|
|
|
|
Session permission ends when the research browser profile shuts down, not when
|
|
the last window happens to close if Firefox remains running. Timed permission
|
|
must expire even across restarts. Existing connections should be closed or
|
|
revalidated when a permission expires or is revoked.
|
|
|
|
### 8.5 Error scope
|
|
|
|
The confirmation dialog lists each observed failure separately. Only eligible,
|
|
selected failures are overridden. Invalid signatures, known revocation, and
|
|
browser-enforced non-overridable policy remain blocked unless a future forensic
|
|
mode is designed with stronger isolation.
|
|
|
|
### 8.6 Confirmation
|
|
|
|
Before committing a rule, show a sentence generated from the complete policy:
|
|
|
|
> Until 2026-08-17 18:00 +04, allow certificate `A1:B2:…` for
|
|
> `library.village:443` when the only failure is an unknown issuer. Continue in
|
|
> the research profile without normal cookies or saved credentials.
|
|
|
|
Broad CA decisions require the user to inspect the selected CA and confirm the
|
|
host scope. No countdown, repeated warning, or expert quiz is required; clarity
|
|
and precision are preferred over friction that users learn to dismiss.
|
|
|
|
## 9. Policy model
|
|
|
|
An illustrative stored rule:
|
|
|
|
```json
|
|
{
|
|
"id": "0191-example",
|
|
"target": {
|
|
"kind": "leaf_certificate",
|
|
"sha256": "base64-or-canonical-hex-fingerprint"
|
|
},
|
|
"network_scope": {
|
|
"host": "library.village",
|
|
"include_subdomains": false,
|
|
"port": 443
|
|
},
|
|
"allowed_failures": ["unknown_issuer"],
|
|
"profile_scope": "research",
|
|
"created_at": "2026-08-16T12:00:00+04:00",
|
|
"expires_at": "2026-08-17T18:00:00+04:00",
|
|
"reason": "Local library network",
|
|
"source_investigation_id": "0191-investigation"
|
|
}
|
|
```
|
|
|
|
Rules are evaluated with deny taking precedence over allow. More-specific rules
|
|
take precedence over broader rules only after deny precedence is applied. An
|
|
unexpected certificate change never inherits a leaf-fingerprint exception.
|
|
|
|
The policy format must be versioned and support export/import. Import previews
|
|
the effective grants and never silently enables a global CA.
|
|
|
|
## 10. Explicit distrust
|
|
|
|
Browsec also needs negative policy because the user may reject a CA that Firefox
|
|
or the operating system normally trusts.
|
|
|
|
Negative rules may target:
|
|
|
|
- exact leaf certificate;
|
|
- public key;
|
|
- intermediate CA;
|
|
- root CA;
|
|
- a CA only within or outside a DNS namespace.
|
|
|
|
The investigation page should say whether the chain was rejected by Mozilla's
|
|
root program, the operating-system store, a Browsec rule, revocation data, or
|
|
another policy source. Trust sources must be visible; "trusted by computer" is
|
|
not sufficient.
|
|
|
|
## 11. Investigation record and audit log
|
|
|
|
Each failed navigation creates an investigation record containing:
|
|
|
|
- timestamp, requested URL origin, SNI, resolved address and proxy state;
|
|
- Firefox/NSS errors and Browsec categories;
|
|
- presented and constructed certificate chains;
|
|
- fingerprints and parsed certificate metadata;
|
|
- TLS version, cipher, key exchange, ALPN and ECH state when available;
|
|
- OCSP, CRL and Certificate Transparency observations;
|
|
- relevant trust and distrust rules;
|
|
- the user's decision and resulting rule ID.
|
|
|
|
Query parameters and fragments should be redacted by default because they may
|
|
contain secrets. Reports should not include cookies, authorization headers,
|
|
form data, response bodies, private keys, or session secrets.
|
|
|
|
Export formats:
|
|
|
|
- human-readable HTML or PDF report;
|
|
- canonical JSON for tooling and comparison;
|
|
- PEM/DER for individual public certificates.
|
|
|
|
## 12. Architecture
|
|
|
|
### 12.1 Prototype
|
|
|
|
The prototype consists of:
|
|
|
|
- a privileged WebExtension Experiment;
|
|
- an internal API that obtains failed-handshake details and chains;
|
|
- a privileged investigation page, isolated from remote content;
|
|
- a policy database and audit database in the research profile;
|
|
- an adapter to Firefox's certificate override service for supported leaf
|
|
exceptions.
|
|
|
|
An ordinary WebExtension is inadequate. Firefox's public `webRequest` API can
|
|
inspect successful TLS connections but cannot override trust decisions, and the
|
|
headers event is not delivered when the TLS handshake fails.
|
|
|
|
### 12.2 Firefox integration
|
|
|
|
Firefox currently has an internal certificate override service with host, port,
|
|
origin attributes, certificate, and temporary/persistent state. The prototype
|
|
can use this for supported exact-certificate exceptions.
|
|
|
|
The verifier-level implementation is required for:
|
|
|
|
- domain-constrained CA anchors;
|
|
- complete enforcement before HTTP data is transmitted;
|
|
- timed rule expiry and revalidation integrated with connections;
|
|
- consistent handling in the socket/network process;
|
|
- detailed alternate-path diagnostics;
|
|
- precise deny rules against otherwise trusted chains.
|
|
|
|
### 12.3 Security boundaries
|
|
|
|
- The investigation UI is browser-owned privileged content, never supplied by
|
|
the failed site.
|
|
- Remote certificate text is escaped and treated as untrusted input.
|
|
- The page cannot be framed or navigated by web content.
|
|
- Trust operations require a user gesture in the top-level privileged page.
|
|
- Rules are committed atomically and validated against the certificate that was
|
|
actually investigated.
|
|
- On retry, the verifier confirms that the current certificate still matches the
|
|
chosen rule.
|
|
- Private CA keys are never generated or stored by Browsec.
|
|
|
|
## 13. Research-profile defaults
|
|
|
|
- Use a dedicated Firefox profile and visible separate branding.
|
|
- Disable automatic import of operating-system/enterprise roots by default.
|
|
- Disable saved passwords and payment information.
|
|
- Do not import client certificates from the normal profile.
|
|
- Use separate cookies, storage, history and downloads.
|
|
- Warn before opening downloaded executables, but do not imply that certificate
|
|
acceptance makes a download safe.
|
|
- Keep Firefox sandboxing, site isolation, Safe Browsing, HSTS, revocation and
|
|
Certificate Transparency enabled unless a specific investigation explains
|
|
and records a change.
|
|
|
|
## 14. Delivery plan
|
|
|
|
### Milestone 1: static UX and data model
|
|
|
|
- Create the investigation record schema and rule schema.
|
|
- Build representative fixtures for major failure categories.
|
|
- Prototype the summary, chain diagram and certificate detail panel.
|
|
- Test terminology with both non-specialists and PKI engineers.
|
|
- Resolve the exact semantics, if any, of a single-visit continuation.
|
|
|
|
### Milestone 2: privileged Firefox prototype
|
|
|
|
- Capture real failed-handshake diagnostics.
|
|
- Render the browser-owned investigation page.
|
|
- Export JSON and certificates.
|
|
- Add exact leaf-certificate session and persistent overrides.
|
|
- Add rule listing, expiry, revocation and audit history.
|
|
|
|
### Milestone 3: policy enforcement
|
|
|
|
- Add timed permissions.
|
|
- Add explicit distrust of otherwise trusted certificates and CAs.
|
|
- Add domain-constrained CA trust.
|
|
- Ensure enforcement occurs before HTTP request data is sent.
|
|
- Test redirects, subresources, service workers, WebSockets, HTTP/2, HTTP/3,
|
|
connection coalescing, proxies, private browsing and containers.
|
|
|
|
### Milestone 4: research-browser distribution
|
|
|
|
- Maintain a minimal Firefox patch set and reproducible build.
|
|
- Apply distinct branding and profile paths.
|
|
- Define update and migration behavior without silently widening policy.
|
|
- Conduct a security review and build adversarial integration tests.
|
|
|
|
## 15. Open questions
|
|
|
|
1. Can a useful "continue for this tab visit" scope be defined and enforced
|
|
across redirects, subresources, workers, and multiplexed connections?
|
|
2. Should public-key trust survive certificate renewal by default, or remain an
|
|
expert-only option?
|
|
3. How should CA namespace constraints interact with certificate name
|
|
constraints and public-suffix boundaries?
|
|
4. Which failures, if any, belong in an isolated forensic mode rather than being
|
|
absolutely non-overridable?
|
|
5. Should timed-rule expiry terminate existing connections immediately?
|
|
6. How should independently observed chains (for example, from another network
|
|
vantage point) be displayed without implying that they prove correctness?
|
|
7. How should policy synchronization work without exposing browsing targets or
|
|
allowing a compromised sync source to widen trust?
|
|
|
|
## 16. Relevant Firefox interfaces and documentation
|
|
|
|
- [Firefox WebExtension API implementation and Experiments](https://firefox-source-docs.mozilla.org/toolkit/components/extensions/webextensions/basics.html)
|
|
- [Firefox `webRequest.getSecurityInfo`](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webRequest/getSecurityInfo)
|
|
- [Firefox certificate verification implementation](https://searchfox.org/mozilla-central/source/security/manager/ssl/SSLServerCertVerification.cpp)
|
|
- [Firefox certificate override service](https://searchfox.org/firefox-main/source/security/manager/ssl/nsCertOverrideService.cpp)
|
|
- [Firefox enterprise certificate configuration](https://support.mozilla.org/en-US/kb/setting-certificate-authorities-firefox)
|
|
- [NSS `certutil` reference](https://nss-crypto.org/reference/security/nss/legacy/tools/certutil/index.html)
|