[Fix] Remove neon CLI dependency and pin all JS dependencies

Remove @neondatabase/api-client and neonctl to address CVE-2026-25639
(axios supply chain vulnerability). Pin all JS dependencies to exact
versions across all package.json files to prevent future supply chain
attacks via semver range resolution.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Yuneng Jiang 2026-04-01 16:15:32 -07:00
parent 7250cba3db
commit 006d481025
No known key found for this signature in database
13 changed files with 158 additions and 296 deletions

View File

@ -3233,31 +3233,9 @@ jobs:
name: Install Playwright Browsers
command: |
npx playwright install
- run:
name: Install Neon CLI
command: |
npm i -g neonctl
- run:
name: Create Neon branch
command: |
export EXPIRES_AT=$(date -u -d "+3 hours" +"%Y-%m-%dT%H:%M:%SZ")
echo "Expires at: $EXPIRES_AT"
neon branches create \
--project-id $NEON_PROJECT_ID \
--name preview/commit-${CIRCLE_SHA1:0:7}-<< parameters.browser >> \
--expires-at $EXPIRES_AT \
--parent br-fancy-paper-ad1olsb3 \
--api-key $NEON_API_KEY || true
- run:
name: Run Docker container
command: |
E2E_UI_TEST_DATABASE_URL=$(neon connection-string \
--project-id $NEON_PROJECT_ID \
--api-key $NEON_API_KEY \
--branch preview/commit-${CIRCLE_SHA1:0:7}-<< parameters.browser >> \
--database-name yuneng-trial-db \
--role neondb_owner)
echo $E2E_UI_TEST_DATABASE_URL
docker run -d \
-p 4000:4000 \
-e DATABASE_URL=$E2E_UI_TEST_DATABASE_URL \
@ -3531,7 +3509,7 @@ workflows:
only:
- main
- /litellm_.*/
# - e2e_ui_testing: # migrate to dynamic db - currently requires neon cli
# - e2e_ui_testing:
# name: e2e_ui_testing_chromium
# browser: chromium
# context: e2e_ui_tests

View File

@ -160,7 +160,6 @@ run_grype_scans() {
"CVE-2026-0775" # npm cli incorrect permission assignment - no fix available yet, npm is only used at build/prisma-generate time
"GHSA-3ppc-4f35-3m26" # minimatch ReDoS via repeated wildcards - from nodejs_wheel bundled npm, not used in application runtime code
"GHSA-83g3-92jg-28cx" # tar arbitrary file read/write via hardlink - from nodejs_wheel bundled npm, not used in application runtime code
"CVE-2026-25639" # axios DoS via __proto__ in mergeConfig - transitive dev dep via @neondatabase/api-client, not imported in application code
"CVE-2026-2297" # Python 3.13 SourcelessFileLoader audit hook bypass - no fix available in base image
"GHSA-qffp-2rhf-9h96" # tar hardlink path traversal - from nodejs_wheel bundled npm, not used in application runtime code
"CVE-2026-2673" # OpenSSL 3.6.1 TLS 1.3 key exchange group negotiation issue - no fix available yet

View File

@ -13,18 +13,18 @@
"@docusaurus/plugin-ideal-image": "3.8.1",
"@docusaurus/preset-classic": "3.8.1",
"@docusaurus/theme-mermaid": "3.8.1",
"@inkeep/cxkit-docusaurus": "^0.5.89",
"@mdx-js/react": "^3.0.0",
"clsx": "^1.2.1",
"prism-react-renderer": "^1.3.5",
"react": "^18.0.0 || ^19.0.0",
"react-dom": "^18.0.0 || ^19.0.0",
"sharp": "^0.32.6",
"uuid": "^9.0.1"
"@inkeep/cxkit-docusaurus": "0.5.107",
"@mdx-js/react": "3.1.1",
"clsx": "1.2.1",
"prism-react-renderer": "1.3.5",
"react": "18.3.1",
"react-dom": "18.3.1",
"sharp": "0.32.6",
"uuid": "9.0.1"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "3.8.1",
"dotenv": "^16.4.5"
"dotenv": "16.6.1"
},
"engines": {
"node": ">=16.14",
@ -20403,13 +20403,6 @@
"url": "https://opencollective.com/webpack"
}
},
"node_modules/search-insights": {
"version": "2.17.3",
"resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.17.3.tgz",
"integrity": "sha512-RQPdCYTa8A68uM2jwxoY842xDhvx3E5LFL1LxvxCNMev4o5mLuokczhzjAgGwUZBAmOKZknArSxLKmXtIi2AxQ==",
"license": "MIT",
"peer": true
},
"node_modules/section-matter": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz",

View File

@ -19,18 +19,18 @@
"@docusaurus/plugin-ideal-image": "3.8.1",
"@docusaurus/preset-classic": "3.8.1",
"@docusaurus/theme-mermaid": "3.8.1",
"@inkeep/cxkit-docusaurus": "^0.5.89",
"@mdx-js/react": "^3.0.0",
"clsx": "^1.2.1",
"prism-react-renderer": "^1.3.5",
"react": "^18.0.0 || ^19.0.0",
"react-dom": "^18.0.0 || ^19.0.0",
"sharp": "^0.32.6",
"uuid": "^9.0.1"
"@inkeep/cxkit-docusaurus": "0.5.107",
"@mdx-js/react": "3.1.1",
"clsx": "1.2.1",
"prism-react-renderer": "1.3.5",
"react": "18.3.1",
"react-dom": "18.3.1",
"sharp": "0.32.6",
"uuid": "9.0.1"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "3.8.1",
"dotenv": "^16.4.5"
"dotenv": "16.6.1"
},
"browserslist": {
"production": [

View File

@ -4,11 +4,11 @@
"deploy": "wrangler deploy --minify src/index.ts"
},
"dependencies": {
"hono": "^4.1.4",
"openai": "^4.29.2"
"hono": "4.1.4",
"openai": "4.29.2"
},
"devDependencies": {
"@cloudflare/workers-types": "^4.20240208.0",
"wrangler": "^3.32.0"
"@cloudflare/workers-types": "4.20240208.0",
"wrangler": "3.32.0"
}
}

View File

@ -5,12 +5,12 @@
"packages": {
"": {
"dependencies": {
"@hono/node-server": "^1.10.1",
"hono": "^4.12.7"
"@hono/node-server": "1.19.6",
"hono": "4.12.7"
},
"devDependencies": {
"@types/node": "^20.11.17",
"tsx": "^4.7.1"
"@types/node": "20.19.25",
"tsx": "4.20.6"
}
},
"node_modules/@esbuild/aix-ppc64": {

View File

@ -3,11 +3,11 @@
"dev": "tsx watch src/index.ts"
},
"dependencies": {
"@hono/node-server": "^1.10.1",
"hono": "^4.12.7"
"@hono/node-server": "1.19.6",
"hono": "4.12.7"
},
"devDependencies": {
"@types/node": "^20.11.17",
"tsx": "^4.7.1"
"@types/node": "20.19.25",
"tsx": "4.20.6"
}
}

View File

@ -1,14 +1,14 @@
{
"dependencies": {
"prism-react-renderer": "^2.4.1",
"prisma": "^5.17.0",
"react-copy-to-clipboard": "^5.1.0"
"prism-react-renderer": "2.4.1",
"prisma": "5.17.0",
"react-copy-to-clipboard": "5.1.0"
},
"devDependencies": {
"@testing-library/jest-dom": "^6.8.0",
"@testing-library/react": "^14.3.1",
"@types/react-copy-to-clipboard": "^5.0.7",
"jest": "^29.7.0"
"@testing-library/jest-dom": "6.8.0",
"@testing-library/react": "14.3.1",
"@types/react-copy-to-clipboard": "5.0.7",
"jest": "29.7.0"
},
"overrides": {
"glob": "13.0.0",

View File

@ -8,7 +8,7 @@
"author": "",
"license": "ISC",
"devDependencies": {
"@playwright/test": "^1.47.2",
"@types/node": "^22.5.5"
"@playwright/test": "1.56.1",
"@types/node": "22.19.1"
}
}

View File

@ -6,22 +6,22 @@
"test:watch": "jest --watch"
},
"devDependencies": {
"@testing-library/react": "^14.0.0",
"@testing-library/jest-dom": "^6.0.0",
"@types/jest": "^29.5.0",
"@types/react": "^18.2.0",
"@types/react-dom": "^18.2.0",
"identity-obj-proxy": "^3.0.0",
"jest": "^29.5.0",
"jest-environment-jsdom": "^29.5.0",
"ts-jest": "^29.1.0",
"typescript": "^5.0.0"
"@testing-library/react": "14.3.1",
"@testing-library/jest-dom": "6.9.1",
"@types/jest": "29.5.14",
"@types/react": "18.3.27",
"@types/react-dom": "18.3.7",
"identity-obj-proxy": "3.0.0",
"jest": "29.7.0",
"jest-environment-jsdom": "29.7.0",
"ts-jest": "29.4.5",
"typescript": "5.9.3"
},
"dependencies": {
"antd": "^5.12.5",
"@ant-design/icons": "^5.0.0",
"react": "^18.2.0",
"react-dom": "^18.2.0"
"antd": "5.29.1",
"@ant-design/icons": "5.6.1",
"react": "18.3.1",
"react-dom": "18.3.1"
},
"overrides": {
"glob": "13.0.0",

View File

@ -8,66 +8,65 @@
"name": "litellm-dashboard",
"version": "0.1.0",
"dependencies": {
"@anthropic-ai/sdk": "^0.54.0",
"@headlessui/tailwindcss": "^0.2.0",
"@heroicons/react": "^1.0.6",
"@remixicon/react": "^4.1.1",
"@tanstack/react-pacer": "^0.2.0",
"@tanstack/react-query": "^5.64.1",
"@tanstack/react-table": "^8.20.6",
"@tremor/react": "^3.13.3",
"@types/papaparse": "^5.3.15",
"antd": "^5.13.2",
"cva": "^1.0.0-beta.3",
"dayjs": "^1.11.19",
"jwt-decode": "^4.0.0",
"lucide-react": "^0.513.0",
"moment": "^2.30.1",
"next": "^16.1.7",
"openai": "^4.93.0",
"papaparse": "^5.5.2",
"react": "^18.3.1",
"react-copy-to-clipboard": "^5.1.0",
"react-dom": "^18.3.1",
"react-json-view-lite": "^2.5.0",
"react-markdown": "^9.0.1",
"react-syntax-highlighter": "^15.6.6",
"remark-gfm": "^4.0.1",
"tailwind-merge": "^3.2.0",
"uuid": "^11.1.0"
"@anthropic-ai/sdk": "0.54.0",
"@headlessui/tailwindcss": "0.2.2",
"@heroicons/react": "1.0.6",
"@remixicon/react": "4.9.0",
"@tanstack/react-pacer": "0.2.0",
"@tanstack/react-query": "5.90.20",
"@tanstack/react-table": "8.21.3",
"@tremor/react": "3.18.7",
"@types/papaparse": "5.5.2",
"antd": "5.29.3",
"cva": "1.0.0-beta.4",
"dayjs": "1.11.19",
"jwt-decode": "4.0.0",
"lucide-react": "0.513.0",
"moment": "2.30.1",
"next": "16.1.7",
"openai": "4.104.0",
"papaparse": "5.5.3",
"react": "18.3.1",
"react-copy-to-clipboard": "5.1.0",
"react-dom": "18.3.1",
"react-json-view-lite": "2.5.0",
"react-markdown": "9.1.0",
"react-syntax-highlighter": "15.6.6",
"remark-gfm": "4.0.1",
"tailwind-merge": "3.4.0",
"uuid": "11.1.0"
},
"devDependencies": {
"@neondatabase/api-client": "^2.6.0",
"@playwright/test": "^1.57.0",
"@tailwindcss/forms": "^0.5.7",
"@testing-library/dom": "^10.4.1",
"@testing-library/jest-dom": "^6.8.0",
"@testing-library/react": "^16.3.0",
"@testing-library/user-event": "^14.6.1",
"@types/babel__traverse": "^7.28.0",
"@types/lodash": "^4.17.15",
"@playwright/test": "1.58.1",
"@tailwindcss/forms": "0.5.11",
"@testing-library/dom": "10.4.1",
"@testing-library/jest-dom": "6.9.1",
"@testing-library/react": "16.3.2",
"@testing-library/user-event": "14.6.1",
"@types/babel__traverse": "7.28.0",
"@types/lodash": "4.17.23",
"@types/node": "20.19.37",
"@types/react": "18.2.48",
"@types/react-copy-to-clipboard": "^5.0.7",
"@types/react-dom": "^18",
"@types/react-syntax-highlighter": "^15.5.11",
"@types/uuid": "^10.0.0",
"@vitest/coverage-v8": "^3.2.4",
"@vitest/ui": "^3.2.4",
"autoprefixer": "^10.4.17",
"dotenv": "^17.2.3",
"eslint": "^9.39.2",
"@types/react-copy-to-clipboard": "5.0.7",
"@types/react-dom": "18.3.7",
"@types/react-syntax-highlighter": "15.5.13",
"@types/uuid": "10.0.0",
"@vitest/coverage-v8": "3.2.4",
"@vitest/ui": "3.2.4",
"autoprefixer": "10.4.24",
"dotenv": "17.2.3",
"eslint": "9.39.2",
"eslint-config-next": "15.5.10",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-unused-imports": "^4.2.0",
"jsdom": "^27.0.0",
"knip": "^5.83.1",
"postcss": "^8.4.33",
"eslint-config-prettier": "10.1.8",
"eslint-plugin-unused-imports": "4.3.0",
"jsdom": "27.4.0",
"knip": "5.83.1",
"postcss": "8.5.6",
"prettier": "3.2.5",
"tailwindcss": "^3.4.1",
"tailwindcss": "3.4.19",
"typescript": "5.9.3",
"vite": "^7.1.11",
"vitest": "^3.2.4"
"vite": "7.3.1",
"vitest": "3.2.4"
},
"engines": {
"node": ">=18.17.0",
@ -1822,16 +1821,6 @@
"@tybys/wasm-util": "^0.10.0"
}
},
"node_modules/@neondatabase/api-client": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/@neondatabase/api-client/-/api-client-2.6.0.tgz",
"integrity": "sha512-NxKE+EFcVwxXU3jj8I/WgueXSyzrXV85AV0nb2SeoKtOa3dlEcTylsdOsMsMeZZeFfQXLyiCOm2nAduGZn9olA==",
"dev": true,
"license": "MIT",
"dependencies": {
"axios": "^1.9.0"
}
},
"node_modules/@next/env": {
"version": "16.1.7",
"resolved": "https://registry.npmjs.org/@next/env/-/env-16.1.7.tgz",
@ -4684,18 +4673,6 @@
"node": ">=4"
}
},
"node_modules/axios": {
"version": "1.13.6",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.13.6.tgz",
"integrity": "sha512-ChTCHMouEe2kn713WHbQGcuYrr6fXTBiu460OTwWrWob16g1bXn4vtz07Ope7ewMozJAnEquLk5lWQWtBig9DQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"follow-redirects": "^1.15.11",
"form-data": "^4.0.5",
"proxy-from-env": "^1.1.0"
}
},
"node_modules/axobject-query": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
@ -6630,27 +6607,6 @@
"dev": true,
"license": "ISC"
},
"node_modules/follow-redirects": {
"version": "1.15.11",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
"integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
"dev": true,
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/RubenVerborgh"
}
],
"license": "MIT",
"engines": {
"node": ">=4.0"
},
"peerDependenciesMeta": {
"debug": {
"optional": true
}
}
},
"node_modules/for-each": {
"version": "0.3.5",
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
@ -10281,13 +10237,6 @@
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
"dev": true,
"license": "MIT"
},
"node_modules/punycode": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",

View File

@ -20,66 +20,65 @@
"knip:fix": "knip --fix"
},
"dependencies": {
"@anthropic-ai/sdk": "^0.54.0",
"@headlessui/tailwindcss": "^0.2.0",
"@heroicons/react": "^1.0.6",
"@remixicon/react": "^4.1.1",
"@tanstack/react-pacer": "^0.2.0",
"@tanstack/react-query": "^5.64.1",
"@tanstack/react-table": "^8.20.6",
"@tremor/react": "^3.13.3",
"@types/papaparse": "^5.3.15",
"antd": "^5.13.2",
"cva": "^1.0.0-beta.3",
"dayjs": "^1.11.19",
"jwt-decode": "^4.0.0",
"lucide-react": "^0.513.0",
"moment": "^2.30.1",
"next": "^16.1.7",
"openai": "^4.93.0",
"papaparse": "^5.5.2",
"react": "^18.3.1",
"react-copy-to-clipboard": "^5.1.0",
"react-dom": "^18.3.1",
"react-json-view-lite": "^2.5.0",
"react-markdown": "^9.0.1",
"react-syntax-highlighter": "^15.6.6",
"remark-gfm": "^4.0.1",
"tailwind-merge": "^3.2.0",
"uuid": "^11.1.0"
"@anthropic-ai/sdk": "0.54.0",
"@headlessui/tailwindcss": "0.2.2",
"@heroicons/react": "1.0.6",
"@remixicon/react": "4.9.0",
"@tanstack/react-pacer": "0.2.0",
"@tanstack/react-query": "5.90.20",
"@tanstack/react-table": "8.21.3",
"@tremor/react": "3.18.7",
"@types/papaparse": "5.5.2",
"antd": "5.29.3",
"cva": "1.0.0-beta.4",
"dayjs": "1.11.19",
"jwt-decode": "4.0.0",
"lucide-react": "0.513.0",
"moment": "2.30.1",
"next": "16.1.7",
"openai": "4.104.0",
"papaparse": "5.5.3",
"react": "18.3.1",
"react-copy-to-clipboard": "5.1.0",
"react-dom": "18.3.1",
"react-json-view-lite": "2.5.0",
"react-markdown": "9.1.0",
"react-syntax-highlighter": "15.6.6",
"remark-gfm": "4.0.1",
"tailwind-merge": "3.4.0",
"uuid": "11.1.0"
},
"devDependencies": {
"@neondatabase/api-client": "^2.6.0",
"@playwright/test": "^1.57.0",
"@tailwindcss/forms": "^0.5.7",
"@testing-library/dom": "^10.4.1",
"@testing-library/jest-dom": "^6.8.0",
"@testing-library/react": "^16.3.0",
"@testing-library/user-event": "^14.6.1",
"@types/babel__traverse": "^7.28.0",
"@types/lodash": "^4.17.15",
"@playwright/test": "1.58.1",
"@tailwindcss/forms": "0.5.11",
"@testing-library/dom": "10.4.1",
"@testing-library/jest-dom": "6.9.1",
"@testing-library/react": "16.3.2",
"@testing-library/user-event": "14.6.1",
"@types/babel__traverse": "7.28.0",
"@types/lodash": "4.17.23",
"@types/node": "20.19.37",
"@types/react": "18.2.48",
"@types/react-copy-to-clipboard": "^5.0.7",
"@types/react-dom": "^18",
"@types/react-syntax-highlighter": "^15.5.11",
"@types/uuid": "^10.0.0",
"@vitest/coverage-v8": "^3.2.4",
"@vitest/ui": "^3.2.4",
"autoprefixer": "^10.4.17",
"dotenv": "^17.2.3",
"eslint": "^9.39.2",
"@types/react-copy-to-clipboard": "5.0.7",
"@types/react-dom": "18.3.7",
"@types/react-syntax-highlighter": "15.5.13",
"@types/uuid": "10.0.0",
"@vitest/coverage-v8": "3.2.4",
"@vitest/ui": "3.2.4",
"autoprefixer": "10.4.24",
"dotenv": "17.2.3",
"eslint": "9.39.2",
"eslint-config-next": "15.5.10",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-unused-imports": "^4.2.0",
"jsdom": "^27.0.0",
"knip": "^5.83.1",
"postcss": "^8.4.33",
"eslint-config-prettier": "10.1.8",
"eslint-plugin-unused-imports": "4.3.0",
"jsdom": "27.4.0",
"knip": "5.83.1",
"postcss": "8.5.6",
"prettier": "3.2.5",
"tailwindcss": "^3.4.1",
"tailwindcss": "3.4.19",
"typescript": "5.9.3",
"vite": "^7.1.11",
"vitest": "^3.2.4"
"vite": "7.3.1",
"vitest": "3.2.4"
},
"overrides": {
"prismjs": "1.30.0",

View File

@ -1,56 +0,0 @@
import { createApiClient, EndpointType } from "@neondatabase/api-client";
import { config } from "dotenv";
import { resolve } from "path";
const envPaths = [
resolve(process.cwd(), "../../.env"), // project root
];
for (const envPath of envPaths) {
config({ path: envPath });
}
const NEON_API_KEY = process.env.NEON_API_KEY!;
const PROJECT_ID = process.env.NEON_PROJECT_ID!;
const PARENT_BRANCH = process.env.NEON_PARENT_BRANCH_ID!;
const NEON_E2E_UI_TEST_DB_NAME = process.env.NEON_E2E_UI_TEST_DB_NAME!;
const apiClient = createApiClient({
apiKey: NEON_API_KEY,
});
export async function createNeonE2ETestingBranch(projectId: string, parentBranchId?: string, expireAt?: string) {
try {
const response = await apiClient.createProjectBranch(projectId, {
branch: {
name: `e2e-local-${crypto.randomUUID()}`,
parent_id: parentBranchId,
expires_at: expireAt ?? new Date(Date.now() + 1000 * 60 * 30).toISOString(),
},
endpoints: [
{
type: EndpointType.ReadWrite,
autoscaling_limit_min_cu: 0.25,
autoscaling_limit_max_cu: 1,
},
],
});
return response;
} catch (error) {
throw error;
}
}
export async function getNeonE2ETestingBranchConnectionString() {
const createBranchResponse = await createNeonE2ETestingBranch(PROJECT_ID, PARENT_BRANCH);
const projectId = createBranchResponse.data.branch.project_id;
const response = await apiClient.getConnectionUri({
database_name: NEON_E2E_UI_TEST_DB_NAME,
role_name: "neondb_owner",
projectId: projectId,
});
console.log("connection string:", response.data.uri);
return response.data.uri;
}
getNeonE2ETestingBranchConnectionString();