Skip to content

List every way DuckLocal reaches the network, and test the local path stays off it - #76

Merged
JetSquirrel merged 5 commits into
mainfrom
feat/network-boundaries
Nov 2, 2026
Merged

JetSquirrel merged 5 commits into
mainfrom
feat/network-boundaries

Conversation

@JetSquirrel

@JetSquirrel JetSquirrel commented Nov 2, 2026 •

Copy link
Copy Markdown
Owner

Part of #64. Closes #68, except for the decision under "Your call".

Why

Someone asked in #29 what guarantees their data stays local. "It's open source" is true but leaves them to do the work. This gives them evidence they can check.

What

docs/network-and-privacy.md lists every outbound path: what starts it, whether it's on by default, where it goes, what it sends, and how to stop it. It also covers what's stored locally, the threat boundaries, how to verify a download, how to build from source, and what a change adding a new path must do.

scripts/check-offline.sh, on Linux CI, runs the CLI and the window over local files under strace and fails on any connection beyond this machine. Before that it runs a control: it makes a real connection attempt and fails unless its filter catches it, because "0 attempts" is also what a blind check would report. Latest result: 0 inet attempts, control caught.

tests/network_paths.rs fails when a network API appears in the source without being listed, and when a telemetry or second HTTP client becomes a direct dependency. It's a text search, so a tripwire rather than a proof.

Tests also pin that the base map and the launch update check start off.

Notices: turning on the base map or the launch check now says where requests go. The S3 dialog and the extension Install button say they download.

What I found

  • The app has one HTTP client in native builds, ureq, used for updates, tiles and S3. Cargo.lock also lists hyper, quinn and a reqwest fork, but those are only for gpui-kit-assets' wasm build. I confirmed this with cargo tree for Windows and Linux; on macOS I only read the manifest, because cargo tree couldn't resolve that target offline here.
  • The README was close but incomplete. It left out extensions and SQL naming remote addresses. Fixed in both languages.
  • A .dash file can reach the network when opened, if httpfs is installed. Its SQL can only read, but read_csv('https://...') is a read, and the URL can carry data from other tables. It can also read any local file you can. This is documented, not changed.

Your call

  1. Should opening an untrusted .dash warn first? The issue asks for a notice "where a workflow first enables an external data source". The notices here cover S3, extensions, tiles and updates, but not a dashboard that names a remote address. Fixing that is a product decision (warn on open? refuse remote addresses until confirmed?), so I've left it. It's the main gap I'd close next.

  2. Updater trust on Windows and Linux. The hash comes from the same server as the package, so it catches corruption but not a compromised server, and those packages aren't signed. The page says so plainly. Whether to sign them is your call.

  3. The reply to this is a cool tool but #29. I haven't posted anything there. Suggested text once this is merged:

    To follow up with something you can check: Network and privacy lists every path that can leave your machine, what it sends, and how to stop it. There's no telemetry or crash upload. CI now traces the app over local files on Linux and fails on any connection beyond the machine, and a test fails if new network code appears without being documented. On macOS or Windows, a per-app firewall gives you the same evidence, and you can build from source. One limit worth knowing: a .dash file runs its read-only SQL when opened, so with httpfs installed, only open dashboards from people you trust.

Limits

  • The runtime check is Linux only, and proves only those paths on that run. It confirms the window started with a dashboard and a map, but not what it drew.
  • Not audited: DuckDB's internals and the other dependencies. The page says so.
  • Facts about third parties (Cloudflare R2 behind dl.ducklocal.app, extensions.duckdb.org) come from the repo's scripts and my own knowledge, so please correct anything wrong.

Testing

  • check-offline.sh passes on Linux CI.
  • cargo test --locked: 460 unit, 4 network-path, CLI and LSP tests pass after merging main, and clippy and fmt are clean.
  • Unrelated flaky test: remote::tests::a_missing_or_stale_endpoint_means_no_window failed once in about 10 runs here and passes otherwise. I think a parallel test grabs the freed port, but haven't proven it. It predates this PR, so I left it.

🤖 Generated with Claude Code

JetSquirrel and others added 5 commits November 2, 2026 15:33
… stays off it

Someone asked in #29 what guarantees that their data stays local. "It's open
source" is true but makes them do the work. This is the evidence.

docs/network-and-privacy.md lists each outbound path: what starts it, whether
it is on by default, where it goes, what it sends and how to stop it. It says
where the boundaries are too, including one worth knowing: with httpfs installed,
a .dash file someone sends can make a network request when it is opened.

scripts/check-offline.sh runs the CLI and the window over local files under
strace on Linux CI, and fails on a connection beyond this machine. A test fails
when a new network API appears in the source until it is listed and documented,
and two more pin that the base map and the launch update check start off.

Turning on the base map or the launch check now says where requests will go,
and the S3 dialog and the extension Install button say they download.

Part of #68.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The search skips a file's test module, so the read-only gate's list of
statements a dashboard may not run was never found there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… none

Its first run reported no attempts at all, which is what it would also report
if it could not see any. It now makes a real attempt under the same tracer and
fails unless that is caught, and that loopback is not.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@JetSquirrel
JetSquirrel marked this pull request as ready for review November 2, 2026 06:48
@JetSquirrel
JetSquirrel merged commit 7e41707 into main Nov 2, 2026
3 checks passed
@JetSquirrel JetSquirrel mentioned this pull request Nov 3, 2026
5 tasks
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.

[P0][Trust] Publish and test DuckLocal's network and privacy boundaries

1 participant