Skip to content

Security: SCA upgrades and tooling modernization#3

Open
randytarampi wants to merge 29 commits into
mainfrom
securitize
Open

Security: SCA upgrades and tooling modernization#3
randytarampi wants to merge 29 commits into
mainfrom
securitize

Conversation

@randytarampi

@randytarampi randytarampi commented Jul 10, 2026

Copy link
Copy Markdown
Member

Summary

Security-hardening and tooling-modernization work from the securitize branch. Clears the outstanding yarn npm audit findings and brings the build, CI, and toolchain up to date without changing the public component API.

Security

Advisory Package Fix
CVE-2022-24785, CVE-2022-31129 moment ^2.30.1
GHSA-wf6x-7x77-mvgw immutable ^4.3.8 (adds typed getIn/updateIn/fromJS helpers in src/utils/immutable.ts)
GHSA-r5fr-rjxr-66jc, GHSA-f23m-r3pf-42rh, GHSA-xxjr-mmjv-4gpg lodash ^4.18.1
GHSA-7fh5-64p2-3v2j, GHSA-qx2v-qp2m-jg93 postcss ^8.5.15
GHSA-gcx4-mw62-g8wm, GHSA-mw96-cpmx-2vgc rollup ^2.80.0
GHSA-rc3x-jf5g-xvc5, GHSA-7x7c-qm48-pq9c karma ^6.4.4
GHSA-869p-cjfg-cm3x jws ^3.2.3 + pin jsonwebtoken@^9.0.2
semver, qs, tough-cookie, follow-redirects Version consolidation
getstream/axios Pinned ^1 resolution

All remaining yarn npm audit --no-deprecations --all --recursive --environment production findings cleared.

Fix

  • linkify's hashtag linking is restored. init() is now called after both the mention and hashtag plugins are registered, since linkifyjs 4.x ignores any plugin registered after the first init() call.

Chore

  • Migrate package management to Yarn Berry (yarn set version berry, packageManager: yarn@4.17.0)
  • Upgrade to typescript@^5
  • Upgrade the Jest toolchain to ^29 (jest, babel-jest, ts-jest, jest-environment-jsdom) and add @types/jest
  • Move @types/emoji-mart, @types/url-parse, @types/webscopeio__react-textarea-autocomplete to devDependencies
  • Require modern Node (engines.node: >=20)
  • Use modern GitHub actions/checkout@v4 and actions/cache@v4 in CI workflows
  • ESLint clean-up across the project

Changed files (17 files, +3423 / −2407)

Key files: package.json, yarn.lock, CHANGELOG.md, src/utils/immutable.ts, src/utils/textRenderer.tsx, src/context/FeedManager.tsx, src/types/linkifyjs.d.ts, .github/workflows/*, .yarnrc.yml

Note

The modernize branch (PR #4) builds on top of this branch. If this PR merges first, that PR will automatically reduce to just the React 18 modernization commit.


Summary by cubic

Security hardening and tooling modernization that clear all yarn npm audit findings, restore hashtag linking, and stabilize CI/docs builds on Node 20–26, removing the size-limit workflow that blocked CI. No public component API changes.

  • Dependencies

    • Upgraded vulnerable libs to clear audits: moment@^2.30.1, immutable@^4.3.8, lodash@^4.18.1, postcss@^8, rollup@^2, karma@^6; pinned jsonwebtoken@^9.0.2 with jws@^3.2.3; consolidated semver/qs/tough-cookie/follow-redirects; added a getstream/axios@^1 resolution.
    • Switched to Yarn Berry (packageManager: yarn@4.17.0), enabled Corepack in CI, use yarn install --immutable, require Node >=20, and updated CI (checkout/cache v4; unit matrix Node 20/22/24/26).
    • Pinned get-intrinsic@1.3.0 for Gatsby v2 on Node 20+ and enabled Yarn’s supply‑chain age gate by removing the npmMinimalAgeGate override.
    • Removed the size-limit workflow (action not allow‑listed) to prevent CI startup failures; ran Prettier to normalize formatting.
  • Bug Fixes

    • Restored linkify hashtag linking by calling init() after registering the mention and hashtag plugins.
    • Type-safety fixes: passed all six StreamUser<UT, AT, CT, RT, CRT, PT> generics in StreamApp/FeedManager; refined src/utils/immutable.ts helpers (narrowed getInToJS fallback type and preserved explicit nulls in typedUpdater).
    • Prevented local state corruption in FeedManager by guarding findIndex results before List.remove() in reaction-removal paths.
    • CI/docs stability on modern runners: added --no-sandbox for ChromiumHeadless, set NODE_OPTIONS=--openssl-legacy-provider for the docs build, replaced the global mainFields override with targeted resolve.alias for linkifyjs and linkify-plugin-mention, and added yarn build before browser bundle and docs builds.

Written for commit 17dca6e. Summary will update on new commits.

Review in cubic

Lots of other moving pieces here due to the tighter typing inside `immutable`...
Apparently we just never ran the tests on the last version? 😅
@bonterra-integrations-serviceuser

bonterra-integrations-serviceuser commented Jul 10, 2026

Copy link
Copy Markdown

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues
Code Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

The `packageManager: yarn@4.17.0` field in `package.json` requires Corepack
to be enabled on the runner. Without it, the globally installed Yarn Classic
1.22.22 refuses to install, erroring with:

  error This project's package.json defines "packageManager": "yarn@4.17.0".
  However the current global version of Yarn is 1.22.22.

Also switch `yarn install --frozen-lockfile --ignore-engines` (Yarn Classic
flags) to `yarn install --immutable` (the Yarn Berry equivalent).
The `StreamUser` class from `getstream` has 6 generic type parameters
(`<UserType, ActivityType, CollectionType, ReactionType, ChildReactionType,
PersonalizationType>`), but `StreamContextValue.user` and
`FeedManagerProps.user` only declared `StreamUser<UT>`, leaving the other 5
type params defaulting to `UR`. The `immutable@^4.3.8` upgrade tightened
type inference, exposing this mismatch as TS2322 errors in CI.

Fix: pass all 6 type params (`StreamUser<UT, AT, CT, RT, CRT, PT>`) in both
type declarations to match the actual usage in `StreamApp`.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

All reported issues were addressed

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

Comment thread src/utils/immutable.ts Outdated
Comment thread src/context/FeedManager.tsx Outdated
Comment thread .yarnrc.yml Outdated
Comment thread src/utils/immutable.ts Outdated
- Add --no-sandbox flag to ChromiumHeadless launcher in karma.config.js
  (Ubuntu 24.04 AppArmor blocks unprivileged user namespaces).
- Pin get-intrinsic to 1.3.0 to avoid async-function@1.0.0's module-sync
  export condition that breaks Gatsby v2's CJS require() on Node 20+.
- Set NODE_OPTIONS=--openssl-legacy-provider for docs-build (webpack v4
  uses md4 hash, removed from Node 17+ OpenSSL).
- Add gatsby-node.js to force webpack mainFields resolution (CJS before
  ESM) and provide node module fallbacks for browser bundle.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

3 issues found across 331 files

Not reviewed (too large): docs/render-page.js (~140,350 lines), docs/components/activity/index.html (~212 lines), docs/components/notification-feed/index.html (~198 lines), docs/components/flat-feed/index.html (~104 lines), docs/components/comment-list/index.html (~93 lines), docs/components/like-button/index.html (~92 lines), docs/components/reaction-list/index.html (~83 lines), docs/components/notification-dropdown/index.html (~75 lines), docs/components/dropdown-panel/index.html (~71 lines), docs/components/panel/index.html (~68 lines), and 36 more - if these are generated or fixture files, add them to ignored paths to exclude them from future reviews.

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="docs/component---src-components-comment-field-mdx-d18ee7639e20aca509e0.js">

<violation number="1" location="docs/component---src-components-comment-field-mdx-d18ee7639e20aca509e0.js:2">
P3: `await console.log(data)` and `await console.log(t)` await a non-thenable value. `console.log()` returns `undefined`, not a Promise, so the `await` is a no-op. This appears in both the playground code preview string and the runtime component literal — users viewing/copying this example will see a misleading pattern that implies console.log is async.</violation>
</file>

<file name="test-browser-bundle/karma.config.js">

<violation number="1" location="test-browser-bundle/karma.config.js:4">
P2: The `--no-sandbox` flag disables Chromium's process sandbox, a security boundary that isolates renderer processes from the OS. This is common in CI/Docker environments where sandboxing may not work, but it should be a conscious trade-off: if any tests load untrusted content or if this config is reused outside of ephemeral CI, removal of sandbox protection introduces real exposure. Consider documenting why the sandbox is being disabled or adding a comment linking to Chrome sandbox requirements.</violation>
</file>

<file name="docs/component---example-readme-md-bc1cec9ab430e0ecc20c.js">

<violation number="1" location="docs/component---example-readme-md-bc1cec9ab430e0ecc20c.js:1">
P3: Accumulating stale build artifacts: this PR adds a 4th hash-variant of `component---example-readme-md-*.js` while the 3 prior variants remain in the repo. Only the version referenced by the HTML entry point is served; the others are dead code that bloat the repository and create confusion about which is current. Consider cleaning up stale docs build artifacts or adding generated `.js`/`.js.map` files under `docs/` to `.gitignore` and generating them at deploy time.</violation>
</file>

Note: This PR contains a large number of files. cubic only reviews up to 200 files per PR, so some files may not have been reviewed. cubic prioritizes the most important files to review.
Tip: instead of fixing issues one by one fix them all with cubic

Re-trigger cubic

Comment thread test-browser-bundle/karma.config.js
Comment thread docs/page-data/components/audio/page-data.json
Comment thread docs/component---example-readme-md-bc1cec9ab430e0ecc20c.js
The browser bundle test (karma) requires dist/browser.full-bundle.js,
which is gitignored and must be built with yarn build. Previously the
test was always failing in CI because the dist/ directory was never
created — the Chromium sandbox crash masked this underlying issue.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

All reported issues were addressed across 331 files

Not reviewed (too large): docs/render-page.js (~140,350 lines), docs/components/activity/index.html (~212 lines), docs/components/notification-feed/index.html (~198 lines), docs/components/flat-feed/index.html (~104 lines), docs/components/comment-list/index.html (~93 lines), docs/components/like-button/index.html (~92 lines), docs/components/reaction-list/index.html (~83 lines), docs/components/notification-dropdown/index.html (~75 lines), docs/components/dropdown-panel/index.html (~71 lines), docs/components/panel/index.html (~68 lines), and 36 more - if these are generated or fixture files, add them to ignored paths to exclude them from future reviews.

Note: This PR contains a large number of files. cubic only reviews up to 200 files per PR, so some files may not have been reviewed. cubic prioritizes the most important files to review.

Fix all with cubic | Re-trigger cubic

Comment thread .github/workflows/unit.yml
Comment thread gatsby-node.js Outdated
The docz theme imports dist/index.css which is gitignored and must be
built with yarn build before the docs build can succeed.
- src/utils/immutable.ts: Narrow getInToJS fallback type from unknown to
  AnyCollection so the helper's contract matches the .toJS() call.
- src/utils/immutable.ts: Use === undefined instead of ?? in typedUpdater
  to preserve explicit null values (old default-parameter behavior).
- src/context/FeedManager.tsx: Guard findIndex against -1 before calling
  List.remove() in all 4 reaction-removal sites to prevent corrupting
  local state when the deleted id isn't found.
- .yarnrc.yml: Remove npmMinimalAgeGate: 0 to enable Yarn's built-in
  supply-chain age gate for freshly-published packages.
- test-browser-bundle/karma.config.js: Add comment explaining why
  --no-sandbox is needed (Ubuntu 24.04 AppArmor blocks user namespaces).
- gatsby-node.js: Replace global mainFields override with targeted
  resolve.alias for linkifyjs and linkify-plugin-mention CJS entries,
  avoiding collateral damage to packages that rely on the browser field.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

1 issue found across 5 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/utils/immutable.ts">

<violation number="1" location="src/utils/immutable.ts:28">
P2: `typedUpdater` was changed to only substitute `notSetValue` when `value` is `undefined`, but the JSDoc still says it applies when the existing value is `null`/`undefined`. Additionally, call sites in `FeedManager.tsx` pass collection updaters (e.g., list `unshift` or `remove`) that will throw at runtime if they receive `null`. If the intent is to preserve the previous `null`/`undefined` fallback contract, the check should handle both; otherwise the documentation should be updated to match.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Fix all with cubic | Re-trigger cubic

Comment thread src/utils/immutable.ts
* semantics: it is applied when the existing value is `null`/`undefined`.
*/
export function typedUpdater<T>(updater: (value: T) => T, notSetValue: T): (value: unknown) => unknown {
return (value) => updater((value === undefined ? notSetValue : value) as T);

@cubic-dev-ai cubic-dev-ai Bot Jul 10, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: typedUpdater was changed to only substitute notSetValue when value is undefined, but the JSDoc still says it applies when the existing value is null/undefined. Additionally, call sites in FeedManager.tsx pass collection updaters (e.g., list unshift or remove) that will throw at runtime if they receive null. If the intent is to preserve the previous null/undefined fallback contract, the check should handle both; otherwise the documentation should be updated to match.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/utils/immutable.ts, line 28:

<comment>`typedUpdater` was changed to only substitute `notSetValue` when `value` is `undefined`, but the JSDoc still says it applies when the existing value is `null`/`undefined`. Additionally, call sites in `FeedManager.tsx` pass collection updaters (e.g., list `unshift` or `remove`) that will throw at runtime if they receive `null`. If the intent is to preserve the previous `null`/`undefined` fallback contract, the check should handle both; otherwise the documentation should be updated to match.</comment>

<file context>
@@ -25,10 +25,10 @@ export function getInToJS<T>(source: AnyCollection, keyPath: Iterable<unknown>,
  */
 export function typedUpdater<T>(updater: (value: T) => T, notSetValue: T): (value: unknown) => unknown {
-  return (value) => updater((value ?? notSetValue) as T);
+  return (value) => updater((value === undefined ? notSetValue : value) as T);
 }
 
</file context>
Suggested change
return (value) => updater((value === undefined ? notSetValue : value) as T);
return (value) => updater((value == null ? notSetValue : value) as T);
Fix with cubic

- Run prettier on FeedManager.tsx and immutable.ts (trailing commas, as-cast parens)
- Remove .github/workflows/size-limit.yml — andresz1/size-limit-action@v1 is not
  on the org's GitHub Actions allowlist, causing a startup_failure on every PR
@randytarampi randytarampi self-assigned this Jul 10, 2026
@randytarampi randytarampi added bug Something isn't working enhancement New feature or request help wanted Extra attention is needed labels Jul 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working enhancement New feature or request help wanted Extra attention is needed

Development

Successfully merging this pull request may close these issues.

2 participants