HarperFast / HarperFast/harper

Replication cert lookup misses an IPv6-literal node identity (compact vs OpenSSL-expanded SAN key)

Open
#2,261 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
JavaScript
Stars
89
Forks
10
Avg merge
2d 6h
Merged PRs (30d)
200

Description

## Summary

When a node's identity is a bare IPv6 **literal** (e.g. `node.hostname: 2001:db8::1`), `getReplicationCert()` cannot find that node's own certificate, because the lookup key and the stored key use different IPv6 spellings.

`security/keys.ts:128` looks the context up by the identity string:

```js
const cert = secureTarget.secureContexts.get(getThisNodeName());
```

`getThisNodeName()` returns the **compact** form (`2001:db8::1`), while `secureContexts` is keyed from certificate SAN text parsed out of the cert, and OpenSSL/X509 renders IPv6 SANs **expanded** (`2001:DB8:0:0:0:0:0:1`; `::1` becomes `0:0:0:0:0:0:0:1`). The two never match, so the `get` returns `undefined`.

## Impact

- `getReplicationCert()` resolves empty for an IPv6-literal identity.
- `reviewSelfSignedCert()` then treats the existing certificate as absent and **regenerates it on every startup**.
- `getReplicationCertAuth()` (`security/keys.ts:139` — `(await getReplicationCert()).options.cert`) can dereference an absent result.

Failure is **silent** in normal logs — the node looks healthy until replication TLS misbehaves — which is what makes it worth tracking rather than leaving as folklore.

Scope is narrow: it needs the node identity to be a bare IPv6 literal. A hostname or IPv4 identity is unaffected.

## Not a regression

This is a **pre-existing** limitation of the cert lookup, not something #2223 introduced. It was surfaced by the cross-model review of [#2223](https://github.com/HarperFast/harper/pull/2223), which makes IPv6-literal identities *viable* (canonicalizing identity to the unbracketed form and bracketing only for URL construction) and therefore reachable. #2223 deliberately scoped this out, since fixing it means changing cert-context keying rather than identity resolution.

## Suggested fix

Canonicalize IP keys **identically on both insertion and lookup** — normalize an IPv6 literal to one canonical form on both sides (e.g. via `net.isIP` + a shared normalizer, cf. `normalizeIPv6` in `resources/analytics/hostnames.ts`) — or locate the replication context by its certificate-record name instead of by SAN text.

Worth adding a generate → parse → `getReplicationCert()` test over an IPv6 identity, since that path currently has no end-to-end coverage.

Contributor guide

Open the contributing guide

Research direction

Start in security/keys.ts around lines 128-139 and compare its lookup key with certificate-context insertion; read normalizeIPv6 in resources/analytics/hostnames.ts as the referenced normalization example. Trace the certificate generate-and-parse path, then add end-to-end coverage showing getReplicationCert() finds an IPv6-literal identity after parsing and that existing hostname and IPv4 lookups remain working.

Written by the indexing model from the issue text.

Assessment

Tech stack
node.js, typescript
Domain
backend, security
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.