mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-08-10 16:32:28 +00:00
docs: document NL2SQL read-only enforcement and its limits
The page claimed read-only mode blocked "multi-statement queries containing semicolons" and said nothing about CTEs, EXPLAIN ANALYZE, or the fact that a SELECT can still reach the database server's filesystem. Both gaps matter now that those routes are enforced. - Replace the semicolon sentence with a table of every indirect write route blocked in read-only mode: multi-statement, writable CTEs (including AS MATERIALIZED), a write after a CTE, EXPLAIN ANALYZE, INTO OUTFILE, server-filesystem functions, and unparseable WITH statements. - Explain that analysis masks literals and comments, so `SELECT 'DROP TABLE users'` is allowed while `EXPLAIN /*x*/ ANALYZE DELETE ...` is blocked, and that a semicolon inside a literal no longer splits statements. - Document the new SET TRANSACTION READ ONLY backstop and which backends fall back without it. - Add a warning that these checks are defence in depth and a least-privileged read-only database role is the only complete control. Every example in the new table was verified against the implementation. Applied to en/ar/ko/pt-BR under docs/edge; the ko and pt-BR pages carry the warning inline as they have no Hardening Recommendations section. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -27,6 +27,10 @@ mode: "wide"
|
|||||||
|
|
||||||
## توصيات التقوية
|
## توصيات التقوية
|
||||||
|
|
||||||
|
<Warning>
|
||||||
|
تُعد فحوصات القراءة فقط المدمجة طبقة دفاع إضافية، وليست حدًا كاملًا. فهي تفحص نص العبارة، ولغة SQL تختلف باختلاف نظام قواعد البيانات: إذ يمكن لعبارة تبدأ بـ `SELECT` أن تصل إلى نظام ملفات خادم قاعدة البيانات (`SELECT ... INTO OUTFILE`، `pg_read_file()`) أو أن تستدعي دالة ذات آثار جانبية. تُحظر المنافذ المعروفة صراحةً، لكن التحكم الكامل الوحيد هو الصلاحيات التي تمنحها في `db_uri`. **وجّه الأداة إلى دور قاعدة بيانات للقراءة فقط بأقل الصلاحيات الممكنة.**
|
||||||
|
</Warning>
|
||||||
|
|
||||||
استخدم جميع الإجراءات التالية في بيئة الإنتاج:
|
استخدم جميع الإجراءات التالية في بيئة الإنتاج:
|
||||||
|
|
||||||
- استخدم مستخدم قاعدة بيانات للقراءة فقط كلما أمكن
|
- استخدم مستخدم قاعدة بيانات للقراءة فقط كلما أمكن
|
||||||
@@ -47,7 +51,21 @@ mode: "wide"
|
|||||||
|
|
||||||
أي محاولة لتنفيذ عملية كتابة (`INSERT`، `UPDATE`، `DELETE`، `DROP`، `CREATE`، `ALTER`، `TRUNCATE`، إلخ) ستُسبب خطأً ما لم يتم تفعيل DML صراحةً.
|
أي محاولة لتنفيذ عملية كتابة (`INSERT`، `UPDATE`، `DELETE`، `DROP`، `CREATE`، `ALTER`، `TRUNCATE`، إلخ) ستُسبب خطأً ما لم يتم تفعيل DML صراحةً.
|
||||||
|
|
||||||
كما تُحظر الاستعلامات متعددة العبارات التي تحتوي على فاصلة منقوطة (مثل `SELECT 1; DROP TABLE users`) في وضع القراءة فقط لمنع هجمات الحقن.
|
كما يحظر وضع القراءة فقط الطرق غير المباشرة للكتابة:
|
||||||
|
|
||||||
|
| المحظور في وضع القراءة فقط | مثال |
|
||||||
|
| --- | --- |
|
||||||
|
| الاستعلامات متعددة العبارات | `SELECT 1; DROP TABLE users` |
|
||||||
|
| تعبيرات CTE الكاتبة، بما في ذلك صيغة `MATERIALIZED` | `WITH d AS MATERIALIZED (DELETE FROM users RETURNING *) SELECT * FROM d` |
|
||||||
|
| عملية كتابة تلي تعبير CTE | `WITH d AS (SELECT 1) DELETE FROM users` |
|
||||||
|
| `EXPLAIN ANALYZE`، الذي ينفّذ العبارة التابعة له فعليًا | `EXPLAIN ANALYZE DELETE FROM users` |
|
||||||
|
| الكتابة إلى نظام ملفات خادم قاعدة البيانات | `SELECT * FROM users INTO OUTFILE '/var/www/shell.php'` |
|
||||||
|
| الدوال التي تصل إلى نظام ملفات الخادم أو تفتح اتصالًا جديدًا | `SELECT pg_read_file('/etc/passwd')`، `dblink_exec(...)` |
|
||||||
|
| عبارة `WITH` يتعذّر تحليلها للتأكد من أنها للقراءة فقط | `WITH d AS DELETE FROM users` |
|
||||||
|
|
||||||
|
تُحلَّل العبارات بعد إخفاء النصوص الحرفية والتعليقات، لذا لا تُعامَل كلمة مفتاحية مخبأة داخل نص حرفي على أنها أمر (`SELECT 'DROP TABLE users'` مسموح)، ولا يُخفي تعليقٌ موضوع بين الكلمات المفتاحية أمرًا (`EXPLAIN /*x*/ ANALYZE DELETE ...` محظور). كما أن الفاصلة المنقوطة داخل نص حرفي ليست فاصلًا بين العبارات، لذا فإن `SELECT ';'` عبارة واحدة صحيحة.
|
||||||
|
|
||||||
|
في وضع القراءة فقط، تضع الأداة أيضًا المعاملة في حالة `SET TRANSACTION READ ONLY`، فترفض PostgreSQL وMySQL عمليات الكتابة على مستوى قاعدة البيانات مهما كانت صياغة العبارة. أما الأنظمة التي لا تدعم هذه الصيغة (SQLite، SQL Server، Snowflake) فتُسجّل رسالة تصحيح وتعود إلى الاعتماد على فحص العبارات وحده — وهذا سبب إضافي للاعتماد على دور للقراءة فقط بدلًا من التحليل النصي.
|
||||||
|
|
||||||
### تفعيل عمليات الكتابة
|
### تفعيل عمليات الكتابة
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,10 @@ If you route untrusted input to agents using this tool, treat it as a high-risk
|
|||||||
|
|
||||||
## Hardening Recommendations
|
## Hardening Recommendations
|
||||||
|
|
||||||
|
<Warning>
|
||||||
|
The built-in read-only checks are defence in depth, not a complete boundary. They inspect the statement text, and SQL is dialect-specific: a statement beginning with `SELECT` can still reach the database server's filesystem (`SELECT ... INTO OUTFILE`, `pg_read_file()`) or call a side-effecting function. The known sinks are blocked explicitly, but the only complete control is the privileges you grant in `db_uri`. **Point the tool at a least-privileged, read-only database role.**
|
||||||
|
</Warning>
|
||||||
|
|
||||||
Use all of the following in production:
|
Use all of the following in production:
|
||||||
|
|
||||||
- Use a read-only database user whenever possible
|
- Use a read-only database user whenever possible
|
||||||
@@ -49,7 +53,21 @@ Use all of the following in production:
|
|||||||
|
|
||||||
Any attempt to execute a write operation (`INSERT`, `UPDATE`, `DELETE`, `DROP`, `CREATE`, `ALTER`, `TRUNCATE`, etc.) will raise an error unless DML is explicitly enabled.
|
Any attempt to execute a write operation (`INSERT`, `UPDATE`, `DELETE`, `DROP`, `CREATE`, `ALTER`, `TRUNCATE`, etc.) will raise an error unless DML is explicitly enabled.
|
||||||
|
|
||||||
Multi-statement queries containing semicolons (e.g. `SELECT 1; DROP TABLE users`) are also blocked in read-only mode to prevent injection attacks.
|
Read-only mode also blocks the indirect routes to a write:
|
||||||
|
|
||||||
|
| Blocked in read-only mode | Example |
|
||||||
|
| --- | --- |
|
||||||
|
| Multi-statement queries | `SELECT 1; DROP TABLE users` |
|
||||||
|
| Writable CTEs, including the materialised spelling | `WITH d AS MATERIALIZED (DELETE FROM users RETURNING *) SELECT * FROM d` |
|
||||||
|
| A write following a CTE | `WITH d AS (SELECT 1) DELETE FROM users` |
|
||||||
|
| `EXPLAIN ANALYZE`, which executes its argument | `EXPLAIN ANALYZE DELETE FROM users` |
|
||||||
|
| Writes to the database server's filesystem | `SELECT * FROM users INTO OUTFILE '/var/www/shell.php'` |
|
||||||
|
| Functions reaching the server's filesystem or opening a new connection | `SELECT pg_read_file('/etc/passwd')`, `dblink_exec(...)` |
|
||||||
|
| A `WITH` statement that cannot be parsed as read-only | `WITH d AS DELETE FROM users` |
|
||||||
|
|
||||||
|
Statements are analysed with string literals and comments masked out, so a keyword hidden in a literal is not mistaken for a command (`SELECT 'DROP TABLE users'` is allowed) and a comment placed between keywords does not hide one (`EXPLAIN /*x*/ ANALYZE DELETE ...` is blocked). A semicolon inside a string literal does not count as a statement separator, so `SELECT ';'` is a single valid statement.
|
||||||
|
|
||||||
|
In read-only mode the tool additionally marks the transaction `SET TRANSACTION READ ONLY`, so PostgreSQL and MySQL reject writes at the database regardless of how the statement was spelled. Backends without that syntax (SQLite, SQL Server, Snowflake) log a debug message and fall back to statement validation alone — one more reason to rely on a read-only role rather than on parsing.
|
||||||
|
|
||||||
### Enabling Write Operations
|
### Enabling Write Operations
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,25 @@ mode: "wide"
|
|||||||
|
|
||||||
DML을 명시적으로 활성화하지 않으면 쓰기 작업(`INSERT`, `UPDATE`, `DELETE`, `DROP`, `CREATE`, `ALTER`, `TRUNCATE` 등)을 실행하려고 할 때 오류가 발생합니다.
|
DML을 명시적으로 활성화하지 않으면 쓰기 작업(`INSERT`, `UPDATE`, `DELETE`, `DROP`, `CREATE`, `ALTER`, `TRUNCATE` 등)을 실행하려고 할 때 오류가 발생합니다.
|
||||||
|
|
||||||
읽기 전용 모드에서는 세미콜론이 포함된 다중 구문 쿼리(예: `SELECT 1; DROP TABLE users`)도 인젝션 공격을 방지하기 위해 차단됩니다.
|
읽기 전용 모드는 우회 경로를 통한 쓰기도 차단합니다:
|
||||||
|
|
||||||
|
| 읽기 전용 모드에서 차단됨 | 예시 |
|
||||||
|
| --- | --- |
|
||||||
|
| 다중 구문 쿼리 | `SELECT 1; DROP TABLE users` |
|
||||||
|
| 쓰기 CTE(`MATERIALIZED` 표기 포함) | `WITH d AS MATERIALIZED (DELETE FROM users RETURNING *) SELECT * FROM d` |
|
||||||
|
| CTE 뒤에 오는 쓰기 작업 | `WITH d AS (SELECT 1) DELETE FROM users` |
|
||||||
|
| 인자를 실제로 실행하는 `EXPLAIN ANALYZE` | `EXPLAIN ANALYZE DELETE FROM users` |
|
||||||
|
| 데이터베이스 서버 파일시스템에 대한 쓰기 | `SELECT * FROM users INTO OUTFILE '/var/www/shell.php'` |
|
||||||
|
| 서버 파일시스템에 접근하거나 새 연결을 여는 함수 | `SELECT pg_read_file('/etc/passwd')`, `dblink_exec(...)` |
|
||||||
|
| 읽기 전용임을 확인할 수 없는 `WITH` 구문 | `WITH d AS DELETE FROM users` |
|
||||||
|
|
||||||
|
구문은 문자열 리터럴과 주석을 가린 상태에서 분석됩니다. 따라서 리터럴 안에 숨은 키워드는 명령으로 오인되지 않고(`SELECT 'DROP TABLE users'`는 허용), 키워드 사이에 삽입된 주석이 명령을 숨기지도 못합니다(`EXPLAIN /*x*/ ANALYZE DELETE ...`는 차단). 문자열 리터럴 안의 세미콜론은 구문 구분자로 세지 않으므로 `SELECT ';'`는 유효한 단일 구문입니다.
|
||||||
|
|
||||||
|
읽기 전용 모드에서는 트랜잭션에 `SET TRANSACTION READ ONLY`도 적용하므로, PostgreSQL과 MySQL은 구문 표기 방식과 무관하게 데이터베이스 차원에서 쓰기를 거부합니다. 해당 구문을 지원하지 않는 백엔드(SQLite, SQL Server, Snowflake)는 디버그 로그를 남기고 구문 검증에만 의존합니다. 파싱이 아니라 읽기 전용 역할에 의존해야 하는 이유가 하나 더 있는 셈입니다.
|
||||||
|
|
||||||
|
<Warning>
|
||||||
|
내장된 읽기 전용 검사는 완전한 경계가 아니라 심층 방어 수단입니다. 이 검사는 구문 텍스트를 검사하며 SQL은 데이터베이스마다 다릅니다. `SELECT`로 시작하는 구문도 데이터베이스 서버의 파일시스템에 접근하거나(`SELECT ... INTO OUTFILE`, `pg_read_file()`) 부수 효과가 있는 함수를 호출할 수 있습니다. 알려진 경로는 명시적으로 차단하지만, 완전한 통제 수단은 `db_uri`에 부여하는 권한뿐입니다. **최소 권한의 읽기 전용 데이터베이스 역할을 사용하십시오.**
|
||||||
|
</Warning>
|
||||||
|
|
||||||
### 쓰기 작업 활성화
|
### 쓰기 작업 활성화
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,25 @@ O `NL2SQLTool` opera em **modo somente leitura por padrão**. Apenas os seguinte
|
|||||||
|
|
||||||
Qualquer tentativa de executar uma operação de escrita (`INSERT`, `UPDATE`, `DELETE`, `DROP`, `CREATE`, `ALTER`, `TRUNCATE`, etc.) resultará em erro, a menos que o DML seja habilitado explicitamente.
|
Qualquer tentativa de executar uma operação de escrita (`INSERT`, `UPDATE`, `DELETE`, `DROP`, `CREATE`, `ALTER`, `TRUNCATE`, etc.) resultará em erro, a menos que o DML seja habilitado explicitamente.
|
||||||
|
|
||||||
Consultas com múltiplas instruções contendo ponto e vírgula (ex.: `SELECT 1; DROP TABLE users`) também são bloqueadas no modo somente leitura para prevenir ataques de injeção.
|
O modo somente leitura também bloqueia os caminhos indiretos para uma escrita:
|
||||||
|
|
||||||
|
| Bloqueado no modo somente leitura | Exemplo |
|
||||||
|
| --- | --- |
|
||||||
|
| Consultas com múltiplas instruções | `SELECT 1; DROP TABLE users` |
|
||||||
|
| CTEs de escrita, incluindo a forma `MATERIALIZED` | `WITH d AS MATERIALIZED (DELETE FROM users RETURNING *) SELECT * FROM d` |
|
||||||
|
| Uma escrita após uma CTE | `WITH d AS (SELECT 1) DELETE FROM users` |
|
||||||
|
| `EXPLAIN ANALYZE`, que executa seu argumento | `EXPLAIN ANALYZE DELETE FROM users` |
|
||||||
|
| Escrita no sistema de arquivos do servidor de banco de dados | `SELECT * FROM users INTO OUTFILE '/var/www/shell.php'` |
|
||||||
|
| Funções que alcançam o sistema de arquivos do servidor ou abrem uma nova conexão | `SELECT pg_read_file('/etc/passwd')`, `dblink_exec(...)` |
|
||||||
|
| Uma instrução `WITH` que não pode ser confirmada como somente leitura | `WITH d AS DELETE FROM users` |
|
||||||
|
|
||||||
|
As instruções são analisadas com literais de texto e comentários mascarados, de modo que uma palavra-chave escondida em um literal não é confundida com um comando (`SELECT 'DROP TABLE users'` é permitido) e um comentário colocado entre palavras-chave não esconde nenhum (`EXPLAIN /*x*/ ANALYZE DELETE ...` é bloqueado). Um ponto e vírgula dentro de um literal não conta como separador de instruções, portanto `SELECT ';'` é uma única instrução válida.
|
||||||
|
|
||||||
|
No modo somente leitura, a ferramenta também marca a transação como `SET TRANSACTION READ ONLY`, de forma que PostgreSQL e MySQL rejeitam escritas no próprio banco de dados, independentemente de como a instrução foi escrita. Backends sem essa sintaxe (SQLite, SQL Server, Snowflake) registram uma mensagem de depuração e voltam a depender apenas da validação de instruções — mais um motivo para confiar em um papel somente leitura em vez da análise textual.
|
||||||
|
|
||||||
|
<Warning>
|
||||||
|
As verificações internas de somente leitura são defesa em profundidade, não uma fronteira completa. Elas inspecionam o texto da instrução, e SQL é específico de cada banco: uma instrução que começa com `SELECT` ainda pode alcançar o sistema de arquivos do servidor (`SELECT ... INTO OUTFILE`, `pg_read_file()`) ou chamar uma função com efeitos colaterais. Os caminhos conhecidos são bloqueados explicitamente, mas o único controle completo são os privilégios concedidos em `db_uri`. **Aponte a ferramenta para um papel de banco de dados somente leitura e com privilégio mínimo.**
|
||||||
|
</Warning>
|
||||||
|
|
||||||
### Habilitando Operações de Escrita
|
### Habilitando Operações de Escrita
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user