Skip to content

feat(webauthncose): allow ber integers in ecdsa sigs#593

Merged
james-d-elliott merged 5 commits intomasterfrom
feat-asn1-ber
Mar 1, 2026
Merged

feat(webauthncose): allow ber integers in ecdsa sigs#593
james-d-elliott merged 5 commits intomasterfrom
feat-asn1-ber

Conversation

@james-d-elliott
Copy link
Member

@james-d-elliott james-d-elliott commented Feb 8, 2026

This allows implementers to permit the use of ASN.1 BER integers within ECDSA signatures. As noted by the function to enable this feature, this is experimental and considered insecure. The ambiguous nature of ASN.1 BER can lead to security issues, and as such this option is not recommended. It's purpose is to support non-conformant authenticators / credentials in the wild, though it's not necessary to support these per the spec. Use at your own risk.

Closes #408

@james-d-elliott james-d-elliott requested a review from a team as a code owner February 8, 2026 09:13
Copilot AI review requested due to automatic review settings February 8, 2026 09:13
@coderabbitai
Copy link

coderabbitai bot commented Feb 8, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds a package-scoped atomic flag and exported setter to toggle experimental allowance of non-canonical BER-encoded integers during ASN.1 unmarshaling of ECDSA signatures, updates signature verification to pass the corresponding asn1.Unmarshal option when enabled, and converts tests to assertion helpers while adding BER-focused test coverage.

Changes

Cohort / File(s) Summary
Feature Flag
protocol/webauthncose/var.go
New file: introduces package-level atomic.Bool allowBERIntegers and exported setter SetExperimentalInsecureAllowBERIntegers(bool) to toggle experimental BER-integer allowance at runtime.
Signature Verification
protocol/webauthncose/webauthncose.go
Switched ASN.1 import to custom package and updated EC2PublicKeyData.Verify() to construct asn1.Unmarshal options; conditionally appends WithUnmarshalAllowBERIntegers(true) when flag is set and passes opts to asn1.Unmarshal.
Tests / Assertions
protocol/attestation_tpm_test.go, protocol/client_test.go, protocol/webauthncose/webauthncose_test.go
Replaced t.Fatalf/manual error checks with require.*/assert.*; added/updated tests to toggle BER allowance and verify signatures under both modes; adjusted assertions and minor test refactors.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 I found some odd bytes in the grass,
I twitched my nose and let them pass.
A tiny switch, a careful hop,
Now quirky sigs can come and stop.
Hooray — the meadow’s checks don't drop.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.38% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main feature: adding support for BER integers in ECDSA signatures within the webauthncose package.
Description check ✅ Passed The description is directly related to the changeset, explaining the purpose of allowing BER integers in ECDSA signatures and warning about the experimental/insecure nature.
Linked Issues check ✅ Passed The PR fully addresses issue #408 by implementing opt-in support for non-canonical BER-encoded ECDSA signatures through the SetExperimentalInsecureAllowBERIntegers function and conditional unmarshal logic.
Out of Scope Changes check ✅ Passed All changes are scoped to adding BER integer support in signature verification and updating related test assertions; no unrelated refactoring or extraneous modifications are present.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat-asn1-ber

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link

codecov bot commented Feb 8, 2026

Codecov Report

❌ Patch coverage is 83.33333% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 58.44%. Comparing base (16f192f) to head (5a44260).
⚠️ Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
protocol/webauthncose/webauthncose.go 75.00% 0 Missing and 1 partial ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #593      +/-   ##
==========================================
+ Coverage   58.36%   58.44%   +0.07%     
==========================================
  Files          42       43       +1     
  Lines        2613     2618       +5     
==========================================
+ Hits         1525     1530       +5     
  Misses        864      864              
  Partials      224      224              
Files with missing lines Coverage Δ
protocol/webauthncose/var.go 100.00% <100.00%> (ø)
protocol/webauthncose/webauthncose.go 68.08% <75.00%> (+0.51%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an opt-in mechanism to accept non-canonical ASN.1 BER INTEGER encodings in ECDSA (ES256) WebAuthn signatures to improve interoperability with non-compliant devices, by switching to an ASN.1 decoder that can be configured to permit BER integers.

Changes:

  • Replace stdlib encoding/asn1 usage with github.com/go-webauthn/x/encoding/asn1 and pass unmarshal options during ECDSA signature parsing.
  • Add a package-level experimental toggle (SetExperimentalInsecureAllowBERIntegers) to allow BER-integer signatures.
  • Bump github.com/go-webauthn/x dependency to v0.2.0.

Reviewed changes

Copilot reviewed 3 out of 4 changed files in this pull request and generated 3 comments.

File Description
protocol/webauthncose/webauthncose.go Uses configurable ASN.1 unmarshal options during ECDSA signature parsing.
protocol/webauthncose/var.go Introduces a global experimental toggle controlling BER-integer acceptance.
go.mod Updates github.com/go-webauthn/x dependency version.
go.sum Updates checksums for the bumped dependency set.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@protocol/webauthncose/var.go`:
- Around line 3-11: Replace the plain package-level bool allowBERIntegers with
an atomic.Bool and update the setter SetExperimentalInsecureAllowBERIntegers to
call Store(value) to avoid races; update readers (e.g. Verify in webauthncose.go
and any other places reading allowBERIntegers) to use Load() instead of direct
reads so all concurrent access is race-free and lock-free.

james-d-elliott and others added 4 commits March 1, 2026 15:55
This allows implementers to permit the use of ASN.1 BER integers within signatures.

Closes #408
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: James Elliott <james-d-elliott@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: James Elliott <james-d-elliott@users.noreply.github.com>
@james-d-elliott james-d-elliott changed the title feat(webauthncose): allow ber integers in ECDSA sigs feat(webauthncose): allow ber integers in ecdsa sigs Mar 1, 2026
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@protocol/webauthncose/webauthncose_test.go`:
- Around line 51-75: The current TestOKPSignatureVerificationBER toggles
SetExperimentalInsecureAllowBERIntegers but exercises Ed25519
(OKPPublicKeyData), so it doesn't test BER-integer handling; add a new test (or
replace) that uses an EC2PublicKeyData with an ECDSA signature whose r and s use
non-minimal/BER-encoded integers, e.g., extra leading 0x00 bytes, then call
Verify(data, sig) with SetExperimentalInsecureAllowBERIntegers(false) and assert
Verify returns false (and no error if that’s the expected API), then enable
SetExperimentalInsecureAllowBERIntegers(true) and assert Verify returns true;
locate usage around TestOKPSignatureVerificationBER, reference EC2PublicKeyData,
SetExperimentalInsecureAllowBERIntegers, and the Verify method to implement the
signature construction and the two assertions.
- Around line 52-54: The test currently sets the global flag via
SetExperimentalInsecureAllowBERIntegers(true) and defers
SetExperimentalInsecureAllowBERIntegers(false), which can corrupt other tests;
capture the prior flag value into a local (e.g., prev :=
GetExperimentalInsecureAllowBERIntegers() or call
SetExperimentalInsecureAllowBERIntegers in a way that returns previous value)
before setting true, then defer restoring that saved value by calling
SetExperimentalInsecureAllowBERIntegers(prev) so the original state is
preserved; reference the SetExperimentalInsecureAllowBERIntegers function to
locate where to read/save and later restore the prior value.

ℹ️ Review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 51f2d7a and cf4c136.

📒 Files selected for processing (3)
  • protocol/attestation_tpm_test.go
  • protocol/client_test.go
  • protocol/webauthncose/webauthncose_test.go

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (2)
protocol/webauthncose/webauthncose_test.go (2)

431-437: ⚠️ Potential issue | 🟠 Major

BER toggle path still isn’t meaningfully validated.

Line 431 enables BER integers, but this block re-verifies the same fixture signature and only checks success. That won’t catch regressions in BER-integer handling unless a non-minimal BER-encoded ECDSA signature is used with explicit off→fail and on→pass assertions.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@protocol/webauthncose/webauthncose_test.go` around lines 431 - 437, The test
currently only enables BER support via
SetExperimentalInsecureAllowBERIntegers(true) and re-runs
VerifySignature(result, data, signature) which doesn’t validate BER handling;
update the test to use a deliberately non-minimal BER-encoded ECDSA signature
fixture (a signature variable different from the minimal one) and assert that
VerifySignature(result, data, signature) fails when
SetExperimentalInsecureAllowBERIntegers(false) (or not set) and succeeds when
SetExperimentalInsecureAllowBERIntegers(true), keeping existing checks for err,
ok, and result == tc.expected; locate the verification calls around
VerifySignature and the toggle call to implement the off→fail and on→pass
assertions.

431-439: ⚠️ Potential issue | 🟡 Minor

Restore previous BER flag state instead of hard-setting false.

Line 438 hard-resets global state. Preserve and restore the prior value so this test remains order-independent.

🔧 Suggested fix
-			SetExperimentalInsecureAllowBERIntegers(true)
+			prevAllowBERIntegers := allowBERIntegers.Load()
+			SetExperimentalInsecureAllowBERIntegers(true)
+			defer SetExperimentalInsecureAllowBERIntegers(prevAllowBERIntegers)

 			ok, err = VerifySignature(result, data, signature)
 			assert.NoError(t, err)
 			assert.True(t, ok)
 			assert.Equal(t, tc.expected, result)

-			SetExperimentalInsecureAllowBERIntegers(false)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@protocol/webauthncose/webauthncose_test.go` around lines 431 - 439, The test
currently calls SetExperimentalInsecureAllowBERIntegers(true) and then
unconditionally SetExperimentalInsecureAllowBERIntegers(false), which can break
test ordering; change the test to read and save the current flag value (via
calling the getter or by storing the returned prior state if
SetExperimentalInsecureAllowBERIntegers returns it), then set it to true, run
VerifySignature(result, data, signature) and assertions, and finally restore the
saved value by calling SetExperimentalInsecureAllowBERIntegers(savedValue) so
the global BER flag state is preserved for other tests.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@protocol/webauthncose/webauthncose_test.go`:
- Around line 431-437: The test currently only enables BER support via
SetExperimentalInsecureAllowBERIntegers(true) and re-runs
VerifySignature(result, data, signature) which doesn’t validate BER handling;
update the test to use a deliberately non-minimal BER-encoded ECDSA signature
fixture (a signature variable different from the minimal one) and assert that
VerifySignature(result, data, signature) fails when
SetExperimentalInsecureAllowBERIntegers(false) (or not set) and succeeds when
SetExperimentalInsecureAllowBERIntegers(true), keeping existing checks for err,
ok, and result == tc.expected; locate the verification calls around
VerifySignature and the toggle call to implement the off→fail and on→pass
assertions.
- Around line 431-439: The test currently calls
SetExperimentalInsecureAllowBERIntegers(true) and then unconditionally
SetExperimentalInsecureAllowBERIntegers(false), which can break test ordering;
change the test to read and save the current flag value (via calling the getter
or by storing the returned prior state if
SetExperimentalInsecureAllowBERIntegers returns it), then set it to true, run
VerifySignature(result, data, signature) and assertions, and finally restore the
saved value by calling SetExperimentalInsecureAllowBERIntegers(savedValue) so
the global BER flag state is preserved for other tests.

ℹ️ Review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cf4c136 and 5a44260.

📒 Files selected for processing (3)
  • protocol/attestation_tpm_test.go
  • protocol/client_test.go
  • protocol/webauthncose/webauthncose_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • protocol/attestation_tpm_test.go

@james-d-elliott james-d-elliott merged commit 68db4d4 into master Mar 1, 2026
11 checks passed
@james-d-elliott james-d-elliott deleted the feat-asn1-ber branch March 1, 2026 07:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support verification of non-canonical BER encoded ECDSA signatures

2 participants