Repository navigation
fix: remediate dependency vulnerabilities and patch braces recursion - #100
Conversation
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. 📝 WalkthroughWalkthroughThe 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. ChangesDependency Security
Web Tooling
Estimated code review effort: 3 (Moderate) | ~25 minutes Change: Bug fix 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Docstring CoverageExplanation 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.)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Warning Some tools did not complete. Review the errors below. 🔧 ESLint
package.jsonOops! 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 scripts/security-braces.test.mjsESLint skipped: the matched ESLint configuration already failed (unknown). scripts/security-dependencies.test.mjsESLint 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. Comment |
|
Preview database and deployment Commit: Migration command and Cloudflare build/deploy completed successfully. There may have been no pending migrations. Migration status is inferred from the required migration hook and the overall Cloudflare result. Build logs contain the individual migration output. |
🚀 Deploying Preview to Cloudflare 🚀Preview URL: https://gurbinder-fix-security-vulnerabilities.preview.invoicely.gg (commit 518aadf)This URL reflects your latest Preview deploymentPreview Deployments by commit
|
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
scripts/security-dependencies.test.mjs (1)
92-99: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy liftExercise Drizzle Kit’s config-loading path.
This test exercises
@esbuild-kit/core-utils’stransformSyncand 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 thedb:generate,db:migrate,db:push, ordb:studioworkflows 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
⛔ Files ignored due to path filters (2)
.yarn/patches/braces-npm-3.0.3-security.patchis excluded by!**/.yarn/**yarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (8)
README.mdapps/web/next.config.tsapps/web/package.jsonapps/web/src/providers/jotai-provider.tsxdocs/cloudflare.mdpackage.jsonscripts/security-braces.test.mjsscripts/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.
| import remarkMdxFrontmatter from "remark-mdx-frontmatter"; | ||
| import { transformSync } from "@esbuild-kit/core-utils"; | ||
| import remarkFrontmatter from "remark-frontmatter"; |
There was a problem hiding this comment.
🩺 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' || trueRepository: 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
doneRepository: 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"|
Production database and deployment Commit: Migration command and Cloudflare build/deploy completed successfully. There may have been no pending migrations. Migration status is inferred from the required migration hook and the overall Cloudflare result. Build logs contain the individual migration output. |
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
bracesadvisory found by the npm registry audit.Changes
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 inyarn.lock.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 --immutablenode --experimental-strip-types --test scripts/*.test.mjs apps/web/src/lib/invoice/move-invoice-to-server.test.mjs— 94 passedyarn test:security— 14 passedyarn workspace web exec tsc --noEmit --incremental false/,/dashboard,/api/auth/ok, and unauthenticated/api/auth/get-sessionreturned 200Builds used local placeholder configuration; external Google OAuth and production services were not exercised. The separate GitHub code-scanning endpoint returned
404: no analysis foundand a missingadmin:repo_hookscope message; that check remains unverified pending reauthentication. Dependabot access worked successfully.