crewai - ✅(Solved) Fix Security: Request to enable Private Vulnerability Reporting / coordinate channel [1 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
crewAIInc/crewAI#5728Fetched 2026-05-07 03:39:53
View on GitHub
Comments
0
Participants
1
Timeline
1
Reactions
0
Participants
Timeline (top)
cross-referenced ×1

Fix Action

Fixed

PR fix notes

PR #5729: fix(memory): escape user input in LanceDBStorage SQL filters (#5728)

Description (problem / solution / changelog)

Summary

Fixes #5728. LanceDBStorage interpolated caller-supplied scope paths and record IDs directly into the WHERE clauses passed to LanceDB's where(), which accepts a raw Apache DataFusion SQL expression and does not support parameterized queries. This allowed:

  • Scope-isolation bypass. A caller restricted to one scope could escape that sandbox and read or delete records belonging to any other scope. The most damaging example, reproduced before the fix:
    storage.delete(scope_prefix="/alpha' OR scope LIKE '/%")
    deleted every record in the table instead of just /alpha's subtree, because the resulting WHERE evaluated to scope LIKE '/alpha' OR scope LIKE '/%' OR scope = '/'.
  • Crashes on legitimate input. Ordinary scope paths or record IDs containing an apostrophe (e.g. "/O'Brien", "O'Reilly-42") raised RuntimeError: Unterminated string literal in list_records, list_scopes, get_scope_info, list_categories, delete(record_ids=…), and reset(scope_prefix=…).

The 4 reported sinks all routed through lib/crewai/src/crewai/memory/storage/lancedb_storage.py:

  1. search(scope_prefix=…)
  2. delete(scope_prefix=…)
  3. delete(record_ids=…)
  4. reset(scope_prefix=…) (plus everything that goes through _scan_rows: list_records, list_scopes, get_scope_info, list_categories, count).

Fix

Added two private helpers on LanceDBStorage:

  • _escape_sql_str(value) — doubles single quotes for string literals (O'BrienO''Brien).
  • _escape_like(value) — additionally escapes the SQL LIKE metacharacters %, _, and \, so that a caller-supplied prefix is matched as a literal, not as a glob.

Every user-controlled value in search, delete, reset, _scan_rows, update, get_record, and touch_records is now routed through the appropriate helper. LIKE clauses now use ESCAPE '\\' so %/_ in scope paths are treated as literals.

Note: update, get_record, and touch_records already escaped IDs inline via replace("'", "''"). Those callsites were switched to the shared helper for consistency, but their behaviour is unchanged.

Tests

Added lib/crewai/tests/memory/test_lancedb_storage_security.py with 12 regression tests covering every sink:

  • helper unit tests for _escape_sql_str and _escape_like,
  • injection payloads against search, delete(scope_prefix), delete(record_ids), and reset — including the delete(scope_prefix="/alpha' OR scope LIKE '/%") payload from the report — asserting that no unintended record is touched,
  • legitimate-input round-trips for apostrophe-containing scopes and IDs across all scan-based readers,
  • assertions that % in a caller-supplied scope_prefix is treated as a literal, not a wildcard.

All existing memory tests in lib/crewai/tests/memory/ continue to pass.

Review & Testing Checklist for Human

  • Confirm the ESCAPE '\\' clause is supported by the minimum LanceDB version pinned in lib/crewai/pyproject.toml. DataFusion has supported it for a long time, but worth a quick sanity check against the lockfile.
  • Verify that no production caller relied on % or _ in a scope_prefix actually behaving as a wildcard (this PR turns them into literals — which matches the documented "scope path" semantics, but is a behaviour change for any code that was using LIKE-style globs).
  • Skim the diff against lancedb_storage.py to confirm no other f-string-built WHERE clause was missed (I searched for all of them; the placeholder-row delete on line 210 is the only remaining one and uses a hard-coded literal).

Notes

Reproduction script (pre-fix output) and a per-sink demonstration are included in the linked session. The 4 sinks called out in the issue all flow through this file; no other module in crewai (and no module in crewai-tools) builds a LanceDB where() from caller-supplied input.

Reporter (@ibondarenko1) does not need their CVSS-9.6 PoC to verify — the deterministic delete(scope_prefix="/alpha' OR scope LIKE '/%") test in this PR is the same class of bug.

Link to Devin session: https://app.devin.ai/sessions/75235e5dd2a74ca4a347a558ef7cc052

Changed files

  • lib/crewai/src/crewai/memory/storage/lancedb_storage.py (modified, +51/-11)
  • lib/crewai/tests/memory/test_lancedb_storage_security.py (added, +271/-0)
RAW_BUFFERClick to expand / collapse

Hello CrewAI team,

I have responsibly verified a security finding in the crewai package on the latest PyPI release (1.14.4) and the latest main HEAD (ec8a522). Per SECURITY.md the official disclosure channel is the Bugcrowd VDP at https://security.crewai.com.

I attempted submission via that form. The form populated cleanly:

  • Title, Target (CrewAI OSS), VRT Category (Server-Side Injection), VRT Subcategory (SQL Injection — Bugcrowd VRT predicted P1 Critical), description (~10K chars), researcher email, terms accepted.
  • Seven supporting attachments uploaded successfully (each HTTP 201 to bugcrowd-attachments-us-east-1-production.s3.amazonaws.com/).
  • However the final Report vulnerability button did not produce a submission POST in the network log over multiple attempts.
  • Bugcrowd form id (for your reference): 1bdce1ef-6153-4283-81d5-f169b6dd4b36/external/report.

Could a maintainer please either:

  1. Confirm whether the Bugcrowd intake received my report (researcher email: [email protected]), or
  2. Enable GitHub Private Vulnerability Reporting on this repository so I can file a draft GHSA via the standard GitHub flow, or
  3. Share a direct security contact email I can use.

I will not share technical details publicly until a private channel is established. The finding affects the LanceDB-backed memory subsystem and rates CVSS 9.6 (P1 Critical) per Bugcrowd VRT (Server-Side Injection / SQL Injection class). I have a deterministic 4-sink replay, verified PASS on pip install crewai (1.14.4).

Thank you for your attention,

@ibondarenko1 ([email protected])

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING