crewAIInc/crewAI · error · ValueError
Security Alert: Invalid database identifier detected: {name}
Error message
Security Alert: Invalid database identifier detected: {name} What it means
DB2VectorSearchTool._validate_identifier guards against SQL injection by regex-matching table and column names: identifiers must start with a letter and contain only letters, digits, or underscores (optionally one period between two such identifiers when allow_period=True, for schema.table). Any name failing the pattern raises ValueError with a 'Security Alert' prefix. This applies to table_name, vector_column, every entry of return_columns, and filter_by — not to user data, only to identifiers embedded in SQL.
Source
Thrown at lib/crewai-tools/src/crewai_tools/tools/db2_search_tool/db2_search_tool.py:206
finally:
self.connection = None
self.dbi_connection = None
self.cursor = None
def _validate_identifier(self, name: str, allow_period: bool = False) -> str:
"""
Validates table and column names to prevent SQL injection.
Simple identifiers must start with a letter and contain only letters, digits,
or underscores. Schema-qualified names (allow_period=True) allow exactly one
period separating two valid simple identifiers (e.g. myschema.mytable).
"""
pattern = (
r"^[A-Za-z][A-Za-z0-9_]*(\.[A-Za-z][A-Za-z0-9_]*)?$"
if allow_period
else r"^[A-Za-z][A-Za-z0-9_]*$"
)
if not re.match(pattern, name):
raise ValueError(
f"Security Alert: Invalid database identifier detected: {name}"
)
return name
def _get_openai_client(self) -> Any:
if self._openai_client is None:
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
raise ValueError(
"OPENAI_API_KEY environment variable is missing. Required for default embeddings."
)
openai = importlib.import_module("openai")
self._openai_client = openai.OpenAI(api_key=api_key)
return self._openai_client
def _generate_embedding(self, text: str) -> list[float]:
if self.custom_embedding_fn:
return self.custom_embedding_fn(text)View on GitHub (pinned to 754d7323be)
Solutions
- Use plain identifiers: letters, digits, underscores, starting with a letter (e.g. 'MYSCHEMA.MYTABLE' for schema-qualified tables).
- If the real DB2 name contains special characters, create a view or alias with a compliant name and point the tool at it.
- Never pass SQL fragments, expressions, or quoted identifiers — only bare names.
- Validate names with the same regex in your config loading to fail before tool construction.
Example fix
# before tool = DB2VectorSearchTool(table_name='my-schema."my table"', vector_column='vec-col', return_columns=['id']) # after tool = DB2VectorSearchTool(table_name='my_schema.my_table', vector_column='vec_col', return_columns=['id'])
Defensive patterns
Strategy: validation
Validate before calling
import re
IDENT = re.compile(r'^[A-Za-z][A-Za-z0-9_]*$')
IDENT_DOTTED = re.compile(r'^[A-Za-z][A-Za-z0-9_]*(\.[A-Za-z][A-Za-z0-9_]*)?$')
def valid_identifiers(table: str, vector_column: str, columns: list[str]) -> bool:
return bool(IDENT_DOTTED.match(table) and IDENT.match(vector_column)
and all(IDENT.match(c) for c in columns)) Type guard
def is_simple_identifier(name: object) -> bool:
return isinstance(name, str) and bool(re.match(r'^[A-Za-z][A-Za-z0-9_]*$', name)) Try / catch
try:
tool = DB2VectorSearchTool(table_name=t, vector_column=v, return_columns=cols)
except ValueError as e:
if 'Invalid database identifier' in str(e):
raise ConfigError(f'rename or create a view for {t!r}; identifiers must be [A-Za-z_][A-Za-z0-9_]*(.name)?') from e
raise Prevention
- Create DB2 objects with unquoted, underscore-only names from the start.
- Where DDL forced special characters, add a view with a compliant name and query that.
- Never accept identifiers from LLM output without running them through the same regex first.
When it happens
Trigger: table_name='my-schema.my table', vector_column='vec-col', return_columns=['select'], or filter_by='dept; DROP TABLE x' — any identifier containing hyphens, spaces, quotes, semicolons, digits at the start, or non-ASCII. Also names quoted with backticks or double quotes.
Common situations: DB2 schemas/tables created with special characters that were quoted at DDL time; LLM-generated tool configuration echoing prose instead of identifiers; attempts to pass expressions ('COUNT(*)') or aliases where a bare column is required.
Related errors
- Invalid skill reference: org and name must be single, non-em
- Blocked path traversal attempt: {member.name!r}
- Blocked unsupported tar member: {member.name!r}
- Blocked link target escaping destination: {member.name!r} ->
- Blocked path traversal attempt: {member!r}
AI-assisted analysis of crewAIInc/crewAI@754d7323be (2026-08-15).
Data as JSON: /api/errors/f9bf9b6d984710e2.
Report an issue: GitHub.