# Arc has an authenticated arbitrary local-file read via DuckDB I/O functions that bypasses RBAC table-level checks

Arc's SQL denylist missed DuckDB I/O functions like read_csv_auto, letting any authenticated token read local files and hit cloud metadata.

- Payout: Research
- Severity: high
- Program: Arc
- Found by: NeuroWinter
- Disclosed: 2026-06-08
- CVE: CVE-2026-47735
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-p2j4-c4g6-rpf5
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-p2j4-c4g6-rpf5
- Tags: area:web3 domain:api impact:data-leak impact:internal-access kind:research platform:ghsa sev:high tech:go technique:source-review vuln:access-control vuln:info-disclosure vuln:path-traversal vuln:ssrf

**Target:** POST /api/v1/query SQL endpoint backed by DuckDB
**Root cause:** The SQL validator used a regex denylist covering only read_parquet( and arc_partition_agg(, leaving the rest of DuckDB's file/network I/O function family callable. RBAC table-reference extraction only parsed FROM/JOIN, so scalar table functions in the SELECT list escaped tenant scoping.
**Steps:**
1. Authenticate with any valid token, even one with `permissions: []`.
2. Send `POST /api/v1/query` with `Authorization: Bearer <token>`.
3. Body: `{"sql": "SELECT * FROM read_csv_auto('/etc/passwd', header=false, columns={'l':'VARCHAR'}) LIMIT 5"}`.
4. Swap the path for `auth.db`, `arc.toml`, `/proc/self/environ`, or cross-tenant Parquet files.
5. With httpfs loaded, use `read_csv_auto('http://169.254.169.254/latest/meta-data/...')` for SSRF.
**How found:** Reporter noticed the validator was a narrow regex denylist naming only two functions and that RBAC extraction only inspected FROM/JOIN, then tried other DuckDB I/O functions placed in the SELECT list.
**Exploitation:** Any authenticated user submits a SELECT whose scalar table function reads an arbitrary path; results return in the query response, exfiltrating bcrypt hashes, S3/TLS secrets, env vars and other tenants' Parquet data. With httpfs present, the same primitive reaches instance metadata endpoints.
**Escalation:** Cross-tenant data access because RBAC is enforced at the table layer, not on raw file paths; SSRF to 169.254.169.254 when httpfs is loaded in S3-backed deployments.
**Insight:** When a SQL engine exposes table functions, denylisting individual function names is hopeless — enumerate the whole I/O family (read_csv*, read_json*, read_text, read_blob, glob, parquet_metadata, read_xlsx) and check whether your authorization parser only walks FROM/JOIN, since scalar subqueries and SELECT-list table functions bypass it.

## Proof of concept (copied exactly from the original report)

**Authenticated arbitrary local-file read via read_csv_auto**

```
POST /api/v1/query
Authorization: Bearer <token>
{"sql": "SELECT * FROM read_csv_auto('/etc/passwd', header=false, columns={'l':'VARCHAR'}) LIMIT 5"}
```

