The private key no longer reaches an exception report: sign/2 answers a mistyped call; the key may be passed by reference - #4
Merged
Conversation
… a mistyped call, and the key may be passed by reference Found by this package's own audit for the OpenSSF badge: a call that broke the documented types raised FunctionClauseError, which Elixir prints with the call's arguments, so the key reached whatever logged it. Measured on e5dd26e: sign("bytes", %{private_key: key}) printed "** (FunctionClauseError) no function clause matching in BeamMCP.Signer.Ed25519.sign/2 ... sign(\"bytes\", %{private_key: <<184, 26, ...>>})". beam_mcp's Canonical.signature/3 raises the same way on mistyped options, before this package is reached, so a fix here alone could not cover it unless the key stops being bytes in the options. Two layers, both here, core untouched: - sign/2 is total: a last clause answers {:error, :bad_arguments}, carrying nothing passed. - :private_key may be a zero-arity function returning the 32 bytes; it is called once per signature and not kept. A function prints as #Function<...>, so a key passed by reference appears in no exception, crash report or log line, core's frames included. The README, moduledoc and pages now pass it that way. The bytes form still works. Red first, the four tests added before the code: "14 tests, 2 failures" -- "a mistyped call is answered {:error, :bad_arguments}, never raised" (** (FunctionClauseError) no function clause matching in BeamMCP.Signer.Ed25519.sign/2) and "the key may be passed by reference" (refused as not_32_bytes). The other two pinned properties that already held: a reference not giving 32 bytes is refused; through core, a referenced key is printed nowhere while a key passed as bytes is (that assertion fails the day core answers a mistyped call). After: 14 tests, 0 failures. The census caught the new guard ([{:erlang, :is_function, 2}] outside the list); it is allowed with its reason, and the third census test now pins the zero-arity reference. Mutants, each red then restored: drop the answering clause (1 failure); drop the reference clause (2); echo the options in the error (1); resolve a function of any arity (2). Credo "found no issues". A minor at the next release (0.x): an accepted form added, and a raise that becomes an answer; the CHANGELOG says how to tell whether you are affected. Signed-off-by: Ayla Croft <aylacroft@proton.me>
…CODE_OF_CONDUCT, GOVERNANCE) linked by their GitHub URLs df5f76e linked them relatively, and ex_doc resolves a relative link only to a file in its extras, so mix docs printed six warnings (three links, two passes). The pull request that added them said "docs without warnings"; that was measured before the README edit and was not true of the merged tree. After: mix docs, 0 warnings. Signed-off-by: Ayla Croft <aylacroft@proton.me>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes the key leak the badge audit found: a mistyped call raised
FunctionClauseError, which Elixir prints with its arguments, the private key among them (sign("bytes", %{private_key: key})printed all 32 bytes).beam_mcp'sCanonical.signature/3raises the same way on mistyped options before this package is reached.Two layers, both in this package; core is not touched
sign/2is total: a mistyped call is answered{:error, :bad_arguments}, which carries nothing that was passed.:private_keymay be a zero-arity function returning the key (private_key: fn -> key end). A function prints as#Function<...>, so a key passed this way cannot appear in any exception, crash report or log line, core's included. The README, moduledoc and pages now use this form; the bytes form still works.Evidence
FunctionClauseError, and the reference refused). After the change: 14 tests, 0 failures.is_function/2guard. It is now allowed, with its reason, and the zero-arity reference is pinned.Second commit: the README's relative links to CONTRIBUTING, CODE_OF_CONDUCT and GOVERNANCE made
mix docsprint six warnings on main. The description of #3 claimed "docs without warnings", but that was measured before the README edit. They are now linked by their GitHub URLs;mix docsgives 0 warnings.Release impact: a minor at the next release (0.x), since a form is added and a raise becomes an answer. The CHANGELOG says how to tell whether you are affected.