Skip to content

fix(db): reserve server files and enforce trusted SQLite access - #1523

Merged
cevheri merged 3 commits into
mainfrom
fix/storage-reserved-paths
Oct 5, 2026
Merged

cevheri merged 3 commits into
mainfrom
fix/storage-reserved-paths

Conversation

@cevheri

@cevheri cevheri commented Oct 5, 2026 •

Copy link
Copy Markdown
Member

Protect server-owned state from embedded database connection targets. SQLite, DuckDB and LibreDB now refuse reserved paths before opening a handle, including symbolic links, dangling links, existing hard links and SQLite sidecars. Bootstrap credential files are reserved as well; ordinary database files in the same directory remain usable.

SQLite cannot confine statement-level file access with its current adapters, so it refuses connections whose server-derived file-access posture is denied. This affects non-admin users and managed SQLite connections shared with non-admin roles, including agent and MCP access. Trusted cached-factory callers must explicitly pass { allowExternalFileAccess: true }. Cache keys separate denied SQLite callers from trusted handles. Administrator-only connections retain access to ordinary SQLite databases.

Validation:

  • Full suite: 1,078 files passed, 40,973 tests passed, 3 skipped; subsequent targeted tests cover the final path changes and trusted cache fixtures.
  • Merged line coverage: 100% (115,923/115,923) after merging the final targeted regressions.
  • Format, lint, typecheck, knip and chart/channel/readme/security drift checks passed.
  • Final library build and package resolution checks passed.
  • Local default Next.js build is blocked by Turbopack's port-binding EPERM in this environment. The webpack production build compiled successfully, then failed generated route typing on the unchanged agent handover route (HandoverParams | undefined versus RouteContext). CI must verify the default production build.

@codecov

codecov Bot commented Oct 5, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@sonarqubecloud

sonarqubecloud Bot commented Oct 5, 2026

Copy link
Copy Markdown

@cevheri
cevheri merged commit ee7ffe6 into main Oct 5, 2026
35 checks passed
@cevheri
cevheri deleted the fix/storage-reserved-paths branch October 5, 2026 09:18
cevheri added a commit that referenced this pull request Oct 5, 2026
Since #1523 a standard login can no longer open SQLite, so section 14 of the
SQLite page no longer backs the caution. A standard user's DuckDB connection
still reaches any DuckDB-format file whose path it names, which is section
14.3 of docs/providers/duckdb.md.
cevheri added a commit that referenced this pull request Oct 5, 2026
#1529)

#1523 refuses a SQLite connection on the editor path when the server-derived file-access posture is denied, and its PR text and docs (`docs/SECURITY.md`, `docs/providers/sqlite.md`) say agent runs and MCP follow the same rule. The profiled path they use, `acquireExecutionProfileProvider`, opened every handle with the profile's own context, so the posture never reached the provider and the profiled cache key did not carry it.

This passes the requester's posture to the profiled provider and keys the profiled cache on it, with absent read as denied, as on the editor path. The MCP context derives the posture before its join key, and the agent hand-over route derives it from the run's own actor. DuckDB's read-only profile already closes file access whatever the posture, so a profiled DuckDB handle opens as before; its profiled cache entries now split by posture as well, which matters only when one record is used under two postures.

Tests first: the three new cases in `tests/isolated/factory.test.ts` failed before the change. The MCP suites' seeds now default to the admin role, because SQLite, the engine they run on, opens only on a seed no other role can use; the hand-over and MCP context tests pin the posture each path passes.

Local gate on the head, rebased onto 7be7181: 1078 files, 40981 pass, 3 skip, 100 percent of lines (115973 of 115973), format, lint, typecheck, knip, the repository checks, `next build`, `build:lib` and `attw`. An independent review found no behaviour defect; its stale-comment and doc findings are in the last commit.
cevheri added a commit that referenced this pull request Oct 5, 2026
…ket app last (#1528)

The auto-connect template installs Studio and `<app>-discovery` in a project named after the app, and CapRover checks each name only when it creates it, removing nothing when a later step fails. With an app name of 40 to 49 characters the install stops at `<app>-discovery` and leaves the project and a running Studio without discovery, and the install form named no limit.

The form text now gives the limit (at most 39 characters, starting with a letter), and `deploy/caprover/README.md` also says what a longer name leaves. The `-discovery` app names Studio in `depends_on`, so the app that holds the Docker socket is always created last; a test pins that order and derives the limit from the template. Creating the socket app first was measured and rejected: with a name already in use it left that app running on its own.

Measured on CapRover 1.15.4: a 40-character name leaves the project and Studio, a name in use leaves only the empty project, and with a 39-character name both apps install and Studio queries the server's PostgreSQL app. The CapRover side is caprover/caprover#2504, fixed in caprover/caprover#2506.

The standard-login caution in the form text and the README now points at section 14.3 of `docs/providers/duckdb.md` instead of section 14 of the SQLite page: since #1523 a standard login can no longer open SQLite, while its DuckDB connection still reaches any DuckDB-format file whose path it names.

Verified: the full local gate passes with 100% line coverage. Nothing in the image or the chart changes.
cevheri added a commit that referenced this pull request Oct 5, 2026
…d three security fixes (#1531)

Carries eight connection types for seven engines: etcd (#1228), IBM Db2 LUW
(#1238), Neo4j with the Graph tab (#1239, #1289), Qdrant (#1270), Milvus
(#1283), InfluxDB and InfluxDB 3 (#1309) and Oxia (#1310). Also CapRover and
DigitalOcean discovery (#1502, #1378, #1528), launch sign-in for hosting
platforms (#1516), and any number of local accounts with passkeys (#1122,
#1195).

Three security fixes: the OIDC state cookie is no longer accepted as a
session (#1380), a non-admin role's DuckDB connection opens with file and
network access off (#1519), and SQLite, DuckDB and LibreDB connections refuse
Studio's own storage and credential files, with SQLite open to admins only in
the editor, agent runs and MCP alike (#1523, #1529). Chart 0.1.78 is flagged
containsSecurityUpdates, and its description calls Trino by its own name, the
rename #1158 left for this bump.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant