Skip to content

Integrating TruffleHog secret detection patterns#16

Open
amrelsagaei wants to merge 5 commits intomainfrom
ae-pr-7-trufflehug-patts
Open

Integrating TruffleHog secret detection patterns#16
amrelsagaei wants to merge 5 commits intomainfrom
ae-pr-7-trufflehug-patts

Conversation

@amrelsagaei
Copy link
Copy Markdown
Contributor

@amrelsagaei amrelsagaei commented Apr 15, 2026

Summary by CodeRabbit

Release Notes v1.2.4

  • New Features

    • Added batch search functionality to search across all predefined secret patterns with a single operation
    • Introduced comprehensive secret pattern library with 12+ categories (cloud providers, AI/ML, CI/CD, payments, and more)
    • Added pattern filtering and search capabilities with category-based organization and custom search
  • Bug Fixes

    • Improved null/undefined handling throughout the application for more robust error behavior
  • Tests

    • Added test infrastructure with Vitest configuration
    • Added comprehensive secret pattern validation tests
  • Chores

    • Added ESLint configuration for code quality enforcement
    • Updated package configuration to support module imports
    • Version bump to 1.2.4

@socket-security
Copy link
Copy Markdown

socket-security bot commented Apr 15, 2026

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Added@​caido/​eslint-config@​0.9.0751006893100
Addedglobals@​17.5.01001008694100
Addedeslint@​9.39.48910010095100

View full report

Comment thread package.json
},
"devDependencies": {
"@caido-community/dev": "^0.1.3",
"@caido/eslint-config": "^0.9.0",
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Can you pin the deps pls ?

@f8thl3ss
Copy link
Copy Markdown

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 16, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 16, 2026

📝 Walkthrough

Walkthrough

This PR introduces batch secret pattern searching, comprehensive test infrastructure (ESLint configuration and Vitest), secret pattern catalogs with validation tests, and refactors nullable semantics to use optional/undefined throughout the backend and frontend codebase.

Changes

Cohort / File(s) Summary
Test & Build Infrastructure
.mise.toml, eslint.config.js, caido.config.ts
Added validate task running pnpm i, lint, typecheck, test, build; created ESLint flat config with browser globals and ignore rules; bumped version from 1.2.3 to 1.2.4.
Root Package Configuration
package.json
Added "type": "module", new scripts (test, lint, lint:fix), and devDependencies (@caido/eslint-config, eslint, globals).
Secret Pattern Catalog
packages/frontend/src/data/secret-patterns.ts, packages/frontend/src/data/secret-patterns.test.ts
Added comprehensive secret pattern registry with 12 categories and regex-based detection; included extensive Vitest test suite validating pattern integrity, positive/negative matches, and no duplicates.
Null/Undefined Semantics Refactoring
packages/backend/src/validation/schemas.ts, packages/shared/src/results.ts, packages/backend/src/services/..., packages/backend/src/utils/grep.ts
Replaced nullable fields with optional properties across schemas and service signatures; updated GrepOptions and GrepResults to use T? instead of T | null; tightened conditional checks to explicit === undefined comparisons.
Backend API & Services
packages/backend/src/api/index.ts, packages/backend/src/index.ts, packages/backend/src/services/grep.ts, packages/backend/src/services/grep.test.ts, packages/backend/src/services/storage.ts
Updated function signatures removing async from non-Promise returns; changed return types for stopGrep and downloadResults; refactored error handling and mock assertions; changed nullable state to undefined-based checks.
Batch Secret Search Feature
packages/frontend/src/stores/batchSearchStore.ts, packages/frontend/src/components/search/batch/BatchSearchDialog.vue, packages/frontend/src/components/search/Form.vue, packages/frontend/src/components/results/Results.vue
Added new useBatchSearchStore orchestrating sequential grep searches across multiple secret patterns with category filtering, progress tracking, and warning dialog confirmation; integrated batch state reset into Form search handler; updated Results component with category dropdown and match categorization.
Frontend Store Updates
packages/frontend/src/stores/grepStore.ts, packages/frontend/src/stores/patternsStore.ts, packages/frontend/src/stores/index.ts
Added currentPatternName state; refined option defaults to use optional properties; updated pattern filtering to support categories (predefined, secrets, custom) with search/subcategory selection; exposed filtered patterns and category controls.
Frontend Components - Results
packages/frontend/src/components/results/MatchViewer.vue, packages/frontend/src/components/results/Results.vue, packages/frontend/src/components/results/...
Refactored prop handling and null/undefined semantics; updated error displays with explicit undefined checks; modified stop-search to sync state without awaiting API call; added category-based filtering and badge labels.
Frontend Components - Search
packages/frontend/src/components/search/Search.vue, packages/frontend/src/components/search/Options.vue, packages/frontend/src/components/search/TransformScriptDialog.vue, packages/frontend/src/components/search/patterns/...
Changed pattern input to use explicit handler clearing currentPatternName; updated computed bindings for transform and match groups to treat absence as undefined; added category/subcategory filtering UI to patterns list with custom regex dialog integration; added "Search All Secrets" button.
Frontend Repositories & Utils
packages/frontend/src/repositories/grep.ts, packages/frontend/src/repositories/customRegex.ts, packages/frontend/src/utils/..., packages/frontend/src/plugins/sdk.ts, packages/frontend/src/types.ts
Updated error checks from truthiness to explicit !== undefined; removed console.error logging; switched to template literals for error messages; converted import statements to type-only where applicable; adjusted nullish coalescing operators.
Frontend Test & Build Config
packages/frontend/vitest.config.ts, packages/frontend/package.json
Added Vitest configuration with test file glob pattern; added test and test:watch npm scripts and vitest dependency.
Miscellaneous Frontend
packages/frontend/src/components/guide/Container.vue, packages/frontend/src/components/index.ts, packages/frontend/src/components/search/ai-dialog/..., packages/frontend/src/views/App.vue, packages/frontend/src/index.ts, packages/frontend/src/stores/aiStore.ts
Reordered imports, adjusted quote styles, reformatted template attributes (camelCase to kebab-case), updated PrimeVue prop names (minSizemin-size), refined conditional logic with explicit undefined checks.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Form
    participant Dialog
    participant batchSearchStore
    participant grepStore
    participant grepRepository
    participant Backend

    User->>Form: Clicks "Search All Secrets"
    Form->>batchSearchStore: startBatchSearch(options)
    batchSearchStore->>Dialog: showWarningDialog = true
    Dialog->>User: Display warning with pattern count

    User->>Dialog: Clicks "Start Search"
    Dialog->>batchSearchStore: confirmAndStart()
    
    batchSearchStore->>batchSearchStore: Initialize search state<br/>(isSearching=true, reset counts)
    
    loop For each valid SECRET_PATTERN
        batchSearchStore->>grepStore: Update pattern & currentPatternName
        batchSearchStore->>grepRepository: searchGrepRequests(pattern)
        grepRepository->>Backend: grep API call
        Backend->>grepRepository: Returns matches
        grepRepository->>batchSearchStore: result.data (matches)
        
        alt Matches found
            batchSearchStore->>batchSearchStore: Tag matches with pattern.category<br/>in matchCategoryMap
            batchSearchStore->>batchSearchStore: Update patternsCompleted,<br/>totalPatterns, activeCategorySet
        else Pattern request error
            batchSearchStore->>batchSearchStore: Continue to next pattern
        end

        alt User cancelled
            batchSearchStore->>batchSearchStore: Break loop, set cancelled=true
            batchSearchStore->>grepRepository: stopGrep()
        end
    end

    batchSearchStore->>grepStore: Set searchTime, clear searching flags
    batchSearchStore->>User: Show completion toast<br/>(success/warning based on results)
Loading
sequenceDiagram
    participant Results as Results.vue
    participant grepStore
    participant batchSearchStore
    participant UI as Match Display

    Results->>grepStore: Read filteredAndSortedResults
    grepStore->>grepStore: Compute filteredAndSortedResults<br/>from searchResults

    alt Batch search active
        Results->>batchSearchStore: Read selectedResultCategory
        Results->>grepStore: Check categoryFilterOptions
        grepStore->>batchSearchStore: For each match: getMatchCategory()
        batchSearchStore->>grepStore: Return pattern.category
        grepStore->>grepStore: Filter results by category<br/>if selectedResultCategory !== "all"
    end

    grepStore->>Results: Return filtered + sorted results
    Results->>UI: Render matches with category badge<br/>and count ("Found X from Y")
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Poem

🐰 A batch of secrets now in sight,
With patterns grouped by category's light,
Null becomes undefined, clean and bright,
Tests and linting keep code tight,
The search for hidden keys takes flight!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 13.64% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title directly matches the main objective: integrating TruffleHog secret detection patterns into the repository.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ae-pr-7-trufflehug-patts

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

Copy link
Copy Markdown

@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: 12

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/backend/src/services/storage.ts (1)

13-24: ⚠️ Potential issue | 🟠 Major

Don’t silently suppress storage directory initialization failures.

Line 22 currently swallows all errors, which can hide real filesystem failures and make later errors harder to diagnose.

💡 Proposed fix
  constructor(sdk: CaidoBackendSDK) {
    this.sdk = sdk;
    this.regexesDir = path.join(this.sdk.meta.path(), "regexes");
-    this.ensureRegexesDirectory();
  }

  private async ensureRegexesDirectory(): Promise<void> {
-    try {
-      await mkdir(this.regexesDir, { recursive: true });
-    } catch {
-      // Directory might already exist
-    }
+    await mkdir(this.regexesDir, { recursive: true });
  }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/backend/src/services/storage.ts` around lines 13 - 24, The
ensureRegexesDirectory method is swallowing all errors which hides real
filesystem failures; update ensureRegexesDirectory (used from the constructor)
to handle errors explicitly by catching the error into a variable and either
rethrowing or logging it with context (including this.regexesDir and the caught
error) instead of an empty catch block; ensure the chosen behavior surfaces
initialization failures to callers (eg. rethrow after logging) so the
constructor/SDK initialization won't silently proceed on real disk errors.
🧹 Nitpick comments (4)
packages/frontend/src/components/results/None.vue (1)

19-29: Optional: extract repeated “no results” condition into a computed flag.

The same predicate appears twice, which makes future tweaks easier to miss.

♻️ Suggested refactor
<script setup lang="ts">
 import Card from "primevue/card";
+import { computed } from "vue";

 import { useGrepStore } from "@/stores";

 const store = useGrepStore();
+const hasNoResults = computed(
+  () => !!store.pattern.trim() && store.results.searchResults?.length === 0,
+);
</script>
-        <i
-          v-if="
-            store.pattern.trim() && store.results.searchResults?.length === 0
-          "
-          class="fas fa-search-minus text-gray-400 text-3xl"
-        ></i>
+        <i v-if="hasNoResults" class="fas fa-search-minus text-gray-400 text-3xl"></i>
         <i v-else class="fas fa-search text-gray-400 text-3xl"></i>

-        <div
-          v-if="
-            store.pattern.trim() && store.results.searchResults?.length === 0
-          "
-          class="text-gray-400 text-md"
-        >
+        <div v-if="hasNoResults" class="text-gray-400 text-md">
           No results found
         </div>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/frontend/src/components/results/None.vue` around lines 19 - 29, The
template repeats the predicate store.pattern.trim() &&
store.results.searchResults?.length === 0 twice; add a computed property (e.g.,
hasNoResults or isNoResults) in the None.vue component that returns that boolean
and replace both occurrences in the template with this computed flag to
centralize the logic and make future changes simpler; update references to use
the new computed name and ensure it imports/uses the same store instance as the
template.
.mise.toml (1)

8-8: Use a deterministic install command in validation.

pnpm i can mask lockfile drift. Prefer a frozen-lockfile install for reproducible validation runs.

♻️ Proposed change
 [tasks.validate]
 description = "Run all checks: install, lint, typecheck, test, build"
 run = """
-pnpm i
+pnpm install --frozen-lockfile
 pnpm lint
 pnpm typecheck
 pnpm test
 pnpm build
 """
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.mise.toml at line 8, The validation currently runs the non-deterministic
command "pnpm i" in .mise.toml; replace it with a frozen-lockfile install (e.g.,
"pnpm install --frozen-lockfile" or the equivalent CI-safe command for your pnpm
version) so the validation fails on lockfile drift and becomes reproducible;
update the command string in .mise.toml to the frozen-lockfile variant and
ensure any CI/validation runner that references the "pnpm i" entry now uses that
updated command.
packages/frontend/src/components/search/TransformScriptDialog.vue (1)

24-28: Minor: Avoid calling trim() twice.

localScript.value.trim() is evaluated twice when the script is non-empty. Consider storing the trimmed value first.

♻️ Proposed fix
 const save = () => {
-  grepStore.options.transformScript =
-    localScript.value.trim() === "" ? undefined : localScript.value.trim();
+  const trimmed = localScript.value.trim();
+  grepStore.options.transformScript = trimmed === "" ? undefined : trimmed;
   visible.value = false;
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/frontend/src/components/search/TransformScriptDialog.vue` around
lines 24 - 28, In save(), avoid calling localScript.value.trim() twice: compute
a single const trimmed = localScript.value.trim() and then set
grepStore.options.transformScript = trimmed === "" ? undefined : trimmed,
finally set visible.value = false; this updates the function save and uses the
variables localScript.value, grepStore.options.transformScript, and
visible.value.
packages/frontend/src/components/search/patterns/PatternsList.vue (1)

38-47: Prefer a stable id for custom-pattern actions.

Edit/delete are keyed off pattern.name, not a stable identifier. If custom names ever collide, both actions will resolve the first match, and the delete path can fall back to "". Thread the custom pattern id through DisplayPattern and use that here directly.

Also applies to: 155-166

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/frontend/src/components/search/patterns/PatternsList.vue` around
lines 38 - 47, The edit/delete flows currently look up custom patterns by name
(getCustomPatternById and editCustomPattern) which is fragile — change these to
use the pattern's stable id: thread the custom pattern id through
DisplayPattern, update the functions (e.g., getCustomPatternById ->
getCustomPatternById(id: string) to find by p.id, and editCustomPattern to
accept id and call patternsStore.openCustomRegexDialog(foundPattern)), and
update the corresponding delete path (the code around the other occurrence at
lines 155-166) to use the id instead of name so actions always target the exact
custom pattern.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@eslint.config.js`:
- Line 22: Add a final newline at the end of the file so the trailing "];" line
ends with a newline to satisfy Prettier/formatting checks; locate the closing
array/semicolon token (the "];" line in eslint.config.js) and ensure the file
ends with a single newline character.

In `@packages/backend/src/services/grep.ts`:
- Line 152: Replace the native RegExp instantiation with the RE2 implementation:
import RE2 from 're2' at the top of packages/backend/src/services/grep.ts and
change the line that creates regex (currently const regex = new RegExp(pattern,
"is")) to use new RE2(pattern, "is") so user-supplied patterns are executed by
re2 (polynomial-time) instead of the native engine; keep the same variable name
(regex) and types where used so the rest of the grep logic (pattern matching
over request/response bodies) continues to work.

In `@packages/frontend/src/components/results/Results.vue`:
- Around line 170-175: The UI flips store.status.isSearching and
store.results.cancelled before the async stopGrep() completes, causing the UI to
show a stopped scan even if the backend stop fails; change stopSearch so it
awaits stopGrep() (or handles its Promise) and only set store.status.isSearching
= false and store.results.cancelled = true after stopGrep() resolves
successfully, and on rejection keep the searching state and surface the error
(so the Stop button remains available for retry); update the stopSearch function
to await stopGrep() and move the state mutations into the success path.

In `@packages/frontend/src/components/search/batch/BatchSearchDialog.vue`:
- Around line 12-18: The Dialog close paths must route through
batchSearchStore.closeWarningDialog so pendingOptions is always cleared; update
the Dialog in BatchSearchDialog.vue to disable built-in closing and bind the
hide event by setting :closable="false" and :close-on-escape="false" and adding
`@hide`="batchSearchStore.closeWarningDialog" (the v-model can remain bound to
batchSearchStore.showWarningDialog) so any user close (button/escape/other)
calls closeWarningDialog() and keeps startBatchSearch() consistent.

In `@packages/frontend/src/components/search/Form.vue`:
- Around line 33-35: handleSearch currently unconditionally calls
batchSearchStore.resetBatchState() and grepStore.searchGrepRequests(), which
allows a normal search to interrupt a running batch (and vice versa) because
both mutate the same grepStore; update handleSearch to first check a running
flag (e.g., grepStore.isRunning or batchSearchStore.isBatchRunning) and return
or disable starting a normal search if a batch run is active, and likewise
modify the batch-start path (the batch button handler referenced around lines
64-70) to check the same running flag and avoid calling
batchSearchStore.resetBatchState() or grepStore.searchGrepRequests() when the
other flow is active; use a single canonical running/mode flag on grepStore (or
batchSearchStore) to coordinate and prevent concurrent starts.

In `@packages/frontend/src/components/search/Search.vue`:
- Around line 8-12: The InputText for the search pattern needs to be disabled
during searches because handlePatternInput currently allows keystrokes to clear
batch search progress; update the InputText element to bind its disabled state
to the combined search statuses (use :disabled="grepStore.status.isSearching ||
batchSearchStore.status.isSearching") and leave handlePatternInput (which sets
grepStore.pattern and clears grepStore.currentPatternName) unchanged so user
input cannot interrupt in-progress searches.

In `@packages/frontend/src/data/secret-patterns.test.ts`:
- Around line 9-13: The testMatch helper ignores each pattern's configured
matchGroups and always prefers capture group 1; update testMatch to consult the
SecretPattern.matchGroups (e.g., use the first configured group index) when
selecting the returned capture: compute an index like const groupIndex =
Array.isArray(pattern.matchGroups) && pattern.matchGroups.length ?
pattern.matchGroups[0] : 1, validate it is a number within match.length, then
return match?.[groupIndex] ?? match?.[0] (falling back to the whole match if the
group is missing).

In `@packages/frontend/src/data/secret-patterns.ts`:
- Around line 166-168: The "JFrog Artifactory Key" detector (pattern
"\\b([a-zA-Z0-9]{64,73})\\b") and several other entries use overly broad,
context-free patterns (bare 64–73 alnum tokens, semver-like \d+\.\d+\.\d+, 44–80
char tokens, 6-digit numbers) that produce many false positives; update those
entries to either remove them or tighten them by requiring provider-specific
context/prefixes (e.g., repository/hostname, header names, known token prefixes)
or replace with stricter regexes that include surrounding keywords, or drop the
entries entirely—apply this change to the "JFrog Artifactory Key" entry and the
other context-free detectors referenced in the file so that only
provider-specific or contextual patterns remain.

In `@packages/frontend/src/stores/batchSearchStore.ts`:
- Around line 27-29: matchCategoryMap is keyed only by match.value which causes
collisions across requests and overlapping patterns; change the map to use a
stable per-match key (e.g., a generated stableMatchId or a composite key like
`${requestId}:${matchIndex}` or an inherent match.id) wherever entries are
created/updated (see matchCategoryMap usage and the code that populates it
around the existing mapping sites and the other occurrences noted). Update the
places that read/write this map (including the logic that sets and reads
selectedResultCategory) to use this stable key so categories are deterministic
across requests and overlaps, and ensure any helpers that produce keys are
consistently used in the three locations currently using match.value as the key.
- Around line 148-153: The cancelSearch() function currently flips
status.cancelled, grepStore.status.isSearching, and grepStore.results.cancelled
before calling grepRepository.stopGrep(); change this to await the asynchronous
stop operation first (await grepRepository.stopGrep()), and only set
grepStore.status.isSearching = false and grepStore.results.cancelled = true
after stopGrep resolves; also keep status.cancelled set immediately (or set it
before awaiting) so intent is recorded, and add a catch around await
grepRepository.stopGrep() to restore/adjust UI state
(grepStore.status.isSearching) or surface an error if stopping fails.

In `@packages/frontend/src/stores/grepStore.ts`:
- Around line 43-45: The code clears currentPatternName.value at the start of a
search which wipes out the label set by patternsStore; remove the line that sets
currentPatternName.value = "" so pattern-driven searches retain their label, but
keep the other initializations (results.searchResults = undefined and
status.isSearching = true) intact; locate and edit the search-starting code
where currentPatternName, results.searchResults, and status.isSearching are set
and delete only the currentPatternName reset.
- Around line 98-107: The truncation logic incorrectly treats exactly 25,000
results as truncated; update the check in the block that assigns
results.searchResults (the newResults/truncatedResults handling) to only treat
cases where newResults.length > 25000 as truncated, then slice to 25,000 and
append the synthetic warning row; ensure the condition uses > 25000 (not >=
25000) so an exact 25,000-result set is left unchanged and does not receive the
warning entry.

---

Outside diff comments:
In `@packages/backend/src/services/storage.ts`:
- Around line 13-24: The ensureRegexesDirectory method is swallowing all errors
which hides real filesystem failures; update ensureRegexesDirectory (used from
the constructor) to handle errors explicitly by catching the error into a
variable and either rethrowing or logging it with context (including
this.regexesDir and the caught error) instead of an empty catch block; ensure
the chosen behavior surfaces initialization failures to callers (eg. rethrow
after logging) so the constructor/SDK initialization won't silently proceed on
real disk errors.

---

Nitpick comments:
In @.mise.toml:
- Line 8: The validation currently runs the non-deterministic command "pnpm i"
in .mise.toml; replace it with a frozen-lockfile install (e.g., "pnpm install
--frozen-lockfile" or the equivalent CI-safe command for your pnpm version) so
the validation fails on lockfile drift and becomes reproducible; update the
command string in .mise.toml to the frozen-lockfile variant and ensure any
CI/validation runner that references the "pnpm i" entry now uses that updated
command.

In `@packages/frontend/src/components/results/None.vue`:
- Around line 19-29: The template repeats the predicate store.pattern.trim() &&
store.results.searchResults?.length === 0 twice; add a computed property (e.g.,
hasNoResults or isNoResults) in the None.vue component that returns that boolean
and replace both occurrences in the template with this computed flag to
centralize the logic and make future changes simpler; update references to use
the new computed name and ensure it imports/uses the same store instance as the
template.

In `@packages/frontend/src/components/search/patterns/PatternsList.vue`:
- Around line 38-47: The edit/delete flows currently look up custom patterns by
name (getCustomPatternById and editCustomPattern) which is fragile — change
these to use the pattern's stable id: thread the custom pattern id through
DisplayPattern, update the functions (e.g., getCustomPatternById ->
getCustomPatternById(id: string) to find by p.id, and editCustomPattern to
accept id and call patternsStore.openCustomRegexDialog(foundPattern)), and
update the corresponding delete path (the code around the other occurrence at
lines 155-166) to use the id instead of name so actions always target the exact
custom pattern.

In `@packages/frontend/src/components/search/TransformScriptDialog.vue`:
- Around line 24-28: In save(), avoid calling localScript.value.trim() twice:
compute a single const trimmed = localScript.value.trim() and then set
grepStore.options.transformScript = trimmed === "" ? undefined : trimmed,
finally set visible.value = false; this updates the function save and uses the
variables localScript.value, grepStore.options.transformScript, and
visible.value.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e922e980-0a33-453b-8154-9a555aa1583b

📥 Commits

Reviewing files that changed from the base of the PR and between 5d51de8 and d656ef0.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (48)
  • .mise.toml
  • caido.config.ts
  • eslint.config.js
  • package.json
  • packages/backend/src/api/index.ts
  • packages/backend/src/index.ts
  • packages/backend/src/services/grep.test.ts
  • packages/backend/src/services/grep.ts
  • packages/backend/src/services/storage.ts
  • packages/backend/src/types.ts
  • packages/backend/src/utils/grep.ts
  • packages/backend/src/validation/schemas.ts
  • packages/frontend/package.json
  • packages/frontend/src/components/guide/Container.vue
  • packages/frontend/src/components/index.ts
  • packages/frontend/src/components/results/Container.vue
  • packages/frontend/src/components/results/MatchViewer.vue
  • packages/frontend/src/components/results/None.vue
  • packages/frontend/src/components/results/Results.vue
  • packages/frontend/src/components/results/Searching.vue
  • packages/frontend/src/components/search/Container.vue
  • packages/frontend/src/components/search/Form.vue
  • packages/frontend/src/components/search/Options.vue
  • packages/frontend/src/components/search/Search.vue
  • packages/frontend/src/components/search/TransformScriptDialog.vue
  • packages/frontend/src/components/search/ai-dialog/AIDialog.vue
  • packages/frontend/src/components/search/ai-dialog/Container.vue
  • packages/frontend/src/components/search/batch/BatchSearchDialog.vue
  • packages/frontend/src/components/search/patterns/Container.vue
  • packages/frontend/src/components/search/patterns/CustomRegexDialog.vue
  • packages/frontend/src/components/search/patterns/PatternsList.vue
  • packages/frontend/src/data/secret-patterns.test.ts
  • packages/frontend/src/data/secret-patterns.ts
  • packages/frontend/src/index.ts
  • packages/frontend/src/plugins/sdk.ts
  • packages/frontend/src/repositories/customRegex.ts
  • packages/frontend/src/repositories/grep.ts
  • packages/frontend/src/stores/aiStore.ts
  • packages/frontend/src/stores/batchSearchStore.ts
  • packages/frontend/src/stores/grepStore.ts
  • packages/frontend/src/stores/index.ts
  • packages/frontend/src/stores/patternsStore.ts
  • packages/frontend/src/types.ts
  • packages/frontend/src/utils/ai.ts
  • packages/frontend/src/utils/clipboard.ts
  • packages/frontend/src/views/App.vue
  • packages/frontend/vitest.config.ts
  • packages/shared/src/results.ts

Comment thread eslint.config.js
"packages/frontend/vitest.config.ts",
],
},
]; No newline at end of file
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix trailing newline to satisfy Prettier.

Line 22 currently fails formatting checks due to missing final newline.

🧹 Minimal fix
 export default [
   ...defaultConfig({
     compat: false,
   }),
   {
     files: ["packages/frontend/**/*.{ts,vue}"],
     languageOptions: {
       globals: {
         ...globals.browser,
       },
     },
   },
   {
     ignores: [
       "packages/backend/vitest.config.ts",
       "packages/frontend/vitest.config.ts",
     ],
   },
 ];
+
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
];
export default [
...defaultConfig({
compat: false,
}),
{
files: ["packages/frontend/**/*.{ts,vue}"],
languageOptions: {
globals: {
...globals.browser,
},
},
},
{
ignores: [
"packages/backend/vitest.config.ts",
"packages/frontend/vitest.config.ts",
],
},
];
🧰 Tools
🪛 ESLint

[error] 22-22: Insert

(prettier/prettier)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@eslint.config.js` at line 22, Add a final newline at the end of the file so
the trailing "];" line ends with a newline to satisfy Prettier/formatting
checks; locate the closing array/semicolon token (the "];" line in
eslint.config.js) and ensure the file ends with a single newline character.

return { error: "No requests found" };
}

const regex = new RegExp(pattern, "is");
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -n -C3 'new RegExp\(pattern, "is"\)|GrepPatternSchema' packages
fd -HI '^package\.json$' -x rg -n '"(re2|safe-regex|safe-regex2)"' {}

Repository: caido-community/data-grep

Length of output: 1995


🏁 Script executed:

# Get the full GrepPatternSchema definition
sed -n '46,70p' packages/backend/src/validation/schemas.ts

# Check the imports and implementation in grep.ts
head -30 packages/backend/src/services/grep.ts

# Search for re2 imports and usage
rg -n "re2|import.*re2" packages

Repository: caido-community/data-grep

Length of output: 1186


🏁 Script executed:

# Check if re2 is actually imported anywhere in the backend
rg -n "import.*re2|require.*re2" packages/backend

# Check the full grep.ts to understand the scope of pattern execution
wc -l packages/backend/src/services/grep.ts

# Look at the extractMatches and buildRegexFilter utilities
cat -n packages/backend/src/utils/grep.ts | head -80

Repository: caido-community/data-grep

Length of output: 2412


🏁 Script executed:

# Check the exact usage of regex at line 152 - see what happens after construction
sed -n '145,170p' packages/backend/src/services/grep.ts

# See if there's any usage of the regex object after construction
sed -n '152,250p' packages/backend/src/services/grep.ts | head -50

Repository: caido-community/data-grep

Length of output: 1709


Use the re2 library for regex execution instead of native RegExp to prevent ReDoS attacks.

This service compiles user-supplied patterns with native JavaScript RegExp and executes them over request/response bodies. A catastrophic backtracking pattern can hang the grep worker and block the entire operation. The GrepPatternSchema only validates syntax, not safety. Since re2 (^1.21.4) is already in your dependencies, replace new RegExp(pattern, "is") at line 152 with re2 to enforce polynomial-time regex matching.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/backend/src/services/grep.ts` at line 152, Replace the native RegExp
instantiation with the RE2 implementation: import RE2 from 're2' at the top of
packages/backend/src/services/grep.ts and change the line that creates regex
(currently const regex = new RegExp(pattern, "is")) to use new RE2(pattern,
"is") so user-supplied patterns are executed by re2 (polynomial-time) instead of
the native engine; keep the same variable name (regex) and types where used so
the rest of the grep logic (pattern matching over request/response bodies)
continues to work.

Comment on lines +170 to +175
const stopSearch = () => {
// Update UI immediately so user sees the stop
store.status.isSearching = false;
store.results.cancelled = true;
// Fire-and-forget — backend stop resolves asynchronously
stopGrep();
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Don’t mark the scan cancelled before stopGrep() succeeds.

stopGrep() is async and already reports backend errors. Flipping store.status.isSearching and store.results.cancelled first makes the UI say the scan stopped even when the backend rejects the stop request, and it removes the Stop button before the user can retry.

Suggested fix
-const stopSearch = () => {
-  // Update UI immediately so user sees the stop
-  store.status.isSearching = false;
-  store.results.cancelled = true;
-  // Fire-and-forget — backend stop resolves asynchronously
-  stopGrep();
+const stopSearch = async () => {
+  const stopped = await stopGrep();
+  if (!stopped) return;
+
+  store.status.isSearching = false;
+  store.results.cancelled = true;
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/frontend/src/components/results/Results.vue` around lines 170 - 175,
The UI flips store.status.isSearching and store.results.cancelled before the
async stopGrep() completes, causing the UI to show a stopped scan even if the
backend stop fails; change stopSearch so it awaits stopGrep() (or handles its
Promise) and only set store.status.isSearching = false and
store.results.cancelled = true after stopGrep() resolves successfully, and on
rejection keep the searching state and surface the error (so the Stop button
remains available for retry); update the stopSearch function to await stopGrep()
and move the state mutations into the success path.

Comment on lines +12 to +18
<Dialog
v-model:visible="batchSearchStore.showWarningDialog"
modal
header="Search All Secrets"
:style="{ width: '500px' }"
:dismissable-mask="false"
>
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

find . -type f -name "BatchSearchDialog.vue" -o -name "batchSearchStore.ts" | head -20

Repository: caido-community/data-grep

Length of output: 189


🏁 Script executed:

cat -n ./packages/frontend/src/components/search/batch/BatchSearchDialog.vue | head -50

Repository: caido-community/data-grep

Length of output: 2055


🏁 Script executed:

cat -n ./packages/frontend/src/components/search/batch/BatchSearchDialog.vue | tail -20

Repository: caido-community/data-grep

Length of output: 673


🏁 Script executed:

cat -n ./packages/frontend/src/stores/batchSearchStore.ts

Repository: caido-community/data-grep

Length of output: 6894


🏁 Script executed:

# Let me check PrimeVue Dialog documentation behavior with a web search
# to confirm the default close mechanisms

Repository: caido-community/data-grep

Length of output: 51


🌐 Web query:

PrimeVue Dialog component default close button escape key behavior

💡 Result:

PrimeVue Dialog close button / Escape key behavior (default): 1) Close (X) button visibility - The “X” close button is rendered only when the dialog is closable. In the Dialog source, the close button slot/button is wrapped in v-if="closable". - Therefore, if you set :closable="false", the close button is not shown. 2) Escape key behavior - PrimeVue’s Dialog supports closing on Escape via the closeOnEscape prop: pressing Escape calls this.close only when closeOnEscape is true. - From the Dialog documentation’s accessibility keyboard support table: escape “Closes the dialog if closeOnEscape is true.” 3) Interaction between closable=false and Escape - There have been reported issues/edge cases where Escape did not work when closable was false, indicating historical coupling/bug. For example, PrimeVue issue reports state that closeOnEscape was not working when closable is false. - In the component implementation, Escape handling is tied to closeOnEscape, not to closable; however the presence/absence of the close button affects the real-world behavior/focus in those reported cases. Practical answer for your question (“default close button escape key behavior”): - By default, if the dialog is closable (close button visible) and closeOnEscape is enabled, Escape closes the dialog. - If you disable the close button (closable=false), Escape should still close when closeOnEscape=true, but PrimeVue has had bugs/regressions in this exact scenario—so verify on your PrimeVue version, especially around 4.1–4.3 where issues were reported. If you share your PrimeVue version and whether you set closeOnEscape / closable, I can tell you the most likely behavior for that exact version.

Citations:


🏁 Script executed:

# Check PrimeVue version in package.json
grep -A2 '"primevue"' ./package.json

Repository: caido-community/data-grep

Length of output: 51


🏁 Script executed:

find . -name "package.json" -type f | xargs grep -l "primevue" | head -5

Repository: caido-community/data-grep

Length of output: 101


🏁 Script executed:

cat ./packages/frontend/package.json | grep -A5 '"primevue"'

Repository: caido-community/data-grep

Length of output: 194


Route every dialog close path through closeWarningDialog().

By default, PrimeVue Dialog has closable=true and closeOnEscape=true. When users close the dialog via the close button or Escape key, only showWarningDialog is updated through the v-model binding. The closeWarningDialog() method is not called, leaving pendingOptions set (see packages/frontend/src/stores/batchSearchStore.ts:155-158). This creates inconsistent state if startBatchSearch() is invoked again. Add :closable="false", :close-on-escape="false", and @hide="batchSearchStore.closeWarningDialog" to ensure all close paths clear pending options.

Suggested fix
   <Dialog
     v-model:visible="batchSearchStore.showWarningDialog"
     modal
     header="Search All Secrets"
     :style="{ width: '500px' }"
     :dismissable-mask="false"
+    :closable="false"
+    :close-on-escape="false"
+    `@hide`="batchSearchStore.closeWarningDialog"
   >
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/frontend/src/components/search/batch/BatchSearchDialog.vue` around
lines 12 - 18, The Dialog close paths must route through
batchSearchStore.closeWarningDialog so pendingOptions is always cleared; update
the Dialog in BatchSearchDialog.vue to disable built-in closing and bind the
hide event by setting :closable="false" and :close-on-escape="false" and adding
`@hide`="batchSearchStore.closeWarningDialog" (the v-model can remain bound to
batchSearchStore.showWarningDialog) so any user close (button/escape/other)
calls closeWarningDialog() and keeps startBatchSearch() consistent.

Comment on lines +33 to +35
const handleSearch = () => {
batchSearchStore.resetBatchState();
grepStore.searchGrepRequests();
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Prevent normal and batch searches from starting over each other.

Both flows mutate the same grepStore state. handleSearch() unconditionally clears batch state and starts a normal grep, while the batch button can still kick off a batch run that reinitializes grepStore for accumulation. If either path is triggered mid-run, results/progress for the active search get overwritten.

Also applies to: 64-70

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/frontend/src/components/search/Form.vue` around lines 33 - 35,
handleSearch currently unconditionally calls batchSearchStore.resetBatchState()
and grepStore.searchGrepRequests(), which allows a normal search to interrupt a
running batch (and vice versa) because both mutate the same grepStore; update
handleSearch to first check a running flag (e.g., grepStore.isRunning or
batchSearchStore.isBatchRunning) and return or disable starting a normal search
if a batch run is active, and likewise modify the batch-start path (the batch
button handler referenced around lines 64-70) to check the same running flag and
avoid calling batchSearchStore.resetBatchState() or
grepStore.searchGrepRequests() when the other flow is active; use a single
canonical running/mode flag on grepStore (or batchSearchStore) to coordinate and
prevent concurrent starts.

Comment on lines +166 to +168
name: "JFrog Artifactory Key",
pattern: "\\b([a-zA-Z0-9]{64,73})\\b",
category: "CI/CD & DevOps",
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cd packages/frontend && wc -l src/data/secret-patterns.ts

Repository: caido-community/data-grep

Length of output: 100


🏁 Script executed:

head -350 packages/frontend/src/data/secret-patterns.ts | tail -200

Repository: caido-community/data-grep

Length of output: 5646


🏁 Script executed:

cat -n packages/frontend/src/data/secret-patterns.ts | sed -n '160,175p'

Repository: caido-community/data-grep

Length of output: 629


🏁 Script executed:

cat -n packages/frontend/src/data/secret-patterns.ts | sed -n '190,205p'

Repository: caido-community/data-grep

Length of output: 529


🏁 Script executed:

cat -n packages/frontend/src/data/secret-patterns.ts | sed -n '265,275p'

Repository: caido-community/data-grep

Length of output: 494


🏁 Script executed:

cat -n packages/frontend/src/data/secret-patterns.ts | sed -n '315,330p'

Repository: caido-community/data-grep

Length of output: 554


🏁 Script executed:

cat -n packages/frontend/src/stores/batchSearchStore.ts

Repository: caido-community/data-grep

Length of output: 6894


Tighten or remove the context-free secret detectors.

These patterns are so broad that they will dominate batch search with false positives: a bare 64–73 char alnum token, semver-like \d+\.\d+\.\d+, any 44–80 char token, and any 6-digit number are all common non-secret text. In this UI, that means "Search All Secrets" will routinely swamp real findings. Please add provider-specific prefixes/context or drop these entries.

Also applies to: lines 197-199, 269-270, 321-323

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/frontend/src/data/secret-patterns.ts` around lines 166 - 168, The
"JFrog Artifactory Key" detector (pattern "\\b([a-zA-Z0-9]{64,73})\\b") and
several other entries use overly broad, context-free patterns (bare 64–73 alnum
tokens, semver-like \d+\.\d+\.\d+, 44–80 char tokens, 6-digit numbers) that
produce many false positives; update those entries to either remove them or
tighten them by requiring provider-specific context/prefixes (e.g.,
repository/hostname, header names, known token prefixes) or replace with
stricter regexes that include surrounding keywords, or drop the entries
entirely—apply this change to the "JFrog Artifactory Key" entry and the other
context-free detectors referenced in the file so that only provider-specific or
contextual patterns remain.

Comment on lines +27 to +29
// Maps match value -> category for filtering results
const matchCategoryMap = ref(new Map<string, SecretPatternCategory>());
const selectedResultCategory = ref<SecretPatternCategory | "all">("all");
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Use a stable per-match key for category mapping.

This map is keyed only by match.value, so the same string found in different requests or matched by overlapping patterns will overwrite previous categories. Once that happens, category filtering becomes nondeterministic. Key this by a stable match identity instead of the raw value alone.

🔧 Suggested fix
-import type { GrepOptions } from "shared";
+import type { GrepOptions, MatchResult } from "shared";
@@
-  const matchCategoryMap = ref(new Map<string, SecretPatternCategory>());
+  const matchCategoryMap = ref(new Map<string, SecretPatternCategory>());
+
+  const getMatchKey = (match: MatchResult) =>
+    `${match.requestId}:${match.source}:${match.startIndex}:${match.endIndex}:${match.value}`;
@@
-              matchCategoryMap.value.set(match.value, pattern.category);
+              matchCategoryMap.value.set(getMatchKey(match), pattern.category);
@@
-  function getMatchCategory(value: string): SecretPatternCategory | undefined {
-    return matchCategoryMap.value.get(value);
+  function getMatchCategory(
+    match: MatchResult,
+  ): SecretPatternCategory | undefined {
+    return matchCategoryMap.value.get(getMatchKey(match));
   }

Also applies to: 104-110, 166-168

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/frontend/src/stores/batchSearchStore.ts` around lines 27 - 29,
matchCategoryMap is keyed only by match.value which causes collisions across
requests and overlapping patterns; change the map to use a stable per-match key
(e.g., a generated stableMatchId or a composite key like
`${requestId}:${matchIndex}` or an inherent match.id) wherever entries are
created/updated (see matchCategoryMap usage and the code that populates it
around the existing mapping sites and the other occurrences noted). Update the
places that read/write this map (including the logic that sets and reads
selectedResultCategory) to use this stable key so categories are deterministic
across requests and overlaps, and ensure any helpers that produce keys are
consistently used in the three locations currently using match.value as the key.

Comment on lines +148 to +153
function cancelSearch() {
status.cancelled = true;
grepStore.status.isSearching = false;
grepStore.results.cancelled = true;
grepRepository.stopGrep();
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Await the stop before marking the UI idle.

cancelSearch() flips both stores out of the searching state before the backend confirms the grep has actually stopped. If the stop is slow or fails, the UI looks idle while the next search can still hit “A grep scan is already running”.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/frontend/src/stores/batchSearchStore.ts` around lines 148 - 153, The
cancelSearch() function currently flips status.cancelled,
grepStore.status.isSearching, and grepStore.results.cancelled before calling
grepRepository.stopGrep(); change this to await the asynchronous stop operation
first (await grepRepository.stopGrep()), and only set
grepStore.status.isSearching = false and grepStore.results.cancelled = true
after stopGrep resolves; also keep status.cancelled set immediately (or set it
before awaiting) so intent is recorded, and add a catch around await
grepRepository.stopGrep() to restore/adjust UI state
(grepStore.status.isSearching) or surface an error if stopping fails.

Comment on lines +43 to 45
currentPatternName.value = "";
results.searchResults = undefined;
status.isSearching = true;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Don’t clear currentPatternName at search start.

packages/frontend/src/stores/patternsStore.ts sets this immediately before launching a saved/secret pattern search. Resetting it here strips the label from normal pattern-driven searches, so the results view can no longer tell users which pattern produced the matches.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/frontend/src/stores/grepStore.ts` around lines 43 - 45, The code
clears currentPatternName.value at the start of a search which wipes out the
label set by patternsStore; remove the line that sets currentPatternName.value =
"" so pattern-driven searches retain their label, but keep the other
initializations (results.searchResults = undefined and status.isSearching =
true) intact; locate and edit the search-starting code where currentPatternName,
results.searchResults, and status.isSearching are set and delete only the
currentPatternName reset.

Comment on lines +98 to +107
if (newResults.length >= 25000) {
const truncatedResults = newResults.slice(0, 25000);
truncatedResults.push({
value: "!!! Results truncated to 25K. Export to view more",
requestId: "",
source: "request",
startIndex: 0,
endIndex: 0,
});
results.searchResults = truncatedResults;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix the truncation off-by-one.

With >= 25000, an exact 25,000-result search gets marked as truncated and receives the synthetic warning row even though nothing was dropped.

🔧 Suggested fix
-        if (newResults.length >= 25000) {
+        if (newResults.length > 25000) {
           const truncatedResults = newResults.slice(0, 25000);
           truncatedResults.push({
             value: "!!! Results truncated to 25K. Export to view more",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (newResults.length >= 25000) {
const truncatedResults = newResults.slice(0, 25000);
truncatedResults.push({
value: "!!! Results truncated to 25K. Export to view more",
requestId: "",
source: "request",
startIndex: 0,
endIndex: 0,
});
results.searchResults = truncatedResults;
if (newResults.length > 25000) {
const truncatedResults = newResults.slice(0, 25000);
truncatedResults.push({
value: "!!! Results truncated to 25K. Export to view more",
requestId: "",
source: "request",
startIndex: 0,
endIndex: 0,
});
results.searchResults = truncatedResults;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/frontend/src/stores/grepStore.ts` around lines 98 - 107, The
truncation logic incorrectly treats exactly 25,000 results as truncated; update
the check in the block that assigns results.searchResults (the
newResults/truncatedResults handling) to only treat cases where
newResults.length > 25000 as truncated, then slice to 25,000 and append the
synthetic warning row; ensure the condition uses > 25000 (not >= 25000) so an
exact 25,000-result set is left unchanged and does not receive the warning
entry.

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.

2 participants