Skip to content

[No QA] Add npm min-release-age cooldown for supply chain protection - #95897

Merged
roryabraham merged 7 commits into
mainfrom
claude-npm-min-release-age
Sep 17, 2026
Merged

roryabraham merged 7 commits into
mainfrom
claude-npm-min-release-age

Conversation

@NicolasBonet

@NicolasBonet NicolasBonet commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

MOBILE-EXPENSIFY: https://github.com/Expensify/Mobile-Expensify/pull/14014

Explanation of Change

  • Adds a 7-day npm install cooldown (min-release-age=7) so freshly published, possibly malicious package versions are not resolved; npm ci and lockfile-clean installs are unaffected.
  • The eight self-published packages App installs from the registry are excluded because we publish and consume them same-day.

Design doc: https://expensify.enterprise.slack.com/docs/T03SC9DTT/F0BNG8W2FML

Fixed Issues

$ https://github.com/Expensify/Expensify/issues/636594

Tests

This is a tooling-only change with no runtime app code affected.

  1. On node 26.5.0 (nvm install), verify npm --version prints 11.17.0.
  2. Run npm ci and verify it completes without errors.
  3. Run npm install @types/node@latest --dry-run and verify npm resolves a version published at least 7 days ago (currently 22.20.1, not the fresh 22.20.3).
  4. Run npm install @types/node@latest --dry-run --min-release-age=0 and verify npm resolves the fresh version, showing the bypass works.
  5. Run npm config get min-release-age-exclude and verify it lists the eight self-published packages.
  • Verify that no errors appear in the JS console

Offline tests

None — no runtime app code changes. npm install behavior offline is unchanged (installs resolve from cache/lockfile).

QA Steps

[No QA] — tooling-only change, no app behavior affected.

  • 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 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 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)
  • 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)
  • 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.
  • 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.

@NicolasBonet
NicolasBonet force-pushed the claude-npm-min-release-age branch from 2d26918 to 387a004 Compare July 16, 2026 23:22
@NicolasBonet NicolasBonet changed the title [No QA] Add npm min-release-age cooldown for supply chain protection [Hold App#96205] [No QA] Add npm min-release-age cooldown for supply chain protection Jul 17, 2026
@NicolasBonet NicolasBonet changed the title [Hold App#96205] [No QA] Add npm min-release-age cooldown for supply chain protection [HOLD App#96205][No QA] Add npm min-release-age cooldown for supply chain protection Jul 17, 2026
@NicolasBonet
NicolasBonet force-pushed the claude-npm-min-release-age branch from 1d20b64 to a1c538e Compare July 22, 2026 14:55
Bump npm to 11.18.0 (first 11.x line with min-release-age-exclude) and
configure a 7-day install cooldown in .npmrc, exempting Expensify-owned
packages. CI installs npm 11 explicitly since Node 20 bundles npm 10.

Lockfile regenerated with npm 11: platform-specific optional deps
(@img/sharp-*) are now recorded, and optional peer dependencies are no
longer auto-installed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

Add setup-npm.sh script for installing the pinned npm version

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

Scope PR to the min-release-age cooldown only

The npm engine bump and setup-npm tooling are no longer needed: the Node 26
upgrade (#96205) ships npm 11.17.0 bundled, which already supports
min-release-age (added in npm 11.10.0).

Generate new package lock
@NicolasBonet
NicolasBonet force-pushed the claude-npm-min-release-age branch from 6f61238 to e922080 Compare July 23, 2026 15:50
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@NicolasBonet NicolasBonet changed the title [HOLD App#96205][No QA] Add npm min-release-age cooldown for supply chain protection [No QA] Add npm min-release-age cooldown for supply chain protection Jul 23, 2026
@NicolasBonet
NicolasBonet marked this pull request as ready for review September 16, 2026 17:35
@NicolasBonet
NicolasBonet requested a review from a team as a code owner September 16, 2026 17:35
@melvin-bot
melvin-bot Bot requested review from getusha and removed request for a team September 16, 2026 17:35
@melvin-bot

melvin-bot Bot commented Sep 16, 2026

Copy link
Copy Markdown

@getusha Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button]

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 16, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ⚠️ Failed 2026-09-16T18:06:02.884186Z 0efd56e Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@roryabraham
roryabraham merged commit 274f0a6 into main Sep 17, 2026
24 of 25 checks passed
@roryabraham
roryabraham deleted the claude-npm-min-release-age branch September 17, 2026 18:37
@OSBotify

Copy link
Copy Markdown
Contributor

✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release.

@github-actions

Copy link
Copy Markdown
Contributor

🚧 roryabraham has triggered a test Expensify/App build. You can view the workflow run here.

@github-actions

Copy link
Copy Markdown
Contributor

🧪🧪 Use the links below to test this adhoc build on Android, iOS, and Web. Happy testing! 🧪🧪
Built from App PR #95897.

Android 🤖 iOS 🍎
https://ad-hoc-expensify-cash.s3.us-east-1.amazonaws.com/rock-artifacts/ad-hoc/rock-android-Adhoc-274f0a6-9e87e9f-953626c178eba1c2943915099254840e9931b597/index.html ❌ FAILED ❌
Android The QR code can't be generated, because the iOS build failed
Web 🕸️
https://95897.pr-testing.expensify.com
Web

👀 View the workflow run that generated this build 👀

@OSBotify

Copy link
Copy Markdown
Contributor

🚀 Deployed to staging by https://github.com/roryabraham in version: 9.4.82-0 🚀

platform result
🕸 web 🕸 success ✅
🤖 android 🤖 cancelled 🔪
🍎 iOS 🍎 cancelled 🔪

@OSBotify

Copy link
Copy Markdown
Contributor

🚀 Deployed to staging by https://github.com/roryabraham in version: 9.4.86-0 🚀

platform result
🕸 web 🕸 success ✅
🤖 android 🤖 success ✅
🍎 iOS 🍎 success ✅

@OSBotify

Copy link
Copy Markdown
Contributor

🚀 Deployed to staging by https://github.com/roryabraham in version: 9.4.89-0 🚀

platform result
🕸 web 🕸 success ✅
🤖 android 🤖 success ✅
🍎 iOS 🍎 success ✅

@OSBotify

Copy link
Copy Markdown
Contributor

🚀 Deployed to production by https://github.com/luacmartins in version: 9.4.89-0 🚀

platform result
🕸 web 🕸 success ✅
🤖 android 🤖 success ✅
🍎 iOS 🍎 failure ❌

Bundle Size Analysis (Sentry):

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.

3 participants