Skip to content

Decision needed: two client-side security fixes are on master only; v0.4.2 is the only release #195

Description

@JC-000

This issue records evidence and asks for a decision. It does not propose cutting a release — that is the maintainer's call.

v0.4.2 is the only release, it has downloadable assets, and two client-side security fixes have landed on master since it was tagged. One of them the project classified in its own commit message as a passive decryption break. (An earlier draft of this line said "at least three" and was refuted by this issue's own correction section below; the number is the whole point of the issue, so it should not have been left contradicting itself.)

Evidence

v0.4.2 was tagged 2026-08-23T11:58:03Z.

1. All-zero X25519 shared secret is not rejected (#153)

Fix is commit 47ab00c, "tls: abort on an all-zero X25519 shared secret (#153)".

$ git tag --contains 47ab00c
                              # empty — in no tag

The commit landed after v0.4.2 was tagged, so no cherry-pick could have carried it. Its own message describes the impact: a server, or an attacker who rewrites one ServerHello in passing, can send a low-order key_share and force every handshake and traffic key to be a function of the two plaintext hello messages. Any passive observer who recorded the session can then derive the traffic keys, without staying on the path.

Also unreleased: tools/test_ecdh_zero_check.py, the suite that covers it.

2. Handshake-message sequence is not enforced (#152, PR #160)

Fix is commit d0c9ed3, "tls: enforce the handshake message sequence (#152)" — TLS_HS_SEQ_CHECK / src/tls_hs_seq.inc, the shared DF_ERR_SEQ rejection in both dispatchers.

$ git tag --contains d0c9ed3
                              # empty

This one changes shipped 6502 code in src/tls_deframe.s and src/tls13.s, so released images genuinely lack the check. Also unreleased: tools/test_hs_sequence.py.

A correction to how this was originally scoped

#163 was suggested to me as a third unreleased security fix. It is not one, and I am recording that rather than repeating it. f3b39d9 is "rigs: fail closed offline when the PRG cannot pass the SAN check (#141)" — a change to test-rig preconditions, not to any shipped 6502 code. It does not affect what a released PRG does, and folding it into a security-release argument would overstate the case. Two client-side fixes are unreleased, not three.

A documentation artifact worth recording separately

README on master credited the all-zero check to "Since v0.4.3". There is no v0.4.3, locally or on the remote — the tag list ends at v0.4.2. The false reference was written by the fix's own author in that same commit, forward-looking to a release that never happened, and it survived until now. Anyone reading the README would have concluded the fix was shipped. Corrected in #192.

The v0.4.2 images also carry a registrable third-party hostname

Independent of the above, and relevant to how a released image behaves if someone runs it unmodified.

The packaging scripts never set HTTPS_HOST, so released images carry the Makefile default. At the v0.4.2 tree that default is www.foo.bar:

$ git show v0.4.2:Makefile | grep 'HTTPS_HOST ?='
HTTPS_HOST ?= www.foo.bar

.bar is a delegated gTLD with live nameservers, so www.foo.bar is a name a third party can register. The rename to www.foo.invalid — RFC 2606 / RFC 6761 reserved, never delegated, cannot resolve — is commit cdf02b4 (PR #164, 2026-08-30) and is in no tag:

$ git tag --contains cdf02b4
                              # empty

Currently NXDOMAIN, so this is latent rather than live. But it combines badly with items 1 and 2: an image with no certificate chain validation, no server-name validation on the ip65 product, and no all-zero-shared-secret check would dial an attacker-controlled host on its first GET if that domain were ever registered.

Footnote — a third unreleased fix that is NOT a crypto break

Deliberately kept out of the list above so it cannot be miscounted as a third client-side security fix, but recorded because it bears on the release decision.

8c4b389, "uci: start CIA1's TOD, so the bounded waits are actually bounded (#145)". Untagged, and it touches shipped 6502 code (src/net/uci/net.s, src/net/uci/uci_cmd.s):

$ git tag --contains 8c4b389
                              # empty

Before it, CIA1's TOD was never started — it is halted out of reset and nothing in the KERNAL starts it — so every UCI spin-wait that believed itself wall-clock bounded was in fact unbounded on hardware. That is a fail-unsafe hang, not a confidentiality or authentication break, which is why it is a footnote rather than item 3. It is also UCI-only, so it affects the two UCI products and not ip65-onchip.

Worth knowing that VICE cannot catch a regression here (it runs the TOD from reset), so the guard is tools/uci/boot_check.py and it needs real hardware.

The decision being asked for

Any of these is a reasonable answer; the point is that it is recorded:

  1. Cut a release from master.
  2. Annotate the v0.4.2 release page with what it lacks.
  3. Do neither, and note here why (e.g. this is explicitly a demonstration project that already says "not cryptographically secure" at the top of its README).

Until it is decided, #192 states in the README that the all-zero check is master-only and links here.

Method note

Every claim above is checkable offline from this repo with git tag --contains and git show <tag>:<path>. The general trap it came out of: a fix being on master says nothing about it being in a release, and a README written at merge time will describe the world the author expected rather than the world that shipped.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions