Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion providers/common/ai/docs/agent_security.rst
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,17 @@ No single layer is sufficient on its own. They work together.
(``DESCRIBE``/``SHOW``) statements pass; INSERT, UPDATE, DELETE, DROP,
and writes hidden behind ``EXPLAIN`` are rejected.
- Does not prevent the agent from reading sensitive data that the
database user has SELECT access to.
database user has SELECT access to. Without ``allowed_tables`` the check is
Comment thread
Lee-W marked this conversation as resolved.
statement-level only: a side-effecting function inside a SELECT
(``nextval``, ``pg_terminate_backend``, ``dblink_exec``) is not blocked.
Setting ``allowed_tables`` adds a function check, but it rejects only functions
sqlglot cannot type; typed syntax such as T-SQL ``NEXT VALUE FOR`` or Snowflake
``seq.nextval`` still passes. Use a least-privilege role and, where the database
supports it, a read-only default for that role or session (for example
``ALTER ROLE <role> SET default_transaction_read_only = on`` on PostgreSQL).
The toolset opens its own connection per call, so you cannot set a transaction
from the Dag, and a read-only setting is defense in depth: it does not stop every
side-effecting function.
* - **DataFusionToolset: read-only by default**
- ``allow_writes=False`` (default) validates every SQL query through
``validate_sql()`` and rejects CREATE TABLE, CREATE VIEW, INSERT
Expand Down
16 changes: 16 additions & 0 deletions providers/common/ai/docs/toolsets/sql.rst
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,22 @@ rejects by scanning the parsed statement for write operations. When
table, so its target must be on the list, while ``SHOW`` enumerates objects beyond
any single table and is rejected outright (see :ref:`allowed-tables-enforcement`).

The read-only check inspects statement types, not what a function does. By default
(no ``allowed_tables``) a function call inside a ``SELECT`` is not examined, so
``SELECT nextval('seq')``, ``SELECT pg_terminate_backend(pid)`` or
``SELECT dblink_exec(...)`` pass validation and run with the connection's
privileges. Setting ``allowed_tables`` turns on the function check: every function
sqlglot cannot type is rejected unless it is listed in ``allowed_functions``. The
check rejects only functions sqlglot cannot type; typed syntax such as T-SQL
``NEXT VALUE FOR seq`` or Snowflake ``seq.nextval`` still passes, so
``allowed_tables`` is not a guarantee against side-effecting functions. Either way,
point the connection at a least-privilege role and, where the database supports it,
a read-only default for that role or session (for example
``ALTER ROLE <role> SET default_transaction_read_only = on`` on PostgreSQL). The
toolset opens its own connection per call, so you cannot set a transaction from the
Dag, and a read-only setting is defense in depth: it does not stop every
side-effecting function.

.. _sql-toolset-restricted:

Restricting the agent
Expand Down