@citisen/dsh-github-accelerator
A DeepSeek Harness (dsh) bundle that keeps the
web_fetch tool working when GitHub is reached through a hosts-file accelerator —
SteamCommunity302, Watt Toolkit / Steam++, or anything else that maps domains to
127.0.0.1 and serves them from a local reverse proxy.
Without it, every web_fetch of GitHub fails with:
Error: URL hostname "github.com" resolves to a non-public IP address
Why it fails
dsh's built-in local fetch provider (http) resolves the request hostname, rejects the
whole answer set if any address is not public unicast, and pins a validated address into
the connection. That is the right default for an anonymous fetcher — and it is exactly
what a hosts-file accelerator breaks, because 127.0.0.1 github.com makes the host
resolve to a non-public address by construction.
There is a second wall right behind it. An accelerator that intercepts TLS signs an
on-the-fly certificate with a CA it installed into the operating system certificate
store. Browsers and curl trust it; Node does not read that store, so even with the
address check out of the way the request dies with
UNABLE_TO_GET_ISSUER_CERT_LOCALLY.
What this plugin does
It registers one extra fetch provider, id http-accelerated, that makes exactly one
decision — is the request hostname on the configured allowlist?
- On the allowlist (GitHub by default): the request is sent to whatever the system resolver returns, so the accelerator's loopback endpoint is used, and the operating system's trust anchors are added to the TLS handshake so the accelerator's interception CA is accepted.
- Everything else: handed to the built-in
httpprovider unchanged. Public-address validation, the redirect policy, byte caps, timeouts and error codes stay exactly as shipped.
Ordinary fetching therefore behaves as before. A private destination that is not on
the allowlist (say http://127.0.0.1:8080/) is still refused by the built-in provider.
Requirements
- DeepSeek Harness with the
webservice and the built-inhttpfetch provider (any stock profile). Tested on dsh0.2.1-rc.2(desktop, Electron 44 / Node 24.21). - Node ≥ 24.9 in the
dshhost for the operating-system trust store (tls.getCACertificates). On older runtimes the plugin falls back to Node's bundled roots, and an accelerator's own CA needsinsecureTLS: true.
Install
Through the Web UI: Plugins → install, enter @citisen/dsh-github-accelerator, then
enable it. Or from a terminal:
dsh plugin --profile desktop add @citisen/dsh-github-accelerator
The same package straight from GitHub:
dsh plugin --profile desktop add github:caparisen/dsh-github-accelerator
dsh plugin forwards to pnpm inside the profile and then reconciles
dsh.profile.bundles; because this package declares dsh.bundle, enabling it needs no
hand-edited YAML.
Use --profile web instead of --profile desktop if you run the browser profile from
the CLI. dsh hot-reloads the profile, but fully quit and reopen the application if the
provider does not take effect.
From a local checkout
cd "$DSH_HOME/profiles/desktop"
pnpm add /absolute/path/to/dsh-github-accelerator
then add "@citisen/dsh-github-accelerator" to dsh.profile.bundles in that profile's
package.json. On Windows a link across drives is unreliable in pnpm: it can resolve to
a non-existent path, after which the bundle reconciliation silently skips the package.
Fix the link by hand (rmdir node_modules\@citisen\dsh-github-accelerator, then
mklink /J the real directory) and add the bundle entry yourself.
Configure
The bundle ships a working default (GitHub's own hosts). To change it, override the row
in your profile's cordis.patch.yml — your layer wins over the bundle layer:
- id: web-fetch-accelerated
name: '@citisen/dsh-github-accelerator'
config:
hosts:
- github.com
- '*.github.com'
- '*.githubusercontent.com'
- huggingface.co
- '*.huggingface.co'
| Key | Default | Meaning |
|---|---|---|
hosts |
GitHub hosts | Hostnames allowed to resolve to non-public addresses. *.example.com matches example.com and every subdomain; * matches everything (not recommended) |
trustSystemCertificates |
true |
Add the OS certificate store to the TLS trust anchors for allowlisted hosts. This is what accepts a local accelerator's CA |
insecureTLS |
false |
Skip certificate verification for allowlisted hosts. Last resort only, for a CA that cannot be installed in the store |
timeoutMs |
30000 |
Deadline for one fetch, including the body read |
maxResponseBytes |
5000000 |
Body byte cap; a declared oversize body fails with WEB_FETCH_TOO_LARGE |
maxBodyChars |
100000 |
Decoded character cap; longer bodies are truncated and flagged |
maxRedirects |
5 |
Same-origin redirect hops |
userAgent |
dsh's default UA | Request header |
providerId / baseProviderId |
http-accelerated / http |
Provider ids; change only if you know why |
selfTestUrl |
empty | When set, the plugin fetches this URL once at startup through ctx.web.fetch and logs the result — a one-line health check |
Most accelerators cover far more than GitHub (huggingface.co, cdn.jsdelivr.net,
registry-1.docker.io, … — see the #S302 block in your hosts file). Add only hosts
whose resolution you are willing to trust, because allowlisting a hostname disables the
public-address check for it.
Verify
Set selfTestUrl and read the host log at startup:
[web-fetch-accelerated] registered provider "http-accelerated" for 5 host pattern(s): github.com, *.github.com, ...
[web-fetch-accelerated] self-test https://github.com/ -> HTTP 200 html 57684 chars in 812 ms
A web_fetch of https://github.com/ should then return page content, and
https://api.github.com/rate_limit should return JSON.
Security notes
- Allowlisted hosts no longer get the "must be public" check. That is the point of the
plugin, and it is the cost: if an allowlisted name is pointed at an internal service,
web_fetchwill reach it. Keep the list small. - TLS for allowlisted hosts trusts everything the operating system trusts. That matches browser behaviour, and is broader than Node's bundled roots.
- Everything off the allowlist is still handled by the built-in provider, unchanged.
- Only the model-facing
web_fetchpath is affected.git,curland package managers in the shell use their own configuration and were never blocked by this error.
Troubleshooting
| Symptom | Cause and fix |
|---|---|
Still resolves to a non-public IP address |
The provider is not selected, or the host is not allowlisted. Check the startup log line; confirm web's fetchProvider is http-accelerated and the bundle is enabled |
the TLS certificate for … is not trusted |
The accelerator's CA is missing from the OS store, or the runtime is older than Node 24.9. Reinstall the accelerator's certificate, or set insecureTLS: true |
web fetch failed: … ECONNREFUSED … may not be running |
The accelerator is not running, or no longer owns that host |
WEB_PROVIDER_CONFIGURED_MISSING |
The bundle is enabled but the package is not installed (or its files are gone). Reinstall it |
WEB_PROVIDER_UNAVAILABLE / not registered |
The built-in http provider was disabled. This plugin delegates to it and cannot stand alone |
Uninstall
Disable or remove the bundle in the Plugins page, or:
dsh plugin --profile desktop remove @citisen/dsh-github-accelerator
then restart. web's fetchProvider returns to http from dsh-base, and the original
error comes back with it.
How it works
cordis.patch.yml pins the web service to http-accelerated and inserts one row. The
plugin's apply registers a WebFetchProvider that:
- parses the URL and matches the hostname against
hosts; - on a match, performs the request with
node:https/node:httpagainst the system resolver's answer, following same-origin redirects and applying the same body caps, charset decoding andWEB_*error codes as the built-in provider; - otherwise calls the provider registered under
httpand returns its result verbatim.
The provider is a plain ESM module with no @deepseek-ai/* imports, so it can be loaded
and tested outside dsh.
Development
npm test # local HTTP server: redirects, caps, charsets, delegation, errors
npm run test:network # additionally fetches https://github.com/ and https://api.github.com/
npm test needs nothing but Node ≥ 24; npm run test:network needs an accelerator (or
any path to GitHub) on the machine.
License
MIT
No comments yet. Be the first to write one.