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

  1. Use plain identifiers: letters, digits, underscores, starting with a letter (e.g. 'MYSCHEMA.MYTABLE' for schema-qualified tables).
  2. If the real DB2 name contains special characters, create a view or alias with a compliant name and point the tool at it.
  3. Never pass SQL fragments, expressions, or quoted identifiers — only bare names.
  4. 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

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


AI-assisted analysis of crewAIInc/crewAI@754d7323be (2026-08-15). Data as JSON: /api/errors/f9bf9b6d984710e2. Report an issue: GitHub.