Skip to content

fix(deps): drop @openauthjs/openauth and clear all audit advisories - #229

Merged
ndycode merged 1 commit into
mainfrom
fix/drop-openauth-clear-advisories
Aug 11, 2026
Merged

fix(deps): drop @openauthjs/openauth and clear all audit advisories#229
ndycode merged 1 commit into
mainfrom
fix/drop-openauth-clear-advisories

Conversation

@ndycode

@ndycode ndycode commented Aug 11, 2026

Copy link
Copy Markdown
Owner

npm run audit:ci was failing, with three advisories reaching consumers (npm audit --omit=dev). All three are gone — the gate now reports 0 vulnerabilities.

The root cause was one function

@openauthjs/openauth sat in the production tree for exactly one thing — generatePKCE, called once in createAuthorizationFlow — and it declares hono as a peer dependency. That is the only reason hono was a direct dependency and an override here; nothing in this codebase imports it. Between them they carried both hono advisories, which could not be cleared while the package stayed.

This is the same removal @sussdorff is making in the sibling repo (ndycode/codex-multi-auth#661), applied here where it also happens to be a security fix.

11 packages leave the tree: @openauthjs/openauth, its dependencies (@standard-schema/spec, aws4fetch, jose), its peers (arctic, hono), and the @oslojs/* chain those pulled in.

PKCE semantics are preserved exactly

Now inline in lib/auth/auth.ts:

  • 64 random bytes, base64url-encoded → an 86-character verifier (RFC 7636 allows 43–128).
  • challenge = base64url(SHA-256(ASCII(verifier))).
  • Both encoders emit unpadded base64url, so the wire format is unchanged.
  • The upstream helper also returned method: "S256". Nothing read it — PKCEPair is { challenge, verifier } and the authorize request already hardcodes code_challenge_method=S256 (auth.ts:224). The as PKCEPair cast the old call site needed goes away with it.

Two advisories were unblocked upstream, not by this repo

Was Now
brace-expansion (high) assessed as upstream-only fixed in 5.0.9
nanoid (high, dev-only) masked behind the prod failure overridden to ^3.3.18

The brace-expansion reassessment is worth recording. It's reached via @opentui/solid → babel-plugin-module-resolver → glob@9 → minimatch@9, and even @opentui/solid@0.5.1 (latest) still pins babel-plugin-module-resolver 5.0.2 — so upgrading upstream genuinely doesn't help. But brace-expansion shipped the fix itself in 5.0.9. The existing ^5.0.8 override already allowed it; the lockfile just had 5.0.8 pinned. Override moved to ^5.0.9.

nanoid only became visible once audit:prod stopped failing and short-circuiting the gate. It comes via vitest → vite → postcss; ^3.3.18 satisfies postcss's own range.

Tests

The existing PKCE assertions checked shape and uniqueness — both of which pass for a challenge that isn't derived from the verifier at all. That failure mode is silent locally and only surfaces as a rejected token exchange against the real server, which is exactly the kind of thing a dependency swap can introduce.

The derivation is now pinned, recomputed with createHash rather than the webcrypto.subtle path the implementation uses, so the two would have to break identically to agree. Plus conformance checks on the base64url alphabet and the 86/43-character lengths.

Verified it discriminates: I changed the implementation to hash the wrong input and confirmed the test fails.

Verification

  • npm run audit:ci0 vulnerabilities (was 3 prod + 1 dev)
  • npm run typecheck — clean
  • npx eslint lib test --ext .ts — clean
  • npm test117 files, 2964 passed, 1 skipped, 0 failed
  • npm run build — clean

Windows only; Linux/non-root not run.

One caveat on scope: overrides only apply to this repo's install tree, so the brace-expansion and nanoid entries fix this repo's audit. The @openauthjs/openauth/hono removal is different — that genuinely leaves the published dependency tree, so it reaches installers.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Security & Reliability

    • Improved authorization flow security with standards-compliant PKCE verifier and challenge generation.
    • Added validation to ensure PKCE values meet required format and length requirements.
  • Maintenance

    • Updated package configuration and dependency overrides to improve compatibility and stability.

note: greptile review for oc-chatgpt-multi-auth. cite files like lib/foo.ts:123. confirm regression tests + windows concurrency/token redaction coverage.

Greptile Summary

the pr replaces the single openauth pkce dependency with an equivalent node crypto implementation and removes the resulting hono dependency chain.

  • pins verifier-to-challenge derivation and rfc 7636 encoding in vitest.
  • updates brace-expansion and nanoid resolutions to clear audit advisories.
  • preserves token safety through cryptographically random, per-flow verifiers.
  • existing vitest coverage checks concurrent flow isolation, and ci includes windows on node 20.

Confidence Score: 5/5

the pr appears safe to merge, with pkce token safety, concurrent flow isolation, and windows compatibility adequately preserved.

the inlined pkce implementation matches the consumed oauth contract, removed packages have no remaining runtime imports, and the manifest and lockfile changes are synchronized.

Important Files Changed

Filename Overview
lib/auth/auth.ts replaces the external pkce helper with a node 18-compatible s256 implementation while preserving verifier and challenge semantics.
test/auth.test.ts adds independent derivation, alphabet, and length assertions for the generated pkce pair.
package.json removes unused production dependencies and updates audit-related overrides without introducing a supported-runtime regression.
package-lock.json synchronizes dependency removals and resolves brace-expansion and nanoid to the requested patched versions.

Sequence Diagram

sequenceDiagram
  participant caller
  participant auth as createAuthorizationFlow
  participant crypto as node crypto
  participant server as oauth server
  caller->>auth: create authorization flow
  auth->>crypto: randomBytes(64)
  crypto-->>auth: base64url verifier
  auth->>crypto: sha-256(verifier)
  crypto-->>auth: base64url challenge
  auth-->>caller: url, state, and pkce pair
  caller->>server: authorize with challenge and s256
  server-->>caller: authorization code
  caller->>server: exchange code with verifier
Loading

Reviews (1): Last reviewed commit: "fix(deps): drop @openauthjs/openauth and..." | Re-trigger Greptile

Context used:

`npm run audit:ci` was failing, with three advisories reaching consumers
(`npm audit --omit=dev`). All three are now gone; the gate reports 0.

`@openauthjs/openauth` was in the production dependency tree for exactly one
function - `generatePKCE`, used once in `createAuthorizationFlow` - and it
declared `hono` as a peer dependency. That is the only reason `hono` was a
direct dependency and an override here: nothing imports it. Between them they
carried the two hono advisories (ReDoS in CORS middleware, plus the same
advisory reached through openauth), which could not be cleared while the
package stayed.

PKCE generation now lives in `lib/auth/auth.ts`, with semantics preserved
exactly:

  - 64 random bytes, base64url-encoded, giving an 86-character verifier
    (RFC 7636 allows 43-128).
  - challenge = base64url(SHA-256(ASCII(verifier))).
  - Both encoders emit unpadded base64url, so the wire format is unchanged.
  - The upstream helper also returned `method: "S256"`. Nothing read it:
    `PKCEPair` is `{ challenge, verifier }` and the authorize request already
    hardcodes `code_challenge_method=S256`. The `as PKCEPair` cast the old
    call site needed is gone with it.

Removing it takes 11 packages out of the tree: @openauthjs/openauth, its
dependencies (@standard-schema/spec, aws4fetch, jose), its peers (arctic,
hono), and the @oslojs/* chain those pulled in.

Two remaining advisories were unblocked by upstream releases rather than by
this repo:

  - `brace-expansion` (high, reached via @opentui/solid -> babel-plugin-
    module-resolver -> glob@9 -> minimatch@9). Previously assessed as
    upstream-only, since even @opentui/solid@0.5.1 still pins
    babel-plugin-module-resolver 5.0.2. That assessment is out of date:
    brace-expansion shipped the fix itself in 5.0.9. The existing `^5.0.8`
    override allowed it but the lockfile had 5.0.8 pinned; the override is
    now `^5.0.9`.
  - `nanoid` (high, dev-only, via vitest -> vite -> postcss). This was
    previously masked because `audit:prod` failed first and short-circuited
    the gate. Overridden to ^3.3.18, which satisfies postcss's own range.

Test coverage: the existing PKCE assertions checked shape and uniqueness,
both of which pass for a challenge that is not derived from the verifier at
all - the server would reject the exchange and nothing would catch it. The
derivation is now pinned, recomputed through `createHash` rather than the
`webcrypto.subtle` path the implementation uses, so the two would have to
break identically to agree. Verified by breaking the hashed input and
confirming the test fails.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Credits must be used to enable repository wide code reviews.

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

The authorization flow now uses a local Web Crypto PKCE generator. Runtime dependencies and package overrides were updated. Tests verify the PKCE challenge derivation and RFC 7636 constraints.

Changes

Local PKCE generation

Layer / File(s) Summary
Implement local PKCE generation
lib/auth/auth.ts, package.json
The authorization flow generates a 64-byte base64url verifier and an unpadded S256 challenge with Web Crypto. Removed runtime dependencies and updated package overrides support the change.
Validate PKCE parameters
test/auth.test.ts
Authorization-flow tests independently recompute the challenge and verify base64url formatting and RFC 7636 length requirements.

Estimated code review effort: 3 (Moderate) | ~20 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the primary dependency removal and audit remediation changes.
Description check ✅ Passed The description clearly explains the change, rationale, testing results, security scope, and platform limitation; omitted template checkboxes are non-critical.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/drop-openauth-clear-advisories

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.

@ndycode
ndycode merged commit d208403 into main Aug 11, 2026
2 checks passed
@ndycode
ndycode deleted the fix/drop-openauth-clear-advisories branch August 11, 2026 17:17
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.

1 participant