CVE-2026-85737
Velociraptor: Low-priv analyst reads arbitrary server files via ungated sql() VQL plugin
Velociraptor is a tool for collecting host-based state information using Velociraptor Query Language (VQL) queries. Prior to 0.77.2, SQLPlugin.Call in vql/parsers/sql/sql.go does not enforce plugin-level FILESYSTEM_READ or NETWORK checks before the mysql and postgres branches pass a caller-controlled connstring to sql.Open, allowing arbitrary outbound database connections. With attacker-controlled MySQL connection options that enable local-infile access, a rogue MySQL server can request files readable by the Velociraptor server process, including root-readable files when that process runs as root. The SQLite file accessor still enforces FILESYSTEM_READ, but a low-privilege analyst with ANY_QUERY can use the zero-permission data accessor and ATTACH DATABASE to create files without the plugin-level check. This issue is fixed in version 0.77.2.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- Low
- User interaction
- None
What an attacker can affect
- Confidentiality
- High
- Integrity
- None
- Availability
- None
Exploit likelihood
What each source reports
CVE List Score used 6.5
Velociraptor: Low-priv analyst reads arbitrary server files via ungated sql() VQL plugin
Velociraptor is a tool for collecting host-based state information using Velociraptor Query Language (VQL) queries. Prior to 0.77.2, SQLPlugin.Call in vql/parsers/sql/sql.go does not enforce plugin-level FILESYSTEM_READ or NETWORK checks before the mysql and postgres branches pass a caller-controlled connstring to sql.Open, allowing arbitrary outbound database connections. With attacker-controlled MySQL connection options that enable local-infile access, a rogue MySQL server can request files readable by the Velociraptor server process, including root-readable files when that process runs as root. The SQLite file accessor still enforces FILESYSTEM_READ, but a low-privilege analyst with ANY_QUERY can use the zero-permission data accessor and ATTACH DATABASE to create files without the plugin-level check. This issue is fixed in version 0.77.2.
- Record
CVE-2026-85737- CVSS 3.1
- 6.5 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N - Weakness
- CWE-862
- Updated
- 2026-11-10
EUVDEUVD-2026-118460 6.5
Velociraptor is a tool for collecting host-based state information using Velociraptor Query Language (VQL) queries. Prior to 0.77.2, SQLPlugin.Call in vql/parsers/sql/sql.go does not enforce plugin-level FILESYSTEM_READ or NETWORK checks before the mysql and postgres branches pass a caller-controlled connstring to sql.Open, allowing arbitrary outbound database connections. With attacker-controlled MySQL connection options that enable local-infile access, a rogue MySQL server can request files readable by the Velociraptor server process, including root-readable files when that process runs as root. The SQLite file accessor still enforces FILESYSTEM_READ, but a low-privilege analyst with ANY_QUERY can use the zero-permission data accessor and ATTACH DATABASE to create files without the plugin-level check. This issue is fixed in version 0.77.2.
- Record
EUVD-2026-118460- CVSS 3.1
- 6.5 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N - Updated
- 2026-11-10
GitHub AdvisoriesGHSA-9qq5-422f-33c2 6.5
Velociraptor: Low-priv analyst reads arbitrary server files via ungated sql() VQL plugin
Summary
The sql() VQL plugin runs a caller-supplied database driver and connection string with no permission check (vql/parsers/sql/sql.go:93, SQLPlugin.Call). For driver='mysql' or driver='postgres' the handle comes from GetHandleOther (sql.go:39), which passes the connection string straight to Go database/sql sql.Open (sql.go:51) and executes the query (sql.go:159).
The plugin declares FILESYSTEM_READ only as Info().Permissions metadata (sql.go:219). That metadata is never consulted at runtime: metadata.go:19 stores it as a string that only the documentation exporter reads (api/reflect.go:82-110). Every sibling network plugin (http_client, netcat, s3, rsyslog) calls CheckAccess(acls.NETWORK) in its own body; sql() calls nothing.
The built-in analyst role holds ANY_QUERY but not FILESYSTEM_READ or NETWORK (acls/roles.go:222), and reaches this sink through the notebook query API.
Result: a low-priv analyst opens arbitrary outbound TCP connections and, through a rogue MySQL server's LOAD DATA LOCAL INFILE, reads any file the root-running server can read, including the deployment CA private key.
Affected
- Velocidex/velociraptor server,
<= v0.77.1(latest release, 2026-06-23). Identical vulnerable code inmasterHEAD1961e79(2026-07-17). - Confirmed live-exploitable on the official
ghcr.io/velocidex/velociraptor-server:latestimage (build 0.77.1, commit bbe2a58). - Stock install, default Basic authenticator, any built-in
analyst,investigator, orapirole (all holdANY_QUERY, none holdsFILESYSTEM_READorNETWORK). - No non-default flag required.
Root cause
SQLPlugin.Call (vql/parsers/sql/sql.go:93) parses the caller driver, connstring, and query arguments and reaches handle.Query (sql.go:159) without any vql_subsystem.CheckAccess call in its body. For driver='mysql' or driver='postgres' the handle comes from GetHandleOther (sql.go:39), which hands the attacker connection string to sql.Open (sql.go:51), so the plugin dials an arbitrary host and, through the MySQL client LOAD DATA LOCAL INFILE feature, reads local files. The plugin states its intended gate only as metadata, VQLMetadata().Permissions(acls.FILESYSTEM_READ) (sql.go:219), but MetadataBuilder.Permissions merely stores a string (vql/metadata.go:19) that is read only by the reflection exporter (api/reflect.go:82-110), never by the query engine. Every sibling network plugin enforces CheckAccess(acls.NETWORK) in its own body, so the omission in sql() is an enforcement oversight. The default analyst role grants ANY_QUERY without FILESYSTEM_READ or NETWORK (acls/roles.go:222), so a user the operator deliberately restricted still reaches the ungated sink.
Note on intent: acls/acls.go documents that specific permission combinations grant admin-equivalent power (SERVER_ARTIFACT_WRITER with COLLECT_SERVER, ARTIFACT_WRITER with COLLECT_CLIENT), but the analyst role holds none of them and is denied EXECVE, NETWORK, and FILESYSTEM_READ on every sibling plugin. If ANY_QUERY is nonetheless intended as trusted, the plugin's own Permissions(FILESYSTEM_READ) metadata and the runtime enforcement on all sibling plugins are misleading and should be reconciled; otherwise this is a missing runtime check.
Reproduction
ghcr.io/velocidex/velociraptor-server:latest (v0.77.1), default config, GUI on https://localhost:8889, one built-in analyst user.
As
analyst, confirm the control: the gated accessor denies the read.sql(driver='sqlite', accessor='file', file='/etc/passwd', query='SELECT 1') => sql: Field file Accessor file: PermissionDenied: Permission denied: [FILESYSTEM_READ]
Start a rogue MySQL server on an attacker host that completes the handshake and answers any query with a
LOAD DATA LOCAL INFILE <target>packet.As the same
analyst, call the ungated branch through the notebook…
- Record
GHSA-9qq5-422f-33c2- CVSS 3.1
- 6.5 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N - Weakness
- CWE-862
- Updated
- 2026-11-09
NVD 6.5
Velociraptor is a tool for collecting host-based state information using Velociraptor Query Language (VQL) queries. Prior to 0.77.2, SQLPlugin.Call in vql/parsers/sql/sql.go does not enforce plugin-level FILESYSTEM_READ or NETWORK checks before the mysql and postgres branches pass a caller-controlled connstring to sql.Open, allowing arbitrary outbound database connections. With attacker-controlled MySQL connection options that enable local-infile access, a rogue MySQL server can request files readable by the Velociraptor server process, including root-readable files when that process runs as root. The SQLite file accessor still enforces FILESYSTEM_READ, but a low-privilege analyst with ANY_QUERY can use the zero-permission data accessor and ATTACH DATABASE to create files without the plugin-level check. This issue is fixed in version 0.77.2.
- Record
CVE-2026-85737- CVSS 3.1
- 6.5 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N - Weakness
- CWE-862
- Updated
- 2026-11-10
OSV 6.5
Velociraptor: Low-priv analyst reads arbitrary server files via ungated sql() VQL plugin
Velociraptor is a tool for collecting host-based state information using Velociraptor Query Language (VQL) queries. Prior to 0.77.2, SQLPlugin.Call in vql/parsers/sql/sql.go does not enforce plugin-level FILESYSTEM_READ or NETWORK checks before the mysql and postgres branches pass a caller-controlled connstring to sql.Open, allowing arbitrary outbound database connections. With attacker-controlled MySQL connection options that enable local-infile access, a rogue MySQL server can request files readable by the Velociraptor server process, including root-readable files when that process runs as root. The SQLite file accessor still enforces FILESYSTEM_READ, but a low-privilege analyst with ANY_QUERY can use the zero-permission data accessor and ATTACH DATABASE to create files without the plugin-level check. This issue is fixed in version 0.77.2.
- Record
CVE-2026-85737- CVSS 3.1
- 6.5 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N - Weakness
- CWE-862
- Updated
- 2026-11-08
OSVGHSA-9qq5-422f-33c2 6.5
Velociraptor: Low-priv analyst reads arbitrary server files via ungated sql() VQL plugin
Summary
The sql() VQL plugin runs a caller-supplied database driver and connection string with no permission check (vql/parsers/sql/sql.go:93, SQLPlugin.Call). For driver='mysql' or driver='postgres' the handle comes from GetHandleOther (sql.go:39), which passes the connection string straight to Go database/sql sql.Open (sql.go:51) and executes the query (sql.go:159).
The plugin declares FILESYSTEM_READ only as Info().Permissions metadata (sql.go:219). That metadata is never consulted at runtime: metadata.go:19 stores it as a string that only the documentation exporter reads (api/reflect.go:82-110). Every sibling network plugin (http_client, netcat, s3, rsyslog) calls CheckAccess(acls.NETWORK) in its own body; sql() calls nothing.
The built-in analyst role holds ANY_QUERY but not FILESYSTEM_READ or NETWORK (acls/roles.go:222), and reaches this sink through the notebook query API.
Result: a low-priv analyst opens arbitrary outbound TCP connections and, through a rogue MySQL server's LOAD DATA LOCAL INFILE, reads any file the root-running server can read, including the deployment CA private key.
Affected
- Velocidex/velociraptor server,
<= v0.77.1(latest release, 2026-06-23). Identical vulnerable code inmasterHEAD1961e79(2026-07-17). - Confirmed live-exploitable on the official
ghcr.io/velocidex/velociraptor-server:latestimage (build 0.77.1, commit bbe2a58). - Stock install, default Basic authenticator, any built-in
analyst,investigator, orapirole (all holdANY_QUERY, none holdsFILESYSTEM_READorNETWORK). - No non-default flag required.
Root cause
SQLPlugin.Call (vql/parsers/sql/sql.go:93) parses the caller driver, connstring, and query arguments and reaches handle.Query (sql.go:159) without any vql_subsystem.CheckAccess call in its body. For driver='mysql' or driver='postgres' the handle comes from GetHandleOther (sql.go:39), which hands the attacker connection string to sql.Open (sql.go:51), so the plugin dials an arbitrary host and, through the MySQL client LOAD DATA LOCAL INFILE feature, reads local files. The plugin states its intended gate only as metadata, VQLMetadata().Permissions(acls.FILESYSTEM_READ) (sql.go:219), but MetadataBuilder.Permissions merely stores a string (vql/metadata.go:19) that is read only by the reflection exporter (api/reflect.go:82-110), never by the query engine. Every sibling network plugin enforces CheckAccess(acls.NETWORK) in its own body, so the omission in sql() is an enforcement oversight. The default analyst role grants ANY_QUERY without FILESYSTEM_READ or NETWORK (acls/roles.go:222), so a user the operator deliberately restricted still reaches the ungated sink.
Note on intent: acls/acls.go documents that specific permission combinations grant admin-equivalent power (SERVER_ARTIFACT_WRITER with COLLECT_SERVER, ARTIFACT_WRITER with COLLECT_CLIENT), but the analyst role holds none of them and is denied EXECVE, NETWORK, and FILESYSTEM_READ on every sibling plugin. If ANY_QUERY is nonetheless intended as trusted, the plugin's own Permissions(FILESYSTEM_READ) metadata and the runtime enforcement on all sibling plugins are misleading and should be reconciled; otherwise this is a missing runtime check.
Reproduction
ghcr.io/velocidex/velociraptor-server:latest (v0.77.1), default config, GUI on https://localhost:8889, one built-in analyst user.
As
analyst, confirm the control: the gated accessor denies the read.sql(driver='sqlite', accessor='file', file='/etc/passwd', query='SELECT 1') => sql: Field file Accessor file: PermissionDenied: Permission denied: [FILESYSTEM_READ]
Start a rogue MySQL server on an attacker host that completes the handshake and answers any query with a
LOAD DATA LOCAL INFILE <target>packet.As the same
analyst, call the ungated branch through the notebook…
- Record
GHSA-9qq5-422f-33c2- CVSS 3.1
- 6.5 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N - Weakness
- CWE-862
- Updated
- 2026-11-09
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
www.velocidex.com/golang/velociraptorGo | through 0.77.1 | 0.77.2 |
www.velocidex.com/golang/velociraptorGo | before 0.77.2 | 0.77.2 |
History
| Recorded | Changed | Sources |
|---|---|---|
| references | CVE List, NVD | |
| published | EUVD | |
| published | EUVD | |
| affected, references | GitHub Advisories | |
| affected, facts, references | OSV | |
| aliases, references | NVD, OSV | |
| first indexed | CVE List, EUVD |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-85737 is a medium vulnerability (CVSS 6.5) in Rapid7 Velociraptor, published November 6, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.24%, the 15th percentile. Fixed in www.velocidex.com/golang/velociraptor 0.77.2.
References
github.com/Velocidex/velociraptor/security/advisories/GHSA-9qq5-422f-33c2
github.com/Velocidex/velociraptor/pull/4952
github.com/Velocidex/velociraptor/commit/d7de958e846d3742a7a3a8538fd463e4f12fc528
github.com/Velocidex/velociraptor/commit/f25390f8fbd00c888f0b7aaba2c061a51c3f7082
github.com/Velocidex/velociraptor/releases/tag/v0.77.2
nvd.nist.gov/vuln/detail/CVE-2026-85737
github.com/advisories/GHSA-9qq5-422f-33c2
github.com/CVEProject/cvelistV5/tree/main/cves/2026/85xxx/CVE-2026-85737.json
github.com/Velocidex/velociraptor
Left out here: the rest of 2 source descriptions. The JSON record has them.