Skip to content

Rebase our fork against latest adopted-ember-addons/main + security fixes - #4

Open
Gaurav0 wants to merge 12 commits into
mainfrom
scf_master
Open

Gaurav0 wants to merge 12 commits into
mainfrom
scf_master

Conversation

@Gaurav0

@Gaurav0 Gaurav0 commented Oct 14, 2026 •

Copy link
Copy Markdown

Summary

Rebases our fork onto upstream adopted-ember-addons/torii v1.0.0 (7dbaf64), fixes the dependency security advisories that can be fixed without a major version bump (including every finding linked to SCF-2442), and fixes the issues a security review found in our postMessage handoff and in torii's OAuth handling.

Previously our fork was based on upstream from July 2023. Upstream has since dropped Node < 20, avoided the Ember global, added @ember/string as a dependency, switched from yarn to pnpm 10 and released 1.0.0.

Commits

Our fork's changes, replayed onto v1.0.0 (unchanged)

  • Use postMessage instead of the storage event in the embedded case (a6f5f38, 66dacf1, 16e4083). When the app runs inside an iframe, browsers can partition localStorage, so the popup and the opener don't see each other's storage. redirect.html now also sends the redirect URL to the opener via postMessage. If the popup can't read the pending request key from localStorage, it asks the opener for it (getPendingRequestKey). ui-service-mixin listens for those messages alongside the existing storage listener. Adds unit tests for the postMessage path.
  • Dropped our old bump version commit (1.0.0-beta.2 → 1.0.0-beta.3) because package.json is now at upstream's 1.0.0.

Security fixes (75c23b9)

These are mostly lockfile-only updates to patched versions that existing semver ranges already allow:

  • Criticals: handlebars 4.7.10, proxy-addr 2.0.8, websocket-driver 0.7.5, shell-quote 1.12.0
  • lodash 4.18.1; minimatch 3.1.5 / 5.1.9 / 9.0.9
  • webpack 5.111.1, @babel/core 7.29.7, postcss 8.5.30, fast-uri, brace-expansion, nanoid, browserslist, js-yaml, picomatch, engine.io, socket.io, and others
  • express 4.22.3 and socket.io-adapter 2.5.8, which unpin patched body-parser, path-to-regexp, qs and ws

package.json changes:

  • ember-cli-babel ^7.26.10 → ^7.26.11 (already resolved to that version)
  • The ember-auto-import devDependency range is aligned with dependencies (^2.10.0). The lockfile resolves 2.13.1.
  • Removed the isbinaryfile: 5.0.0 resolution. It was added to keep yarn installs working on older Node, and the minimum is now Node 20, so it resolves to 5.0.7.

Remaining SCF-2442 findings (f0aaf53, a42e645) and dev-toolchain overrides (b0a4b07)

  • ember-qunit 5 → 6 (f0aaf53). ember-qunit 5 pulled in ember-auto-import 1 → babel-core 6, which brought babel-traverse 6 (CVE-2023-45133, no fixed release) and json5 0.5.1 (CVE-2022-46175). ember-qunit 6 uses ember-auto-import 2. No test changes were needed.

  • testem pinned to ~3.19.1 (f0aaf53). testem 3.16 (via ember-cli 4.8) kept babel-core 6 installed as an optional peer of consolidate 0.16. 3.19.1 uses consolidate 1.x. It is the last testem that supports Node < 20.19; 3.20+ requires Node ^20.19 || ^22.12 || >=24.

  • tmp forced to ^0.2.7 (a42e645, pnpm.overrides). can-symlink, fixturify-project and external-editor pin tmp 0.0.x (CVE-2025-54798, CVE-2026-44705) and have no release that updates it. They only use tmpNameSync, dirSync, fileSync and setGracefulCleanup, which tmp 0.2.x still provides. The build, which runs can-symlink, and the tests pass.

  • @babel/runtime, ansi-html and decode-uri-component overrides (b0a4b07, pnpm.overrides). @babel/runtime is forced to ^7.26.10, which is within the same major. ansi-html (0.0.7 → 0.0.9) and decode-uri-component (0.2.2 → 0.5.0) are 0.x bumps, used only by the dev toolchain (broccoli and sane). The test-environment build passes. Overrides only apply to this repo's own install; consumers still get ember-cli-babel 7's exact @babel/runtime pin (see "What's left").

Overall, pnpm audit goes from 182 advisories (8 critical) to 37 (1 critical). Production dependencies go from 42 advisories to 2, with no criticals.

SCF-2442

All 21 findings linked to SCF-2442 are fixed: the lockfile no longer resolves any of the vulnerable versions they name (COMP-10093 to COMP-10115).

Package Finding versions Now
@babel/plugin-transform-modules-systemjs 7.18.9 7.29.8
@babel/traverse 7.18.9 7.28.0, 7.29.10
brace-expansion 1.1.11 1.1.21, 2.1.7
browserslist 4.21.9 4.29.3
json5 0.5.1, 2.2.1 2.2.3 (0.5.1 removed with babel-core 6)
minimatch 3.1.2 3.1.5, 5.1.9, 9.0.9
semver 7.0.0 7.7.2
tmp 0.0.28, 0.0.33 0.2.7

This was checked against the lockfile. A FOSSA rescan is still needed to confirm the findings clear.

CI (5614ac7)

Disables the ember-release, ember-beta and ember-canary ember-try scenarios, which now test against Ember 7. LTS 3.28 through 5.12, classic, jQuery and Embroider scenarios still run.

Security review fixes (08fd322, 8204c1c, 41e2559, 47fc3d4)

  • Only accept postMessages from the popup we opened (08fd322). The postMessage handoff above accepted an OAuth result from any window on any origin. Any page loaded in the popup during login has a reference to the app window (window.opener), and can usually read the popup's window.name, which is the request key. So such a page could hand the app a token of its choosing. The mixin now ignores messages unless they come from our own origin and from the popup or iframe torii opened. Messages are parsed defensively, so unrelated postMessages from other scripts no longer throw. redirect.html also checks the origin of the key reply and no longer leaks url as a global. Adds eslint-plugin-html so the script in redirect.html is linted.
  • Secure randomness and a new state for each login (8204c1c). The popup id and the OAuth state used Math.random(); they now use crypto.getRandomValues. state was generated once and reused for every login attempt; it is now regenerated on each open(). A state set in the configuration is still kept.
  • Verify state for bearer/token providers by default (41e2559). oauth2-bearer, which the portal's prime provider extends, sent state but never checked it. It now rejects a response whose state is missing or doesn't match, as do google-oauth2-bearer and google-oauth2-bearer-v2. Providers whose server doesn't return state can opt out with verifyState: false in their provider config. The returned authorizationToken has the same shape as before, so saved sessions are unaffected. SCF's Doorkeeper returns state on the implicit-grant redirect, so prime needs no change.
  • Smaller fixes (47fc3d4). google-oauth2-bearer-v2 now rejects, instead of hanging, when token validation returns an error status or a body that isn't JSON. The app-wide remoteServiceName setting is now honored: it was read from an always-empty default export.

Behavior change for apps: test stubs that fake torii's popup for a bearer provider must now return the state from the URL they were given, as a real server does. The portal has one such test; its fix is on the portal branch below.

What's left

None of the remaining advisories affect code shipped to the browser. Torii's runtime code only imports Ember itself and @ember/string. None of them is linked to SCF-2442. Fixing what remains requires major bumps:

Advisory Comes from Needs
tar ≤ 7.5.20 (critical, dev), ip-address (high, dev) release-plan 0.16 release-plan 0.20
@babel/runtime 7.12.18 (moderate, prod, build-time only; overridden for this repo's own install, but consumers still get the pin) ember-cli-babel 7 exact pin ember-cli-babel 8
sprintf-js 1.1.3 (moderate, prod, build-time only) ember-auto-import → broccoli-debug → quick-temp → underscore.string no fixed release
braces, micromatch, markdown-it, linkify-it, uuid, ansi-html, … (dev) ember-cli 4.8 (braces and micromatch also via ember-template-lint and eslint-plugin-ember) ember-cli upgrade
got (moderate, dev) ember-try 2 ember-try upgrade

Testing

  • pnpm lint passes
  • ember test: 182/182 passing locally, including after the ember-qunit 6, testem and tmp changes (pnpm build also succeeds; the ember-try matrix was not run locally; see the CI checks). These include new real-browser tests that open an actual popup on redirect.html and check three things: the storage handoff, the postMessage handoff, and that a forged result from another window is ignored. There's also an iframe variant. Chrome now runs with --disable-popup-blocking so tests can open popups.
  • I checked that the new tests fail against the previous code.
  • Portal test suite, run against this branch (Chrome, CI=true): passes, after its one popup stub is updated to return state.
  • Not yet checked by hand: login in Safari (storage partitioning), the portal embedded in a cross-origin page, and federated (CRM) login.

After merging

The portal branch gaurav/chore/SCF-2442-update-torii-security (SeeClickFix/portal#2169) is up to date with this PR: it points the portal's torii dependency at this PR's head (b0a4b07) and includes the test stub fix. After merging, update it to the merge commit or a tag.

🤖 Generated with Claude Code

Gaurav0 and others added 4 commits October 14, 2026 13:44
Update vulnerable dependencies to patched versions allowed by existing
semver ranges (lockfile only), including:
- handlebars 4.7.10, proxy-addr 2.0.8, websocket-driver 0.7.5,
  shell-quote 1.12.0 (criticals)
- lodash 4.18.1, minimatch 3.1.5 / 5.1.9 / 9.0.9
- webpack 5.111.1, @babel/core 7.29.7, postcss 8.5.30, fast-uri 3.1.8,
  brace-expansion, nanoid, browserslist, js-yaml, picomatch, engine.io,
  socket.io, and others
- express 4.22.3 and socket.io-adapter 2.5.8 to pick up patched
  body-parser, path-to-regexp, qs and ws

Also:
- ember-auto-import resolves to 2.13.1; devDependencies range aligned
  to ^2.10.0
- ember-cli-babel range raised to ^7.26.11 (already resolved)
- Remove isbinaryfile 5.0.0 resolution; minimum node is now 20, so it
  resolves to 5.0.7

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Gaurav0
Gaurav0 requested review from a team and AndrewHYi October 14, 2026 18:29
@Gaurav0 Gaurav0 self-assigned this Oct 14, 2026
Gaurav0 and others added 8 commits October 14, 2026 14:39
The postMessage handoff accepted an OAuth result from any window and any
origin. Any page loaded in the popup has a handle to the opener and can
read the popup's window.name (the request key), so it could inject a
token or code.

- ui-service-mixin: ignore messages unless they come from our own origin
  and from the window we opened (new remoteWindow() hook; the iframe
  service returns its contentWindow). The window is remembered at open
  time because close() clears service.remote before late results arrive.
- Parse result messages defensively so unrelated postMessages from other
  scripts no longer throw.
- redirect.html: check the origin of the key reply, parse defensively,
  and declare `url` (it was an implicit global).
- Lint inline scripts in public HTML with eslint-plugin-html.
- Tests: unit tests for origin/source/malformed/late messages, and
  real-popup and iframe handoff tests (Chrome runs with
  --disable-popup-blocking).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- uuid-generator: build the popup id (the pending request key) from
  crypto.getRandomValues instead of Date.now() and Math.random(). Not
  crypto.randomUUID(), which needs a secure context.
- random-url-safe: generate the OAuth `state` from crypto.getRandomValues,
  rejecting bytes that would bias the distribution.
- oauth2-code: add refreshState() and call it at the start of open() in
  oauth2-code, oauth2-bearer and google-oauth2-bearer-v2, so each login
  attempt sends and checks a new state. A configured state is kept.
- Tests: v4 uuid format, no Math.random, and a URL-to-state round trip
  (state sent is the state checked; a state from an earlier attempt is
  rejected).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
oauth2-bearer (and google-oauth2-bearer, which extends it) and
google-oauth2-bearer-v2 sent `state` but never checked it, so any token
delivered for the open popup was accepted.

- Read `state` from the redirect and reject a missing or mismatched value,
  using the same error as oauth2-code (moved into assertState()).
- New `verifyState` provider setting (default true) to opt out for
  providers that do not echo `state`.
- The returned token only contains the provider's responseParams, so the
  shape of authorizationToken (and of sessions that store it) is unchanged.
- Tests: state read, match, mismatch, missing, opt-out and token shape for
  oauth2-bearer; new google-oauth2-bearer-v2 tests. The Google bearer
  integration mocks now echo state, as Google does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ceName

- google-oauth2-bearer-v2: reject when the token validation request
  returns a non-2xx status or a body that is not JSON (or is null),
  instead of throwing inside onload and leaving the login pending.
- providers/base and redirect-handler read the app-wide
  `remoteServiceName` through getConfiguration(). They read it from the
  module's default export, which is always an empty object, so the
  setting was ignored. The torii-callback initializer runs before the
  torii initializer, so it now calls configure() before the redirect
  handler runs.
- Tests: google-v2 validation failures; base provider service selection;
  redirect handler does not close the window when using the iframe
  service.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ember-qunit 5 depended on ember-auto-import 1, which pulled in
babel-core 6 and with it babel-traverse 6 (CVE-2023-45133, no fixed
release) and json5 0.5.1 (CVE-2022-46175). ember-qunit 6 uses
ember-auto-import 2.

testem 3.16 (via ember-cli 4.8) also kept babel-core 6 installed as
an optional peer of consolidate 0.16. Pin testem to 3.19.1, which
uses consolidate 1.x. It is the last release that still supports
Node < 20.19; 3.20 and later require Node ^20.19 || ^22.12 || >=24.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
can-symlink, fixturify-project and external-editor pin tmp 0.0.x
(CVE-2025-54798, CVE-2026-44705) and have no release that updates it.
They only use tmpNameSync, dirSync, fileSync and setGracefulCleanup,
which tmp 0.2.x still provides, so override it for the whole tree.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ntime

Patch-level/minor-in-0.x overrides for dev-toolchain advisories that
don't require a major bump. Test-environment build verified.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@Gaurav0
Gaurav0 marked this pull request as ready for review October 16, 2026 14:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants