Skip to content

Conversation

@mldangelo
Copy link
Member

Summary

  • Replace xlsx (SheetJS) with read-excel-file to eliminate CVE-2023-30533 (high severity prototype pollution)
  • The xlsx package v0.18.5 on npm is vulnerable; the fix (v0.19.3+) was never published to npm
  • read-excel-file is actively maintained, has no vulnerabilities, and is 7x smaller (1MB vs 7.5MB)

Changes

  • Replace xlsx with read-excel-file in devDependencies and optionalDependencies
  • Rewrite src/util/xlsx.ts to use the new library's API
  • Update unit tests for xlsx parsing
  • Update integration tests in testCaseReader

npm audit results

Before After
22 vulnerabilities (21 moderate, 1 high) 21 vulnerabilities (21 moderate, 0 high)

Test plan

  • npm run build passes
  • npm run lint passes
  • Unit tests pass (test/util/xlsx.test.ts)
  • Integration tests pass (test/util/testCaseReader.test.ts)
  • Real xlsx file parsing works (examples/simple-csv/tests.xlsx)

@use-tusk
Copy link
Contributor

use-tusk bot commented Nov 25, 2025

⏩ No test execution environment matched (3971fc5) View output ↗


View check history

Commit Status Output Created (UTC)
6fd8433 ⏩ No test execution environment matched Output Nov 25, 2025 4:12PM
ecc9e1d ⏩ No test execution environment matched Output Nov 25, 2025 4:32PM
32a2791 ⏩ No test execution environment matched Output Nov 25, 2025 5:09PM
dbfcd34 ⏩ No test execution environment matched Output Nov 25, 2025 5:59PM
2790f28 ⏩ No test execution environment matched Output Nov 25, 2025 6:15PM
210db41 ⏩ No test execution environment matched Output Nov 25, 2025 6:28PM
4d586be ⏩ No test execution environment matched Output Nov 25, 2025 6:33PM
ab510fb ⏩ No test execution environment matched Output Nov 25, 2025 6:35PM
3971fc5 ⏩ No test execution environment matched Output Nov 25, 2025 10:26PM

View output in GitHub ↗

Copy link
Contributor

@promptfoo-scanner promptfoo-scanner bot left a comment

Choose a reason for hiding this comment

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

I reviewed this PR which replaces the xlsx library with read-excel-file to address a dependency vulnerability. The changes are focused on Excel file parsing functionality with no LLM-related code modifications.

Minimum severity threshold for this scan: Medium

@promptfoo-scanner
Copy link
Contributor

👍 All Clear

No LLM security vulnerabilities were found in this PR.

JustinBeckwith
JustinBeckwith previously approved these changes Nov 25, 2025
Copy link
Contributor

@JustinBeckwith JustinBeckwith left a comment

Choose a reason for hiding this comment

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

Thank you. I tried doing this before I started, but wasn't quite confident enough in the codebase yet.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 25, 2025

📝 Walkthrough

Walkthrough

This pull request replaces the xlsx package with read-excel-file across the codebase. Changes include: updating package.json dependencies to swap out the old library for the new one, refactoring the core Excel parsing logic in src/util/xlsx.ts to use the new library's API (including sheet name retrieval and row-based data parsing), and updating test files with new mocking strategies to reflect the different API surface. A documentation comment is also updated to reference the new package.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • src/util/xlsx.ts — Core refactoring of parsing logic with API changes (sheet access, row parsing, error handling); requires verification of correctness against the new library's contract
  • test/util/xlsx.test.ts — Comprehensive test updates with new mocking strategy; ensure all scenarios (null values, numeric values, sheet selection by name/index, error cases) are properly covered
  • test/util/testCaseReader.test.ts — Mock adjustments and module reset patterns; verify try/finally cleanup logic is sound
  • package.json — Cross-check that the package replacement is consistent across dependencies, optionalDependencies, and devDependencies sections
  • Error message handling — Validate that error messages referencing read-excel-file are consistent and user-friendly across all affected files

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: replacing xlsx with read-excel-file to address a high severity vulnerability.
Description check ✅ Passed The description is comprehensive and directly related to the changeset, explaining the vulnerability, benefits, specific changes, and test results.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/replace-xlsx-with-read-excel-file

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (5)
examples/simple-csv/promptfooconfig.yaml (1)

8-9: Excel alternative comment now correctly references read-excel-file

The updated comment is aligned with the new Excel reader and the rest of the config (schema line, field order, file:// usage, short description) still looks good. When you next touch this example, consider bumping the provider model to one of the current recommended IDs (e.g., openai:o3-mini / openai:gpt-4o-mini) to match the examples guidelines, but that’s not blocking this PR.

package.json (1)

169-170: read-excel-file wiring matches the new XLSX code; clarify sharp’s role and avoid duplication

Adding read-excel-file to devDependencies and optionalDependencies is consistent with treating Excel support as optional while keeping it available for local development.

sharp now appears in both devDependencies and optionalDependencies, which is redundant. It’s worth deciding whether sharp is truly a runtime-optional feature (keep only in optionalDependencies) or purely a dev/test tool (keep only in devDependencies), and removing the extra entry accordingly.

Also applies to: 229-230

src/util/xlsx.ts (1)

15-32: Dynamic import + sheet/data validation look solid; a couple of tiny cleanups possible

The new parseXlsxFile flow is coherent:

  • Validates file existence up front.
  • Dynamically imports read-excel-file/node with a clear “install this optional dependency” message.
  • Handles file.xlsx#SheetName and file.xlsx#1 selection correctly against readSheetNames, with good range/name errors.
  • Maps [row][col] into CsvRow objects with string values and '' defaults, then enforces non-empty headers, at least one data row, and at least one non-empty cell anywhere.

Two small nits you might consider (non‑blocking):

  • The knownErrors entry 'contains only empty data' is redundant, since all of your own messages for that case start with Sheet "… and are already caught by the 'Sheet "' prefix; you can safely drop it or switch the check to includes for that one entry.
  • The “read-excel-file is not installed…” string is duplicated in the import catch and in the bottom catch; extracting it to a constant would make future edits less error‑prone.

Functionally this implementation matches the updated tests.

Also applies to: 37-101, 112-132

test/util/testCaseReader.test.ts (1)

567-600: Integration XLSX test will usually skip due to mocked fs.existsSync

Because this file globally mocks fs (with existsSync: jest.fn()), the integration test’s const fs = require('fs'); if (fs.existsSync(exampleFile)) { … } will almost always hit the “Skipping integration test – example Excel file not found” branch unless you explicitly override existsSync beforehand.

If you want this test to actually exercise the real example XLSX file under normal dev runs, consider switching just this test to use jest.requireActual('fs') (or temporarily un-mocking fs) for the existence check, while still letting the rest of the file use the mocked fs.

test/util/xlsx.test.ts (1)

3-15: Comprehensive coverage of the new parseXlsxFile behavior

These tests do a nice job exercising the new read-excel-file–based implementation:

  • The module-level mock for read-excel-file/node plus per-test stubbing gives you precise control over readSheetNames and row data.
  • You cover success, missing-module, generic read failures, empty/no-sheet conditions, sheet selection by name and index (including out-of-range and invalid), and detailed data validation (no headers, only empty data, mixed empty/valid rows, nulls, numerics), all matching the logic in src/util/xlsx.ts.

If you ever see mock state leaking between tests, you could switch the afterEach to also call jest.resetAllMocks(), but the current restoreAllMocks + per-test stubbing appears sufficient here.

Also applies to: 20-245

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1d1effa and 6fd8433.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (5)
  • examples/simple-csv/promptfooconfig.yaml (1 hunks)
  • package.json (2 hunks)
  • src/util/xlsx.ts (3 hunks)
  • test/util/testCaseReader.test.ts (3 hunks)
  • test/util/xlsx.test.ts (5 hunks)
🧰 Additional context used
📓 Path-based instructions (12)
test/**/*.test.ts

📄 CodeRabbit inference engine (test/CLAUDE.md)

test/**/*.test.ts: Always use both --coverage and --randomize flags when running Jest tests: npm test -- --coverage --randomize
Never increase test timeouts - fix the slow test instead
Never use .only() or .skip() in committed code
Always include mock cleanup in test files using afterEach(() => { jest.resetAllMocks(); }) to prevent test pollution
Test entire objects using .toEqual() rather than testing individual fields with separate assertions
Mock minimally - only mock external dependencies (APIs, databases), not code under test
Mirror the src/ directory structure in test files: test/providers/ mirrors src/providers/, test/redteam/ mirrors src/redteam/, etc.
Use @jest/globals imports in Jest test files

Files:

  • test/util/xlsx.test.ts
  • test/util/testCaseReader.test.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/gh-cli-workflow.mdc)

**/*.{ts,tsx}: Ensure TypeScript compilation passes by running npm run build or npx tsc from the root to verify TypeScript is valid
Prefer not to introduce new TypeScript types; use existing interfaces whenever possible

Use TypeScript with strict type checking

Files:

  • test/util/xlsx.test.ts
  • test/util/testCaseReader.test.ts
  • src/util/xlsx.ts
**/*.test.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/gh-cli-workflow.mdc)

Avoid disabling or skipping tests unless absolutely necessary and documented

**/*.test.{ts,tsx,js,jsx}: Follow Jest best practices with describe/it blocks
Test both success and error cases for all functionality

Files:

  • test/util/xlsx.test.ts
  • test/util/testCaseReader.test.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,js,jsx}: Follow consistent import order (Biome will handle import sorting)
Use consistent curly braces for all control statements
Prefer const over let; avoid var
Use object shorthand syntax whenever possible
Use async/await for asynchronous code
Use consistent error handling with proper type checks

**/*.{ts,tsx,js,jsx}: Follow consistent import order (Biome will handle import sorting)
Use consistent curly braces for all control statements
Prefer const over let; avoid var
Use object shorthand syntax whenever possible
Use async/await for asynchronous code
Use consistent error handling with proper type checks
Always sanitize sensitive data before logging to prevent exposing secrets, API keys, passwords, and other credentials in logs

Files:

  • test/util/xlsx.test.ts
  • test/util/testCaseReader.test.ts
  • src/util/xlsx.ts
**/test/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Follow Jest best practices with describe/it blocks

Files:

  • test/util/xlsx.test.ts
  • test/util/testCaseReader.test.ts
examples/**/promptfooconfig.yaml

📄 CodeRabbit inference engine (examples/CLAUDE.md)

examples/**/promptfooconfig.yaml: promptfooconfig.yaml must include schema reference and follow strict field order: description, env (optional), prompts, providers, defaultTest (optional), scenarios (optional), tests
Use latest AI models in examples: 'openai:gpt-5', 'anthropic:claude-sonnet-4-5-20250929'
Use 'file://' prefix for external file references in example configurations
Keep description field in promptfooconfig.yaml SHORT (3-10 words)

examples/**/promptfooconfig.yaml: Include a working promptfooconfig.yaml (or equivalent) file in each example
Always include the YAML schema reference at the top of configuration files: # yaml-language-server: $schema=https://promptfoo.dev/config-schema.json
Follow specific field order in configuration files: description, env, prompts, providers, defaultTest, scenarios, tests
When referencing external files in configuration, always use the file:// prefix
For trivial test cases, make them quirky and fun to increase engagement
Always use the latest model versions available in 2025 (e.g., openai:o3-mini, openai:gpt-4o-mini, anthropic:claude-3-7-sonnet-20250219)
Include a mix of providers when comparing model performance
When demonstrating specialized capabilities (vision, audio, etc.), use models that support those features
Always use the latest available model versions for that provider in provider examples
Update model versions when new ones become available

Files:

  • examples/simple-csv/promptfooconfig.yaml
examples/**/*

📄 CodeRabbit inference engine (.cursor/rules/examples.mdc)

Each example should have its own directory with a clear, descriptive name

Files:

  • examples/simple-csv/promptfooconfig.yaml
examples/**/*.yaml

📄 CodeRabbit inference engine (.cursor/rules/examples.mdc)

examples/**/*.yaml: Ensure all configuration files pass YAML lint validation
Include comments to explain non-obvious parts in configuration and code files
Use descriptive variable and function names
Format configuration files consistently

Files:

  • examples/simple-csv/promptfooconfig.yaml
examples/**

📄 CodeRabbit inference engine (.cursor/rules/gh-cli-workflow.mdc)

When modifying examples, update existing files instead of adding new ones. Replace outdated model IDs rather than introducing brand new example files

Files:

  • examples/simple-csv/promptfooconfig.yaml
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use Drizzle ORM for database operations

Files:

  • src/util/xlsx.ts
package.json

📄 CodeRabbit inference engine (AGENTS.md)

Use CommonJS modules (type: 'commonjs' in package.json)

Use CommonJS modules (type: "commonjs" in package.json)

Files:

  • package.json
{.nvmrc,package.json}

📄 CodeRabbit inference engine (CLAUDE.md)

Node.js version requirement (>=20.0.0). Use nvm use to align with .nvmrc (currently v24.7.0)

Files:

  • package.json
🧠 Learnings (39)
📚 Learning: 2025-11-24T18:15:41.142Z
Learnt from: CR
Repo: promptfoo/promptfoo PR: 0
File: test/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:15:41.142Z
Learning: Applies to test/**/*.test.ts : Mock minimally - only mock external dependencies (APIs, databases), not code under test

Applied to files:

  • test/util/xlsx.test.ts
  • test/util/testCaseReader.test.ts
📚 Learning: 2025-11-24T18:17:17.843Z
Learnt from: CR
Repo: promptfoo/promptfoo PR: 0
File: .cursor/rules/jest.mdc:0-0
Timestamp: 2025-11-24T18:17:17.843Z
Learning: Applies to test/**/*.test.ts,test/**/*.spec.ts : Use Jest's mocking utilities (jest.mock, jest.Mocked) rather than complex custom mocks

Applied to files:

  • test/util/xlsx.test.ts
  • test/util/testCaseReader.test.ts
📚 Learning: 2025-11-24T18:17:17.843Z
Learnt from: CR
Repo: promptfoo/promptfoo PR: 0
File: .cursor/rules/jest.mdc:0-0
Timestamp: 2025-11-24T18:17:17.843Z
Learning: Applies to test/**/*.test.ts,test/**/*.spec.ts : Mock as few functions as possible to keep tests realistic

Applied to files:

  • test/util/xlsx.test.ts
  • test/util/testCaseReader.test.ts
📚 Learning: 2025-11-24T18:17:17.843Z
Learnt from: CR
Repo: promptfoo/promptfoo PR: 0
File: .cursor/rules/jest.mdc:0-0
Timestamp: 2025-11-24T18:17:17.843Z
Learning: Applies to test/**/*.test.ts,test/**/*.spec.ts : Prefer shallow mocking over deep mocking in Jest tests

Applied to files:

  • test/util/xlsx.test.ts
  • test/util/testCaseReader.test.ts
📚 Learning: 2025-11-24T18:17:17.843Z
Learnt from: CR
Repo: promptfoo/promptfoo PR: 0
File: .cursor/rules/jest.mdc:0-0
Timestamp: 2025-11-24T18:17:17.843Z
Learning: Applies to test/**/*.test.ts,test/**/*.spec.ts : Mock API responses to avoid external dependencies in Jest tests

Applied to files:

  • test/util/xlsx.test.ts
  • test/util/testCaseReader.test.ts
📚 Learning: 2025-11-24T18:17:17.843Z
Learnt from: CR
Repo: promptfoo/promptfoo PR: 0
File: .cursor/rules/jest.mdc:0-0
Timestamp: 2025-11-24T18:17:17.843Z
Learning: Applies to test/**/*.test.ts,test/**/*.spec.ts : Reset mocks between tests to prevent test pollution

Applied to files:

  • test/util/xlsx.test.ts
  • test/util/testCaseReader.test.ts
📚 Learning: 2025-11-24T18:17:17.843Z
Learnt from: CR
Repo: promptfoo/promptfoo PR: 0
File: .cursor/rules/jest.mdc:0-0
Timestamp: 2025-11-24T18:17:17.843Z
Learning: Applies to test/**/*.test.ts,test/**/*.spec.ts : Mock external dependencies but not the code being tested in Jest tests

Applied to files:

  • test/util/xlsx.test.ts
  • test/util/testCaseReader.test.ts
📚 Learning: 2025-11-24T18:14:47.318Z
Learnt from: CR
Repo: promptfoo/promptfoo PR: 0
File: src/app/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:14:47.318Z
Learning: Applies to src/app/**/*.test.{ts,tsx} : Import test utilities from 'vitest', not 'jest/globals'. Use: `import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'`

Applied to files:

  • test/util/xlsx.test.ts
  • test/util/testCaseReader.test.ts
  • package.json
📚 Learning: 2025-11-24T18:15:41.142Z
Learnt from: CR
Repo: promptfoo/promptfoo PR: 0
File: test/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:15:41.142Z
Learning: Applies to test/**/*.test.ts : Use `jest/globals` imports in Jest test files

Applied to files:

  • test/util/xlsx.test.ts
  • test/util/testCaseReader.test.ts
📚 Learning: 2025-11-24T18:14:47.318Z
Learnt from: CR
Repo: promptfoo/promptfoo PR: 0
File: src/app/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:14:47.318Z
Learning: Applies to src/app/**/*.test.{ts,tsx} : Mock API calls in tests using `vi.mock()` to prevent real network requests

Applied to files:

  • test/util/xlsx.test.ts
📚 Learning: 2025-11-24T18:15:41.142Z
Learnt from: CR
Repo: promptfoo/promptfoo PR: 0
File: test/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:15:41.142Z
Learning: Applies to test/**/*.test.ts : Always include mock cleanup in test files using `afterEach(() => { jest.resetAllMocks(); })` to prevent test pollution

Applied to files:

  • test/util/xlsx.test.ts
  • test/util/testCaseReader.test.ts
📚 Learning: 2025-11-24T19:12:15.259Z
Learnt from: CR
Repo: promptfoo/promptfoo PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T19:12:15.259Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Test both success and error cases for all functionality

Applied to files:

  • test/util/xlsx.test.ts
  • test/util/testCaseReader.test.ts
📚 Learning: 2025-11-24T18:15:14.923Z
Learnt from: CR
Repo: promptfoo/promptfoo PR: 0
File: src/providers/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:15:14.923Z
Learning: Applies to src/providers/test/providers/**/*.test.ts : Every provider must have tests including mock API responses, success and error cases, rate limits, timeouts, and invalid config handling, runnable with `npx jest providers/my-provider --coverage --randomize`

Applied to files:

  • test/util/xlsx.test.ts
  • test/util/testCaseReader.test.ts
📚 Learning: 2025-11-24T18:17:17.843Z
Learnt from: CR
Repo: promptfoo/promptfoo PR: 0
File: .cursor/rules/jest.mdc:0-0
Timestamp: 2025-11-24T18:17:17.843Z
Learning: Applies to test/**/*.test.ts,test/**/*.spec.ts : Test error handling and edge cases including rate limits and timeouts for providers

Applied to files:

  • test/util/xlsx.test.ts
  • test/util/testCaseReader.test.ts
📚 Learning: 2025-11-24T18:15:41.142Z
Learnt from: CR
Repo: promptfoo/promptfoo PR: 0
File: test/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:15:41.142Z
Learning: Applies to test/providers/**/*.test.ts : Every provider test must include: success case (normal API response), error cases (4xx, 5xx, rate limits), configuration validation, and token usage tracking

Applied to files:

  • test/util/xlsx.test.ts
  • test/util/testCaseReader.test.ts
📚 Learning: 2025-11-24T18:13:58.059Z
Learnt from: CR
Repo: promptfoo/promptfoo PR: 0
File: examples/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:13:58.059Z
Learning: Applies to examples/**/promptfooconfig.yaml : Keep description field in promptfooconfig.yaml SHORT (3-10 words)

Applied to files:

  • examples/simple-csv/promptfooconfig.yaml
📚 Learning: 2025-07-18T17:25:38.445Z
Learnt from: CR
Repo: promptfoo/promptfoo PR: 0
File: .cursor/rules/examples.mdc:0-0
Timestamp: 2025-07-18T17:25:38.445Z
Learning: Applies to examples/*/promptfooconfig*.yaml : Format configuration files consistently

Applied to files:

  • examples/simple-csv/promptfooconfig.yaml
📚 Learning: 2025-07-18T17:25:38.444Z
Learnt from: CR
Repo: promptfoo/promptfoo PR: 0
File: .cursor/rules/examples.mdc:0-0
Timestamp: 2025-07-18T17:25:38.444Z
Learning: Applies to examples/*/promptfooconfig*.yaml : For trivial test cases in configuration, make them quirky and fun to increase engagement

Applied to files:

  • examples/simple-csv/promptfooconfig.yaml
📚 Learning: 2025-07-18T17:25:38.444Z
Learnt from: CR
Repo: promptfoo/promptfoo PR: 0
File: .cursor/rules/examples.mdc:0-0
Timestamp: 2025-07-18T17:25:38.444Z
Learning: Applies to examples/*/promptfooconfig*.yaml : Follow the specific field order in all configuration files: description, env (optional), prompts, providers, defaultTest (optional), scenarios (optional), tests

Applied to files:

  • examples/simple-csv/promptfooconfig.yaml
📚 Learning: 2025-11-24T18:13:58.059Z
Learnt from: CR
Repo: promptfoo/promptfoo PR: 0
File: examples/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:13:58.059Z
Learning: Applies to examples/**/promptfooconfig.yaml : promptfooconfig.yaml must include schema reference and follow strict field order: description, env (optional), prompts, providers, defaultTest (optional), scenarios (optional), tests

Applied to files:

  • examples/simple-csv/promptfooconfig.yaml
📚 Learning: 2025-11-24T18:16:46.293Z
Learnt from: CR
Repo: promptfoo/promptfoo PR: 0
File: .cursor/rules/examples.mdc:0-0
Timestamp: 2025-11-24T18:16:46.293Z
Learning: Applies to examples/**/promptfooconfig.yaml : Follow specific field order in configuration files: description, env, prompts, providers, defaultTest, scenarios, tests

Applied to files:

  • examples/simple-csv/promptfooconfig.yaml
📚 Learning: 2025-11-24T18:16:46.293Z
Learnt from: CR
Repo: promptfoo/promptfoo PR: 0
File: .cursor/rules/examples.mdc:0-0
Timestamp: 2025-11-24T18:16:46.293Z
Learning: Applies to examples/**/promptfooconfig.yaml : For trivial test cases, make them quirky and fun to increase engagement

Applied to files:

  • examples/simple-csv/promptfooconfig.yaml
📚 Learning: 2025-07-18T17:25:38.445Z
Learnt from: CR
Repo: promptfoo/promptfoo PR: 0
File: .cursor/rules/examples.mdc:0-0
Timestamp: 2025-07-18T17:25:38.445Z
Learning: Applies to examples/*/promptfooconfig*.yaml : Update model versions when new ones become available in configuration files

Applied to files:

  • examples/simple-csv/promptfooconfig.yaml
📚 Learning: 2025-07-18T17:25:38.444Z
Learnt from: CR
Repo: promptfoo/promptfoo PR: 0
File: .cursor/rules/examples.mdc:0-0
Timestamp: 2025-07-18T17:25:38.444Z
Learning: Applies to examples/*/promptfooconfig*.yaml : Include a working promptfooconfig.yaml (or equivalent) file in each example

Applied to files:

  • examples/simple-csv/promptfooconfig.yaml
📚 Learning: 2025-11-24T18:16:46.293Z
Learnt from: CR
Repo: promptfoo/promptfoo PR: 0
File: .cursor/rules/examples.mdc:0-0
Timestamp: 2025-11-24T18:16:46.293Z
Learning: Applies to examples/**/promptfooconfig.yaml : Update model versions when new ones become available

Applied to files:

  • examples/simple-csv/promptfooconfig.yaml
📚 Learning: 2025-07-18T17:25:38.444Z
Learnt from: CR
Repo: promptfoo/promptfoo PR: 0
File: .cursor/rules/examples.mdc:0-0
Timestamp: 2025-07-18T17:25:38.444Z
Learning: Applies to examples/*/promptfooconfig*.yaml : For OpenAI, prefer models like 'openai:o3-mini' and 'openai:gpt-4o-mini' in configuration files

Applied to files:

  • examples/simple-csv/promptfooconfig.yaml
📚 Learning: 2025-11-24T18:13:58.059Z
Learnt from: CR
Repo: promptfoo/promptfoo PR: 0
File: examples/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:13:58.059Z
Learning: Applies to examples/**/promptfooconfig.yaml : Use latest AI models in examples: 'openai:gpt-5', 'anthropic:claude-sonnet-4-5-20250929'

Applied to files:

  • examples/simple-csv/promptfooconfig.yaml
📚 Learning: 2025-11-24T18:17:17.843Z
Learnt from: CR
Repo: promptfoo/promptfoo PR: 0
File: .cursor/rules/jest.mdc:0-0
Timestamp: 2025-11-24T18:17:17.843Z
Learning: Applies to test/**/*.test.ts,test/**/*.spec.ts : Ensure test failures are deterministic and do not depend on external state

Applied to files:

  • test/util/testCaseReader.test.ts
📚 Learning: 2025-11-24T18:17:17.843Z
Learnt from: CR
Repo: promptfoo/promptfoo PR: 0
File: .cursor/rules/jest.mdc:0-0
Timestamp: 2025-11-24T18:17:17.843Z
Learning: Applies to test/**/*.test.ts,test/**/*.spec.ts : Clean up after tests by calling `jest.resetAllMocks()` in an `afterEach` block to prevent side effects

Applied to files:

  • test/util/testCaseReader.test.ts
📚 Learning: 2025-11-24T18:17:17.843Z
Learnt from: CR
Repo: promptfoo/promptfoo PR: 0
File: .cursor/rules/jest.mdc:0-0
Timestamp: 2025-11-24T18:17:17.843Z
Learning: Applies to test/**/*.test.ts,test/**/*.spec.ts : Clean up any test data or mocks after each test to prevent side effects

Applied to files:

  • test/util/testCaseReader.test.ts
📚 Learning: 2025-11-24T18:17:44.371Z
Learnt from: CR
Repo: promptfoo/promptfoo PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-24T18:17:44.371Z
Learning: Applies to **/test/**/*.{ts,tsx,js,jsx} : Follow Jest best practices with describe/it blocks

Applied to files:

  • test/util/testCaseReader.test.ts
📚 Learning: 2025-11-24T18:13:58.059Z
Learnt from: CR
Repo: promptfoo/promptfoo PR: 0
File: examples/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:13:58.059Z
Learning: Always test examples with local build using 'npm run local -- eval -c examples/my-example/promptfooconfig.yaml', not with published versions

Applied to files:

  • test/util/testCaseReader.test.ts
📚 Learning: 2025-07-18T17:25:38.445Z
Learnt from: CR
Repo: promptfoo/promptfoo PR: 0
File: .cursor/rules/examples.mdc:0-0
Timestamp: 2025-07-18T17:25:38.445Z
Learning: When developing or testing examples locally, use 'npm run local' commands instead of 'npx promptfoolatest' to ensure local changes are tested

Applied to files:

  • test/util/testCaseReader.test.ts
📚 Learning: 2025-11-24T18:17:17.843Z
Learnt from: CR
Repo: promptfoo/promptfoo PR: 0
File: .cursor/rules/jest.mdc:0-0
Timestamp: 2025-11-24T18:17:17.843Z
Learning: Applies to test/**/*.test.ts,test/**/*.spec.ts : Always run `nvm use` first to ensure you're using the correct Node.js version before running Jest tests

Applied to files:

  • test/util/testCaseReader.test.ts
  • package.json
📚 Learning: 2025-11-24T18:17:01.480Z
Learnt from: CR
Repo: promptfoo/promptfoo PR: 0
File: .cursor/rules/gh-cli-workflow.mdc:0-0
Timestamp: 2025-11-24T18:17:01.480Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Avoid disabling or skipping tests unless absolutely necessary and documented

Applied to files:

  • test/util/testCaseReader.test.ts
📚 Learning: 2025-07-18T17:25:57.700Z
Learnt from: CR
Repo: promptfoo/promptfoo PR: 0
File: .cursor/rules/gh-cli-workflow.mdc:0-0
Timestamp: 2025-07-18T17:25:57.700Z
Learning: Applies to **/*.{test,spec}.{js,ts,jsx,tsx} : Avoid disabling or skipping tests unless absolutely necessary and documented

Applied to files:

  • test/util/testCaseReader.test.ts
📚 Learning: 2025-11-24T18:15:41.142Z
Learnt from: CR
Repo: promptfoo/promptfoo PR: 0
File: test/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:15:41.142Z
Learning: Applies to test/**/*.test.ts : Never use `.only()` or `.skip()` in committed code

Applied to files:

  • test/util/testCaseReader.test.ts
📚 Learning: 2025-11-24T18:13:48.317Z
Learnt from: CR
Repo: promptfoo/promptfoo PR: 0
File: drizzle/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:13:48.317Z
Learning: Applies to drizzle/test/**/*.{ts,tsx,js} : Use in-memory SQLite database in test files for migration testing (see `test/` directory for patterns)

Applied to files:

  • test/util/testCaseReader.test.ts
📚 Learning: 2025-11-24T18:14:47.318Z
Learnt from: CR
Repo: promptfoo/promptfoo PR: 0
File: src/app/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:14:47.318Z
Learning: Applies to src/app/**/*.test.{ts,tsx} : Use Vitest for testing (not Jest). Vitest is configured in vite.config.ts with jsdom environment and globals enabled

Applied to files:

  • package.json
🧬 Code graph analysis (3)
test/util/xlsx.test.ts (1)
src/util/xlsx.ts (1)
  • parseXlsxFile (4-144)
test/util/testCaseReader.test.ts (1)
src/util/xlsx.ts (1)
  • parseXlsxFile (4-144)
src/util/xlsx.ts (1)
src/types/index.ts (1)
  • CsvRow (85-87)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (18)
  • GitHub Check: Test on Node 22.x and windows-latest
  • GitHub Check: Test on Node 24.x and windows-latest
  • GitHub Check: Test on Node 22.x and ubuntu-latest
  • GitHub Check: Test on Node 22.x and macOS-latest
  • GitHub Check: Test on Node 24.x and ubuntu-latest
  • GitHub Check: Test on Node 20.x and macOS-latest
  • GitHub Check: Test on Node 20.x and windows-latest
  • GitHub Check: Test on Node 20.x and ubuntu-latest
  • GitHub Check: Redteam (Production API)
  • GitHub Check: Share Test
  • GitHub Check: Build on Node 24.x
  • GitHub Check: Build on Node 22.x
  • GitHub Check: webui tests
  • GitHub Check: Redteam (Staging API)
  • GitHub Check: Build on Node 20.x
  • GitHub Check: Build Docs
  • GitHub Check: security-scan
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (1)
test/util/testCaseReader.test.ts (1)

454-504: XLSX tests now correctly mirror the read-excel-file behavior and error paths

The updated tests around XLSX support look good:

  • jest.doMock('read-excel-file/node', …) + jest.resetModules() + fresh import of readStandaloneTestsFile ensures the dynamic import in src/util/xlsx.ts sees the mocked module.
  • The happy-path test uses the correct “array-of-arrays with headers in row 0” shape and aligns with the new CsvRow mapping.
  • The “module not installed” test throws from the mock factory and validates the user-facing guidance string, exercising the dynamic import failure path.
  • The “no sheets” case stubs readSheetNames to [] and checks the exact "Excel file has no sheets" message, matching the implementation.

This provides good coverage of both success and primary error scenarios after the library swap.

Also applies to: 506-565

…nerability

The xlsx package (SheetJS) version 0.18.5 on npm has a high severity
prototype pollution vulnerability (CVE-2023-30533). The fix exists in
version 0.19.3+, but SheetJS stopped publishing to npm.

This replaces xlsx with read-excel-file, which:
- Has no known vulnerabilities
- Is actively maintained (last update Sep 2025)
- Is 7x smaller (1.0 MB vs 7.5 MB)
- Provides all needed functionality (read xlsx, select sheets)

Changes:
- Replace xlsx with read-excel-file in package.json
- Rewrite src/util/xlsx.ts to use read-excel-file API
- Update tests in test/util/xlsx.test.ts
- Update tests in test/util/testCaseReader.test.ts
- Update example comment in examples/simple-csv/promptfooconfig.yaml

npm audit results: 22 vulnerabilities → 21 (high severity removed)
JustinBeckwith
JustinBeckwith previously approved these changes Nov 25, 2025
jameshiester and others added 2 commits November 25, 2025 13:57
Co-authored-by: James Hiester <james@promptfoo.dev>
Co-authored-by: mldangelo <michael.l.dangelo@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
@JustinBeckwith JustinBeckwith merged commit e6e2b98 into main Nov 25, 2025
35 checks passed
@JustinBeckwith JustinBeckwith deleted the fix/replace-xlsx-with-read-excel-file branch November 25, 2025 22:44
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.

5 participants