Skip to content

fix: remediate dependency vulnerabilities and patch braces recursion - #100

Merged
legions-developer merged 1 commit into
mainfrom
gurbinder/fix-security-vulnerabilities
Oct 5, 2026
Merged

legions-developer merged 1 commit into
mainfrom
gurbinder/fix-security-vulnerabilities

Conversation

@legions-developer

Copy link
Copy Markdown
Owner

This fixes the vulnerable dependency versions behind all 98 open Dependabot alerts retrieved on October 5, 2026 (1 critical, 50 high, 42 medium, 5 low), across 28 packages. It also adds a local mitigation for an additional unpatched braces advisory found by the npm registry audit.

Changes

  • Update Better Auth within 1.6 (1.6.33), devalue (5.9.4), Axios (1.20.0), tar (7.5.22), PostCSS (8.5.29), and the affected transitive dependency versions in yarn.lock.
  • Upgrade Sentry from 9 to 10.76 with a matching OpenTelemetry dependency tree (core 2.11.0). Migrate its Next configuration import and debug-logging option.
  • Remove the unused Jotai DevTools dependency and commented UI, eliminating vulnerable jsondiffpatch and Immutable dependencies.
  • Remove the obsolete fast-xml-parser 4.x override so AWS uses its supported, fixed 5.7.3 version.
  • Apply scoped compatible overrides for the legacy Drizzle esbuild loader, MDX TOML parser, and MDX UUID dependency. Add integration regression coverage.
  • Resolve node-gyp to 12.4.0, removing make-fetch-happen, http-cache-semantics, and ip-address from the tree. http-cache-semantics 4.3.0 still reproduces the max-stale bug despite being outside the listed vulnerable range, so updating only that package would not fix it. Node now requires >=22.9.0.

Code changes required

Small Sentry/Next configuration changes and removal of unused DevTools references are included. Invoice logic, OAuth configuration, database schema, and migrations need no changes. The new braces mitigation changes third-party code through a native Yarn patch.

Remaining upstream advisory

GHSA-vfj7-8cjw-p6xm has no upstream fixed release. The committed Yarn patch limits combined brace/parenthesis nesting and recursive AST traversal to 100 levels, rejecting deeper input with SyntaxError. Nine regression tests cover ordinary patterns, exact limits, hostile input, micromatch callers, and direct AST calls.

Version-based scanners can continue to flag braces 3.0.3. No advisory is dismissed or excluded. Yarn audit reports no advisories for the patched tree, but a separate npm bulk audit that explicitly includes every locked version confirms one remaining upstream advisory: braces, locally mitigated here. Replace the patch when an upstream fixed release is available.

Validation

  • yarn install --immutable
  • node --experimental-strip-types --test scripts/*.test.mjs apps/web/src/lib/invoice/move-invoice-to-server.test.mjs — 94 passed
  • yarn test:security — 14 passed
  • yarn workspace web exec tsc --noEmit --incremental false
  • Next production build, lint, and final OpenNext/Cloudflare bundle build
  • Local production smoke checks: /, /dashboard, /api/auth/ok, and unauthenticated /api/auth/get-session returned 200
  • Independently matched all 98 original advisory ranges against the final lockfile: zero vulnerable matches

Builds used local placeholder configuration; external Google OAuth and production services were not exercised. The separate GitHub code-scanning endpoint returned 404: no analysis found and a missing admin:repo_hook scope message; that check remains unverified pending reauthentication. Dependabot access worked successfully.

@coderabbitai

coderabbitai Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

📝 Walkthrough

Walkthrough

The changes raise the Node.js minimum to 22.9.0, update dependency resolutions, and add security regression tests. The web app also updates its Sentry configuration and dependencies, and removes Jotai DevTools references.

Changes

Dependency Security

Layer / File(s) Summary
Dependency constraints and test wiring
package.json, README.md, docs/cloudflare.md
The root manifest raises the Node.js minimum, updates dependency resolutions, and adds a security test command. The README adds dependency security guidance, and the Cloudflare setup instructions document the new Node.js minimum.
Brace nesting regression tests
scripts/security-braces.test.mjs
Tests cover brace parsing and expansion, the 100-level nesting limit, literal brace characters, deeply nested input, and nested AST input.
Dependency behavior regression tests
scripts/security-dependencies.test.mjs
Tests cover data transformer behavior, MDX frontmatter, Drizzle configuration loading, and S3 XML response parsing.

Web Tooling

Layer / File(s) Summary
Sentry and Jotai configuration
apps/web/package.json, apps/web/next.config.ts, apps/web/src/providers/jotai-provider.tsx
The web app updates Sentry’s version, import path, and logger configuration. It removes the Jotai DevTools dependency and configuration, and renders the shared Jotai provider without the commented DevTools code.

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

Change: Bug fix

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 4 files. (4 skipped: 4… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the dependency vulnerability remediation and braces recursion patch, which are the main changes.
Description check ✅ Passed The description directly explains the dependency updates, braces mitigation, related code changes, and validation.
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.
Full details: Docstring Coverage

Explanation

Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 4 files. (4 skipped: 4 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Warning

Some tools did not complete. Review the errors below.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

package.json

Oops! Something went wrong! :(

ESLint: 9.30.0

Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: Package subpath './library.js' is not defined by "exports" in /node_modules/@invoicely/eslint-config/package.json
Referenced from: /.eslintrc.js
at exportsNotFound (node:internal/modules/esm/resolve:310:10)
at packageExportsResolve (node:internal/modules/esm/resolve:658:9)
at resolveExports (node:internal/modules/cjs/loader:685:36)
at Module._findPath (node:internal/modules/cjs/loader:752:31)
at Module._resolveFilename (node:internal/modules/cjs/loader:1461:27)
at wrapResolveFilename (node:internal/modules/cjs/loader:1049:27)
at resolveForCJSWithHooks (node:internal/modules/cjs/loader:1094:12)
at require.resolve (node:internal/modules/helpers:171:31)
at Object.resolve (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2447:46)
at ConfigArrayFactory._loadExtendedShareableConfig (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3383:33)
(node:2) ESLintRCWarning: You are using an eslintrc configuration file, which is deprecated and support will be removed in v10.0.0. Please migrate to an eslint.config.js file. See https://eslint.org/docs/latest/use/configure/migration-guide for details. An eslintrc configuration file is used because you have the ESLINT_USE_FLAT_CONFIG environment variable set to false. If you want to use an eslint.config.js file, remove the environment variable. If you want to find the location of the eslintrc configuration file, use the --debug flag.
(Use node --trace-warnings ... to show where the warning was created)

scripts/security-braces.test.mjs

ESLint skipped: the matched ESLint configuration already failed (unknown).

scripts/security-dependencies.test.mjs

ESLint skipped: the matched ESLint configuration already failed (unknown).


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.

@github-actions

github-actions Bot commented Oct 5, 2026

Copy link
Copy Markdown

Preview database and deployment

Commit: 518aadf717b1

Migration command and Cloudflare build/deploy completed successfully. There may have been no pending migrations.

Cloudflare build logs

Migration status is inferred from the required migration hook and the overall Cloudflare result. Build logs contain the individual migration output.

@cloudflare-workers-and-pages

Copy link
Copy Markdown

🚀 Deploying Preview to Cloudflare 🚀

Preview URL: https://gurbinder-fix-security-vulnerabilities.preview.invoicely.gg (commit 518aadf)

This URL reflects your latest Preview deployment

Preview Deployments by commit

Status Deployment URL Commit Updated (UTC) See this deployment's details
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://5cf508bc.preview.invoicely.gg 518aadf 2026-10-05T15:56:27.729Z Visit the dashboard ↗

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
scripts/security-dependencies.test.mjs (1)

92-99: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Exercise Drizzle Kit’s config-loading path.

This test exercises @esbuild-kit/core-utils’s transformSync and evaluates the config under an isolated environment. It does not load the config through Drizzle Kit. A loader regression can therefore leave this test green even though the db:generate, db:migrate, db:push, or db:studio workflows fail. Keep the isolated environment and add a check through a supported Drizzle Kit command or loader.


ℹ️ Review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 4a1d7d1c-e871-4aaa-9111-0e193a61a6ee
📥 Commits

Reviewing files that changed from the base of the PR and between 20ec36a and 518aadf.

⛔ Files ignored due to path filters (2)
  • .yarn/patches/braces-npm-3.0.3-security.patch is excluded by !**/.yarn/**
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (8)
  • README.md
  • apps/web/next.config.ts
  • apps/web/package.json
  • apps/web/src/providers/jotai-provider.tsx
  • docs/cloudflare.md
  • package.json
  • scripts/security-braces.test.mjs
  • scripts/security-dependencies.test.mjs

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 3 remain after this review.

Comment on lines +2 to +4
import remarkMdxFrontmatter from "remark-mdx-frontmatter";
import { transformSync } from "@esbuild-kit/core-utils";
import remarkFrontmatter from "remark-frontmatter";

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🔎 Supported by static analysis

🏁 Script executed:

#!/bin/bash
set -u
printf '%s\n' '--- changed test at reviewed head ---'
git show 518aadf717b18b0134f1f5a9d1fc8959f4c64fbf:scripts/security-dependencies.test.mjs | nl -ba
printf '%s\n' '--- manifests and package-manager config at reviewed head ---'
git ls-tree -r --name-only 518aadf717b18b0134f1f5a9d1fc8959f4c64fbf | rg '(^|/)(package\.json|yarn\.lock|\.yarnrc\.yml|\.npmrc|pnpm-lock\.yaml)$' || true
for f in package.json .yarnrc.yml; do
  if git cat-file -e "518aadf717b18b0134f1f5a9d1fc8959f4c64fbf:$f" 2>/dev/null; then
    printf '%s\n' "--- $f at head ---"
    git show "518aadf717b18b0134f1f5a9d1fc8959f4c64fbf:$f"
  fi
done
printf '%s\n' '--- PR base-to-head change for test and dependency configuration ---'
git diff --stat 20ec36ad3b0bf9fb140d1a0ee512c0070a7b03ab 518aadf717b18b0134f1f5a9d1fc8959f4c64fbf -- scripts/security-dependencies.test.mjs package.json .yarnrc.yml yarn.lock
git diff --unified=5 20ec36ad3b0bf9fb140d1a0ee512c0070a7b03ab 518aadf717b18b0134f1f5a9d1fc8959f4c64fbf -- scripts/security-dependencies.test.mjs package.json .yarnrc.yml
printf '%s\n' '--- declarations and linker references in tracked files at head ---'
git grep -n -E '"(remark-mdx-frontmatter|@esbuild-kit/core-utils|remark-frontmatter|@mdx-js/mdx)"|nodeLinker|pnp' 518aadf717b18b0134f1f5a9d1fc8959f4c64fbf -- ':!yarn.lock' || true

Repository: legions-developer/invoicely

Length of output: 35325


🤖 get_repo_knowledge executed:

get_repo_knowledge legions-developer/invoicely /tmp/coderabbit-repo-knowledge/legions-developer-invoicely-b84fcfe7/architecture /tmp/coderabbit-repo-knowledge/legions-developer-invoicely-b84fcfe7/conventions

Length of output: 23166


🏁 Script executed:

#!/bin/bash
set -u
head=518aadf717b18b0134f1f5a9d1fc8959f4c64fbf
printf '%s\n' '--- numbered root manifest dependency section ---'
git show "$head:package.json" | nl -ba | sed -n '1,80p'
printf '%s\n' '--- numbered Yarn linker config ---'
git show "$head:.yarnrc.yml" | nl -ba
printf '%s\n' '--- focused lockfile entries for direct test imports ---'
for name in '@esbuild-kit/core-utils' 'remark-mdx-frontmatter' 'remark-frontmatter' '@mdx-js/mdx'; do
  printf '%s\n' "--- $name ---"
  git grep -n -F -- "$name@" "$head" -- yarn.lock || true
done

Repository: legions-developer/invoicely

Length of output: 4435


🌐 Web query:

official Yarn 4 node-modules linker hoisting undeclared dependencies root workspace dependency resolution

💡 Result:

**Yarn 4’s `node-modules` linker can make undeclared dependencies resolvable by accident.** It creates a conventional `node_modules` tree, and with the default `nmHoistingLimits: none`, dependencies may be hoisted to the project root. Node’s upward search can then let a workspace resolve a package it never declared—a “ghost dependency.” That’s filesystem resolution, not Yarn treating the root workspace’s dependencies as dependencies of every workspace. ([yarnpkg.com](https://yarnpkg.com/configuration/yarnrc/?utm_source=openai))

To constrain hoisting, set `nmHoistingLimits: workspaces` in `.yarnrc.yml`; Yarn documents that this keeps packages from being hoisted past the workspace that depends on them. It changes the install layout, though, and isn’t a substitute for declaring each workspace’s actual dependencies. ([yarnpkg.com](https://yarnpkg.com/configuration/yarnrc/?utm_source=openai))

For strict undeclared-dependency checks, Yarn’s PnP linker is the documented option: it tracks dependency relationships and rejects access to packages that aren’t declared. ([yarnpkg.com](https://yarnpkg.com/features/pnp?utm_source=openai))

The Yarn docs establish the linker and hoisting behavior; they don’t guarantee that every particular undeclared package will resolve from every workspace—the result depends on the installed layout and Node’s resolution.

Citations:

- 1: https://yarnpkg.com/configuration/yarnrc/?utm_source=openai
- 2: https://yarnpkg.com/configuration/yarnrc/?utm_source=openai
- 3: https://yarnpkg.com/features/pnp?utm_source=openai

🏁 Script executed:

#!/bin/bash
set -u
head=518aadf717b18b0134f1f5a9d1fc8959f4c64fbf
for name in '@esbuild-kit/core-utils' 'remark-mdx-frontmatter' 'remark-frontmatter' '@mdx-js/mdx'; do
  printf '%s\n' "--- lockfile references for $name ---"
  git grep -n -F -- "\"$name\":" "$head" -- yarn.lock || true
done
printf '%s\n' '--- app manifest MDX-related dependencies ---'
git show "$head:apps/web/package.json" | nl -ba | rg -n -C 2 'mdx|remark|esbuild|dependencies|devDependencies' || true
printf '%s\n' '--- package manager settings ---'
git show "$head:.yarnrc.yml"
git show "$head:package.json" | nl -ba | sed -n '8,14p;26,30p;38,60p'

Repository: legions-developer/invoicely

Length of output: 2574


Declare the test’s direct dependencies.

test:security runs this file from the repository root. Its four top-level imports are not declared in the root manifest, so the test can rely on Yarn hoisting their packages to the root. A different node_modules layout can make module loading fail before any assertion runs.

Suggested manifest change
   "devDependencies": {
     "@effect/language-service": "^0.23.3",
+    "@esbuild-kit/core-utils": "^3.3.2",
     "@invoicely/eslint-config": "workspace:*",
     "@invoicely/typescript-config": "workspace:*",
+    "@mdx-js/mdx": "^3.0.0",
     "@types/node": "^22.15.3",
     "dotenv-cli": "^8.0.0",
     "husky": "^9.1.7",
     "patch-package": "^8.0.0",
     "prettier": "^3.5.3",
     "prettier-plugin-sort-imports": "^1.8.7",
     "prettier-plugin-tailwindcss": "^0.6.11",
+    "remark-frontmatter": "^5.0.0",
+    "remark-mdx-frontmatter": "^4.0.0",
     "turbo": "^2.9.15",
     "typescript": "5.8.2"

@legions-developer
legions-developer merged commit 7b2bc13 into main Oct 5, 2026
3 of 4 checks passed
@github-actions

github-actions Bot commented Oct 5, 2026

Copy link
Copy Markdown

Production database and deployment

Commit: 7b2bc13126c7

Migration command and Cloudflare build/deploy completed successfully. There may have been no pending migrations.

Cloudflare build logs

Migration status is inferred from the required migration hook and the overall Cloudflare result. Build logs contain the individual migration output.

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