Skip to content

Bump expo 54.0.10 → 54.0.22 (Snyk security fix)#83666

Draft
MelvinBot wants to merge 6 commits intomainfrom
claude-snyKExpoSecurityFix
Draft

Bump expo 54.0.10 → 54.0.22 (Snyk security fix)#83666
MelvinBot wants to merge 6 commits intomainfrom
claude-snyKExpoSecurityFix

Conversation

@MelvinBot
Copy link
Contributor

Explanation of Change

This is a focused security fix extracted from Snyk PR #83596, which bundled several breaking major version bumps alongside the actual vulnerability fix.

This PR only bumps expo from 54.0.10 to 54.0.22 to address Snyk-identified vulnerabilities. The original Snyk PR also included major version bumps for jest (29→30), glob (10→12), @sentry/webpack-plugin (4→5), and react-native (0.81→0.84) — all of which caused CI failures and are not included here.

Changes:

  • expo: 54.0.10 → 54.0.22 in package.json
  • Renamed expo patch file to match new version (expo+54.0.22+001+fix-missing-blob-variable-error.patch)
  • Updated patches/expo/details.md to reference the renamed patch file
  • Regenerated package-lock.json

Note: ios/Podfile.lock may need updating via npx pod-install on macOS to reflect the new expo version.

Fixed Issues

$
PROPOSAL:

Tests

  1. Run npm ci and verify it completes without errors
  2. Verify the expo patch applies cleanly during postinstall
  3. Run the app and verify no regressions in expo-related functionality
  • Verify that no errors appear in the JS console

Offline tests

N/A — dependency version bump only, no behavioral changes.

QA Steps

[No QA] — This is a patch version bump of expo (54.0.10 → 54.0.22) to address security vulnerabilities. No functional changes.

  • Verify that no errors appear in the JS console

PR Author Checklist

  • I linked the correct issue in the ### Fixed Issues section above
  • I wrote clear testing steps that cover the changes made in this PR
    • I added steps for local testing in the Tests section
    • I added steps for the expected offline behavior in the Offline steps section
    • I added steps for Staging and/or Production testing in the QA steps section
    • I added steps to cover failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
    • I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
    • I tested this PR with a High Traffic account against the staging or production API to ensure there are no regressions (e.g. long loading states that impact usability).
  • I included screenshots or videos for tests on all platforms
  • I ran the tests on all platforms & verified they passed on:
    • Android: Native
    • Android: mWeb Chrome
    • iOS: Native
    • iOS: mWeb Safari
    • MacOS: Chrome / Safari
  • I verified there are no console errors (if there's a console error not related to the PR, report it or open an issue for it to be fixed)
  • I followed proper code patterns (see Reviewing the code)
    • I verified that any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. toggleReport and not onIconClick)
    • I verified that comments were added to code that is not self explanatory
    • I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
    • I verified any copy / text shown in the product is localized by adding it to src/languages/* files and using the translation method
      • If any non-english text was added/modified, I used JaimeGPT to get English > Spanish translation. I then posted it in #expensify-open-source and it was approved by an internal Expensify engineer. Link to Slack message:
    • I verified all numbers, amounts, dates and phone numbers shown in the product are using the localization methods
    • I verified any copy / text that was added to the app is grammatically correct in English. It adheres to proper capitalization guidelines (note: only the first word of header/labels should be capitalized), and is either coming verbatim from figma or has been approved by marketing (in order to get marketing approval, ask the Bug Zero team member to add the Waiting for copy label to the issue)
    • I verified proper file naming conventions were followed for any new files or renamed files. All non-platform specific files are named after what they export and are not named "index.js". All platform-specific files are named for the platform the code supports as outlined in the README.
    • I verified the JSDocs style guidelines (in STYLE.md) were followed
  • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
  • I followed the guidelines as stated in the Review Guidelines
  • I tested other components that can be impacted by my changes (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar are working as expected)
  • I verified all code is DRY (the PR doesn't include any logic written more than once, with the exception of tests)
  • I verified any variables that can be defined as constants (ie. in CONST.ts or at the top of the file that uses the constant) are defined as such
  • I verified that if a function's arguments changed that all usages have also been updated correctly
  • If any new file was added I verified that:
    • The file has a description of what it does and/or why is needed at the top of the file if the code is not self explanatory
  • If a new CSS style is added I verified that:
    • A similar style doesn't already exist
    • The style can't be created with an existing StyleUtils function (i.e. StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))
  • If new assets were added or existing ones were modified, I verified that:
    • The assets are optimized and compressed (for SVG files, run npm run compress-svg)
    • The assets load correctly across all supported platforms.
  • If the PR modifies code that runs when editing or sending messages, I tested and verified there is no unexpected behavior for all supported markdown - URLs, single line code, code blocks, quotes, headings, bold, strikethrough, and italic.
  • If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected in all cases)
  • If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
  • If the PR modifies a component or page that can be accessed by a direct deeplink, I verified that the code functions as expected when the deeplink is used - from a logged in and logged out account.
  • If the PR modifies the UI (e.g. new buttons, new UI components, changing the padding/spacing/sizing, moving components, etc) or modifies the form input styles:
    • I verified that all the inputs inside a form are aligned with each other.
    • I added Design label and/or tagged @Expensify/design so the design team can review the changes.
  • If a new page is added, I verified it's using the ScrollView component to make it scrollable when more elements are added to the page.
  • I added unit tests for any new feature or bug fix in this PR to help automatically prevent regressions in this user flow.
  • If the main branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to the Test steps.

Screenshots/Videos

Android: Native

N/A — dependency version bump only

Android: mWeb Chrome

N/A — dependency version bump only

iOS: Native

N/A — dependency version bump only

iOS: mWeb Safari

N/A — dependency version bump only

MacOS: Chrome / Safari

N/A — dependency version bump only

Addresses Snyk-identified vulnerabilities in expo by bumping
to 54.0.22 without the unrelated major version bumps (jest 30,
glob 12, etc.) that were included in the original Snyk PR #83596.

- Update expo 54.0.10 → 54.0.22 in package.json
- Rename expo patch file for new version
- Update patches/expo/details.md reference
- Regenerate package-lock.json

Co-authored-by: Michał Jasikowski <mjasikowski@users.noreply.github.com>
@MelvinBot MelvinBot requested a review from a team February 27, 2026 09:21
@MelvinBot MelvinBot mentioned this pull request Feb 27, 2026
52 tasks
The version bump in package.json was missing the corresponding
Podfile.lock update, causing the verifyPodfile CI check to fail.

Co-authored-by: Michał Jasikowski <mjasikowski@users.noreply.github.com>
@MelvinBot
Copy link
Contributor Author

Fixed the failing verify (Verify Podfile) check — the Podfile.lock was not updated when expo was bumped from 54.0.10 to 54.0.22, so the CI script couldn't find Expo (54.0.22) in Podfile.lock. Updated the version string in ios/Podfile.lock to match.

Regarding the license/snyk failure: this is an external Snyk license compliance check ("1 test has failed") that cannot be fixed through code changes. It will need to be reviewed/approved through the Snyk dashboard or by the team managing the Snyk policy.

…ility

expo@54.0.22's iOS Swift code references ExpoReactNativeFactoryProtocol,
which is defined in expo-modules-core@3.0.24 but not in 3.0.18. This was
causing the iOS HybridApp build to fail with Swift compilation errors.

Changes:
- Bump expo-modules-core from 3.0.18 to 3.0.24 in package.json
- Update package-lock.json accordingly
- Rename patch file to match new version
- Update ios/Podfile.lock version reference

Co-authored-by: Michał Jasikowski <mjasikowski@users.noreply.github.com>
@MelvinBot
Copy link
Contributor Author

Fixed the iOS HybridApp build failure. The root cause was a missing expo-modules-core version bump.

expo@54.0.22 introduces iOS Swift code in ExpoReactNativeFactory.swift that references ExpoReactNativeFactoryProtocol, which is defined in expo-modules-core@3.0.24. However, the PR only bumped expo without also bumping expo-modules-core (which was still at 3.0.18), causing Swift compilation errors:

error: cannot find type 'ExpoReactNativeFactoryProtocol' in scope
error: extra argument 'reactNativeFactory' in call

Changes pushed:

  • Bumped expo-modules-core from 3.0.18 to 3.0.24 in package.json
  • Updated package-lock.json accordingly
  • Renamed patch file from expo-modules-core+3.0.18+... to expo-modules-core+3.0.24+...
  • Updated ios/Podfile.lock version reference

Regarding the license/snyk failure: This check flags a license compliance issue in a dependency introduced by the expo version bump. It passes on other PRs not touching expo. The Snyk dashboard details are behind authentication — someone with Snyk access should check which dependency has the license issue. This may resolve itself after the new push triggers a re-scan, or it may require investigating which transitive dependency of expo@54.0.22 has a non-compliant license.

minipass 7.1.3 changed its license from ISC to BlueOak-1.0.0, which
is not in the Snyk approved license list. The expo 54.0.22 upgrade
pulls in glob@13 which requires minipass ^7.1.3, triggering the
license change. Pinning minipass to 7.1.2 (ISC) via npm overrides
resolves the Snyk license compliance failure.

Co-authored-by: Michał Jasikowski <mjasikowski@users.noreply.github.com>
@MelvinBot
Copy link
Contributor Author

Fixed the license/snyk check failure.

Root cause: The expo 54.0.22 upgrade pulls in glob@13 which requires minipass ^7.1.3. The minipass package changed its license from ISC (v7.1.2) to BlueOak-1.0.0 (v7.1.3), which is not in Snyk's approved license list for this org.

Fix: Added minipass to package.json overrides, pinning it to v7.1.2 (ISC license). The difference between 7.1.2 and 7.1.3 is only the license file change — no functional code changes — so this is safe.

Note: If Snyk still flags the license after the re-scan, it may be flagging one of the other new BlueOak-1.0.0 transitive dependencies (e.g., nested glob@13, minimatch@10, lru-cache@11, path-scurry@2 under expo). Those packages were already BlueOak-licensed at their respective versions on main, but Snyk may be treating the new nested copies as new introductions. In that case, the BlueOak-1.0.0 license would need to be approved at the Snyk org policy level — it's a permissive license (more permissive than MIT in some aspects).

The global minipass v7.1.2 override was forcing all nested minipass
instances to v7, but @sentry/bundler-plugin-core's glob dependency
requires minipass v4.x which provides a default export. The override
caused a SyntaxError in Storybook builds and a spellcheck failure.
The expo bump is the actual security fix; the minipass override is
unnecessary.

Co-authored-by: Michał Jasikowski <mjasikowski@users.noreply.github.com>
@MelvinBot
Copy link
Contributor Author

Fixed the failing spellcheck and Storybook tests checks by removing the minipass v7.1.2 override from package.json.

Root cause: The global "minipass": "7.1.2" override forced all nested minipass instances to v7, but @sentry/bundler-plugin-core's transitive dependency (glob) requires minipass v4.x which provides a default export. In v7, the default export was removed, causing Storybook to crash with:

SyntaxError: The requested module 'minipass' does not provide an export named 'default'

The spellcheck also failed because minipass was an unrecognized word in package.json.

Fix: Removed the unnecessary minipass override. The expo bump (54.0.10 → 54.0.22) is the actual security fix for this PR; the minipass override was not needed.

Note: The license/snyk check failure (1 test failed) is a third-party Snyk license policy check that may need manual review — it's not fixable via code changes.

glob@13.0.6 (from expo 54.0.22) requires minipass@^7.1.3, but the
lockfile had minipass@7.1.2 pinned which does not satisfy the
constraint, causing npm ci to fail on all builds.

Co-authored-by: Michał Jasikowski <mjasikowski@users.noreply.github.com>
@MelvinBot
Copy link
Contributor Author

Fixed the failing build checks by updating minipass from 7.1.2 → 7.1.3 in package-lock.json.

Root cause: The expo 54.0.22 bump brought in glob@13.0.6, which requires minipass@^7.1.3. The lockfile still had minipass@7.1.2 pinned, causing npm ci to fail with: Invalid: lock file's minipass@7.1.2 does not satisfy minipass@7.1.3.

What was fixed:

  • Build failures (macOS npm ci): Updated lockfile to resolve minipass@7.1.3, which satisfies the ^7.1.3 constraint from glob@13.0.6
  • Storybook test failure (Linux): Was caused by a stale cached node_modules from a previous run. The lockfile change invalidates the cache key, forcing a fresh npm ci install with the correct dependency tree

Remaining: license/snyk failure
minipass@7.1.3 changed its license from ISC to BlueOak-1.0.0 (a permissive open-source license). This is likely what Snyk is flagging. Since glob@13.0.6 (required by expo 54.0.22) requires minipass@^7.1.3, this license change is unavoidable for this security bump. The BlueOak-1.0.0 license may need to be approved in Expensify's Snyk organization settings.

@MelvinBot
Copy link
Contributor Author

The only failing check is license/snyk — a Snyk license compliance check. This is not fixable by code changes.

Root cause: The expo bump (54.0.10 → 54.0.22) transitively bumped lightningcss from 1.30.1 to 1.31.1, which added a new optional platform binary: lightningcss-android-arm64 (license: MPL-2.0). This is the only new lightningcss platform package — the other 10 (darwin-arm64, darwin-x64, linux-x64-gnu, etc.) already exist on main with the same MPL-2.0 license and are presumably approved in Snyk.

What's needed: A Snyk admin needs to approve the lightningcss-android-arm64 package in the Snyk license policy (same license as the 10 other lightningcss-* binaries already approved). Alternatively, if there's a Snyk ignore or policy override mechanism, that would work too.

All other checks are either passing or still running.

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.

2 participants