# ArcadeDB: Privilege escalation via reader role in /api/v1/command JS scripting language — arbitrary host file read

ArcadeDB reader-role users could POST a js-language command to /api/v1/command, bypassing authz and the GraalVM sandbox via reflection to read arbitrary host files.

- Payout: Research
- Severity: high
- Program: ArcadeDB
- Found by: kyojune76
- Disclosed: 2026-07-16
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-48qw-824m-86pr
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-48qw-824m-86pr
- Tags: area:web domain:api domain:web impact:data-leak kind:research platform:ghsa sev:high tech:java technique:source-review vuln:access-control vuln:auth-bypass vuln:info-disclosure vuln:privilege-escalation

**Target:** HTTP command API /api/v1/command/{database} with GraalVM polyglot scripting
**Root cause:** Polyglot script execution (js and other GraalVM languages) skipped the database authorization checks applied to SQL/Cypher, and the GraalVM sandbox's allowedPackages whitelist was bypassable by reflecting off the bound database object to reach a ClassLoader.
**Steps:**
1. Authenticate with an account holding only `reader` privileges on a database.
2. Send `POST /api/v1/command/{database}` with a body specifying `"language": "js"` and a script payload.
3. In the script, escape the sandbox: `database.getClass().getClassLoader().loadClass("java.io.File")`.
4. Use the loaded class to read host files such as `/etc/passwd` and configuration files.
**How found:** Not described beyond the advisory's root-cause breakdown: the reporter noticed the scripting path never passed through the SQL/Cypher authorization checks, then found that reflecting off the bound `database` object reached a ClassLoader and defeated the allowedPackages sandbox restriction.
**Exploitation:** Any authenticated principal, regardless of database role, could submit a js-language command to the HTTP command endpoint. The script ran without database authorization checks; reflecting off the bound `database` object yielded a ClassLoader, allowing arbitrary class loading despite the allowedPackages whitelist. Process creation was blocked (allowCreateProcess(false)), so the achieved impact was host file read (confidentiality high), not command execution.
**Insight:** When a product sandboxes a scripting engine with a package allowlist, check whether any bound/global object exposes getClass() — a ClassLoader reachable from a whitelisted object nullifies the allowlist entirely. Also test alternate query languages (js, cypher, etc.) against the same endpoint, since authz is often wired only into the primary SQL path.

