September 26, 2026
From File Preview to Server-Side File Read: Testing DuckDB SQL Execution
At first glance, a SQL query feature inside an ETL platform doesnβt look particularly dangerous.

By CyberSpire
4 min read
An authenticated user selects a table, writes a query, and gets the results back. It is exactly what you'd expect from a data-processing application.
The application was using DuckDB to process data, and DuckDB provides lightweight library, eliminating server management and network latency.
Understanding the Feature
The application provided a Workspace where an authenticated user could select a table and execute SQL queries against their ETL data.
The intended workflow was roughly:
User
β
Workspace
β
Select Table
β
Execute SQL
β
Query Authorized ETL Data
β
Display ResultsUser
β
Workspace
β
Select Table
β
Execute SQL
β
Query Authorized ETL Data
β
Display ResultsThis is a legitimate and useful feature.
The security question was:
Is the SQL execution environment restricted to the user's authorized ETL data, or can SQL access resources belonging to the underlying server?
Looking at DuckDB
The application used DuckDB as part of its SQL/data-processing workflow.
DuckDB provides functions for reading external data sources directly from SQL.
One of those functions is:
read_csv()read_csv()
For example, a normal use case might be:
SELECT *
FROM read_csv('/path/to/authorized/data.csv');SELECT *
FROM read_csv('/path/to/authorized/data.csv');The security concern appears when a user can control that path.
If the backend simply executes the supplied SQL, the SQL engine may become capable of reading files that were never intended to be available through the Workspace.
1) Testing Server-Side File Access
I started with a controlled test using a system file that is commonly available on Linux systems.
The SQL query used for validation was:
SELECT * FROM read_csv('/etc/passwd');SELECT * FROM read_csv('/etc/passwd');If the SQL engine is properly restricted, the request should be rejected.
Instead, the Workspace returned content from the underlying server filesystem.
That confirmed something important:
The authenticated user could make the server-side DuckDB process read a file outside the intended ETL data scope.
The important point here is that the query is executed by the backend, not by my local machine.
The request flow becomes:
My Browser
β
Workspace API
β
Backend
β
DuckDB
β
Server filesystem
β
/etc/passwdMy Browser
β
Workspace API
β
Backend
β
DuckDB
β
Server filesystem
β
/etc/passwd2) Testing the Tenant Boundary
The next question was even more important for a multi-tenant application:
Could the same SQL functionality access another tenant's data?
I used two controlled tenant accounts.
The intended model was:
Tenant A
βββ Tenant A data
Tenant B
βββ Tenant B dataTenant A
βββ Tenant A data
Tenant B
βββ Tenant B dataA Tenant B user should never be able to query Tenant A's uploaded dataset.
During testing, I identified the server-side path associated with a controlled uploaded CSV file.
I then tested whether that file could be referenced directly through DuckDB.
The sanitized example was:
SELECT *
FROM read_csv(
'/app/data/uploads/<tenant-specific-path>/controlled-test.csv'
);SELECT *
FROM read_csv(
'/app/data/uploads/<tenant-specific-path>/controlled-test.csv'
);
The exact production path and identifiers are intentionally omitted here.
Two Security Boundaries Were Crossed
The testing demonstrated two related issues through the same functionality.
1. Server-Side File Access
A user-controlled SQL query could make DuckDB read files from the underlying server filesystem.
SELECT * FROM read_csv('/etc/passwd');SELECT * FROM read_csv('/etc/passwd');2. Cross-Tenant Data Access
A user from one tenant could use a server-side file path to access a controlled dataset belonging to another tenant.
SELECT *
FROM read_csv('/app/data/uploads/<other-tenant-path>/file.csv');SELECT *
FROM read_csv('/app/data/uploads/<other-tenant-path>/file.csv');So the actual security model looked like:
Expected:
User
β
Workspace
β
Authorized ETL DataUser
β
Workspace
β
Authorized ETL DataBut the tested behavior allowed:
User
β
Workspace SQL
β
DuckDB read_csv()
βββ Server filesystem
βββ Other tenant's dataUser
β
Workspace SQL
β
DuckDB read_csv()
βββ Server filesystem
βββ Other tenant's dataWhy read_csv() Was the Interesting Attack Surface
The SQL query itself wasn't necessarily the vulnerability.
The problem was the combination of:
User-controlled SQL
+
Powerful DuckDB functions
+
Server-side file access
+
Insufficient authorization/isolationUser-controlled SQL
+
Powerful DuckDB functions
+
Server-side file access
+
Insufficient authorization/isolationIndividually, each component may appear legitimate.
Together, they created a security boundary violation.
What I Found Next: DuckDB read_parquet()
While testing other DuckDB file-access functionality, I also looked at read_parquet(). That led to another interesting behavior involving server-side outbound requests (SSRF).
The read_csv() behavior and the read_parquet() behavior are related because both originate from the same SQL execution capability, but they represent different security impacts.
I'll cover the read_parquet() SSRF behavior and the testing approach in a separate article.
Security Impact
The demonstrated impact included:
- Unauthorized server-side file read
- Cross-tenant data exposure
- Disclosure of internal filesystem paths
- Potential access to other application-managed files
- Potential exposure of confidential ETL datasets
The actual impact depends on what files are accessible to the DuckDB/ETL process.
How Should This Be Fixed?
1. Restrict file-reading functions
Functions such as:
read_csv()
read_parquet()read_csv()
read_parquet()should only be able to access explicitly approved locations.
2. Don't allow arbitrary paths
The application should not allow a user to provide an arbitrary server filesystem path through SQL.
3. Enforce tenant authorization
Before a dataset is accessed, the backend should verify:
Authenticated User
β
Tenant
β
Dataset
β
Authorized?Authenticated User
β
Tenant
β
Dataset
β
Authorized?4. Isolate processing environments
Each tenant or ETL job should have an appropriately isolated execution context where possible.
5. Use least privilege
The DuckDB/ETL process should run with only the filesystem permissions it actually needs.
It should not have unnecessary access to:
System files
Application configuration
Credentials
Other tenant directories
Unrelated application dataSystem files
Application configuration
Credentials
Other tenant directories
Unrelated application data6. Prevent information disclosure
Internal filesystem paths and backend debugging information should not be returned to users.
Practical Testing Checklist
When assessing a SQL/data-processing feature, I recommend checking:
β What SQL functions are available?
β Can SQL read local files?
β Can SQL access external URLs?
β Can users specify filesystem paths?
β Are paths restricted to approved directories?
β Can one tenant reference another tenant's files?
β Are table and dataset identifiers authorization-checked?
β Does the backend expose internal filesystem paths?
β Is the SQL execution environment isolated?
β What OS permissions does the processing service have?β What SQL functions are available?
β Can SQL read local files?
β Can SQL access external URLs?
β Can users specify filesystem paths?
β Are paths restricted to approved directories?
β Can one tenant reference another tenant's files?
β Are table and dataset identifiers authorization-checked?
β Does the backend expose internal filesystem paths?
β Is the SQL execution environment isolated?
β What OS permissions does the processing service have?The key is to test the boundary, not just the SQL functionality.
A feature that is designed to query data should only be able to query the data the user is authorized to access.
Final Takeaway
The interesting part of this vulnerability wasn't simply that DuckDB supports read_csv().
The real issue was that a user-controlled SQL interface exposed that capability without sufficiently restricting the resources available to the SQL execution environment.
A seemingly normal workflow:
Workspace β SQL Query β ResultsWorkspace β SQL Query β Resultsbecame:
Workspace
β
User-controlled SQL
β
DuckDB
β
Server filesystem
β
Other tenant's dataWorkspace
β
User-controlled SQL
β
DuckDB
β
Server filesystem
β
Other tenant's dataThat is why SQL execution features deserve the same level of authorization testing as any other sensitive API.
If the application lets users execute code or queries on the server, always ask what the execution environment can actually reach.