api-relay-audit
toby-bridges
Local security audit for AI API relays and LLM proxies: detects prompt injection, model substitution, tool-call rewriting, SSE anomalies, error leakage, and Web3 wallet risks.
ZSeven-W/dsh-harbor
DeepSeek Harness (DSH) plugin: a read-only ledger for the plugins you already have installed — a capability inventory with file:line evidence, declared-vs-detected reconciliation, cross-profile version drift, and a diff of what changed since the last scan.
PROJECT TOPICS
INSTALL REFERENCE
dsh plugin --profile web add github:ZSeven-W/dsh-harbor
该命令指向仓库当前默认分支;尚无绑定当前 commit 的完整验证结果。
PROJECT README
Evidence-first governance for the DeepSeek Harness plugins already installed on your machine.
Capability Inventory • Declared vs Detected • Runtime Attribution • Conflict Detection • Version Drift • Change Timeline • Upgrade Preflight
npm: @zseven-w/dsh-harbor · Current plugin release: 0.1.0-rc.3 · Tested with DSH 0.1.5-rc.2
English · 简体中文 · 繁體中文 · 日本語 · 한국어 · Français · Español · Deutsch · Português · Русский · हिन्दी · Türkçe · ไทย · Tiếng Việt · Bahasa Indonesia
The Harbor settings page in DSH light mode — live runtime registries, profile-scoped attribution, local version truth, and the change baseline.
DSH plugins run in the host's Node realm with the same local permissions as DSH itself. Harbor does not pretend this can be solved with a score or a badge: it keeps a read-only, evidence-backed ledger of what is installed, what each plugin declares, what its code and live host actually expose, where plugins collide, and what changed since the previous scan.
🔎 Capability InventoryHarbor scans every installed third-party bundle across DSH profiles and reports a fixed 13-capability vocabulary. Source findings carry |
🤝 Declared vs DetectedPlugins may declare |
🟢 Runtime AttributionInside a live DSH host, Harbor enumerates tools, providers, and routes, then attributes them only to plugins installed in the active profile. Missing host registries remain visible as coverage gaps rather than empty proof. |
⚠️ Conflict DetectionThe ledger finds same-profile tool names, route prefixes, provider ids, client-module ids, and order-sensitive message hooks. A quoted route used by a client does not make that client the route owner. |
🧭 Two Version AxesCross-profile drift is local and always offline. The optional upstream check is separate, explicit, registry-aware, credential-redacted, and cached for six hours. |
🕰️ Change TimelineSnapshots track additions, removals, version transitions, profile moves, capability changes, and claim changes. Even two artifacts exchanging profiles are reported as concrete per-profile transitions. |
🛫 Upgrade PreflightBefore you move DSH to a new version, Harbor installs that exact version into its own cache, then import-probes every installed plugin against it in a child process, checks |
🧷 One Settings CheckThe only user-settings check with a known upgrade casualty: when a built-in agent preset is renamed ( |
~/.dsh/profiles/*
├─ installed package + provenance
│ registry artifact | link: working tree | file: snapshot
├─ declared
│ package.json + cordis.patch.yml
├─ static
│ bounded source scan + file:line evidence
├─ runtime (when loaded inside DSH)
│ tools + providers + routes + profile-scoped attribution
├─ versions
│ local cross-profile drift + opt-in registry check
└─ snapshot
additions + removals + version/profile/capability/claim changes
The CLI and the settings page consume the same scan core. The default path is offline. Only harbor scan --check-updates, harbor preflight, or the panel's Check for updates / Upgrade preflight actions contact a registry.
harbor preflight --list # dist-tags, recent versions, locally cached host trees
harbor preflight --dsh next # or a concrete version: --dsh 0.1.5-rc.2
harbor preflight --dsh 0.1.5-rc.2 --json
What runs, in order:
@deepseek-ai/dsh@<version> is installed into <state dir>/hosts/<version> with npm install -g --prefix. A completed install is reused; the global npm prefix and your profiles are never written.node child. A module.register resolve hook rewrites @deepseek-ai/* imports to the target tree, so the plugin links against the version under evaluation while its own dependencies keep resolving from its real install. Missing packages and removed exports fail at link time and are reported verbatim — the DSH loader is fail-loud, so one such plugin blocks the whole profile.dsh.client.inject / external ids are checked against the packages in the target that declare a web client module (DSH ≥ 0.1.5 skips unknown ids silently, so this never errors on its own). Host peer ranges are matched with npm's prerelease rule.agent-presets.default from settings.yaml is checked against the target's built-in presets.Verdicts are per plugin (blocks boot / loads / unresolvable / not probed) and per profile; peer-range and dead-inject findings are advisories and never change a verdict. Unresolvable means the plugin's own dependency could not be found — a packaging problem, not a host problem. Exit code 3 means at least one profile would not boot. Node ≥ 20.6 is required for the resolve hook.
Outside a profile — in CI, or for a package you have not installed — name the subjects explicitly:
harbor preflight --dsh next --plugin . # this repository (build it first)
harbor preflight --dsh next --pack @scope/some-plugin@1.2.3 # fetched from the registry, deps installed with scripts disabled
harbor host-diff --from 0.1.1-rc.2 --to 0.1.5-rc.1
Installs both versions into the cache and reports what a plugin could have depended on that moved: packages added/removed, web client modules added/removed, built-in presets, and — by importing each official package's entry in a child — every export name added or removed per package. This is the machine-readable changelog the release notes do not carry; the settingsNamespace removal that broke plugins on 0.1.5 shows up here as an export removal in @deepseek-ai/dsh-settings. Exit code 3 when anything was removed.
Plugin authors can run the same preflight on every pull request and every night against the next dist-tag:
- uses: actions/checkout@v4
- run: pnpm install --frozen-lockfile && pnpm run build # the built server entry is what gets probed
- uses: ZSeven-W/dsh-harbor@v0.1.0-rc.3
with:
dsh: next # version or dist-tag; default latest
The job fails with exit code 3 when the plugin would block boot, warns on stale declarations (fail-on-advisories: true turns those into failures), writes a job summary, and uploads the JSON report. The target host tree is cached per DSH version.
This repository also runs two scheduled workflows: an hourly watch on @deepseek-ai/dsh dist-tags that commits a host-diff for every tag move, and a nightly board that import-probes every npm package declaring dsh.bundle or dsh.client (about 4,500 at the time of writing) against the current next, incrementally — only plugins whose latest version changed are re-probed, and a full run happens when a DSH dist-tag moves. Results are published as a static page and a JSON index under board/. Probing executes each package's module top level in a disposable CI runner; that scan never runs on a user's machine, where preflight only touches plugins the user installed.
Expand any capability pill to inspect its tier, detail, and source evidence — here the Web route registration resolves to src/hub/index.mjs:212.
| Tier | What Harbor actually knows |
|---|---|
declared |
A manifest or filesystem fact, such as client injection or an on-disk realm copy. |
runtime |
A registry entry observed in the active DSH host. |
static |
A source behavior matched with inspectable file:line evidence. |
heuristic |
A pattern-based inference that deserves human review. |
Harbor reports facts, not a risk score. Spawning a subprocess may be the entire purpose of a plugin; the useful question is whether that capability is visible, declared, attributable, and expected.
DSH is a separate package. Install the tested host version if you do not already have it:
npm install -g @deepseek-ai/dsh@latest
For local development, install the current checkout into a Web profile and restart DSH once:
dsh plugin --profile web add link:/path/to/dsh-harbor
dsh web
For a registry install, use the prerelease next tag:
dsh plugin --profile web add @zseven-w/dsh-harbor@next
dsh web
Open Settings → DSH Harbor. The panel mounts only in profiles with a Web server; the CLI remains usable in headless and CI environments.
curl http://127.0.0.1:3080/_dsh/dsh-harbor/ping
pnpm --dir ~/.dsh/profiles/web exec harbor --version
A healthy ping reports four mounted Harbor routes. The package executable is profile-scoped: installing into web does not place harbor on your global shell PATH.
harbor scan
harbor scan --evidence
harbor scan --json --no-snapshot
harbor scan --json --check-updates
harbor manifest ./my-plugin
harbor preflight --dsh next
Invocation choices:
# installed in the web profile
pnpm --dir ~/.dsh/profiles/web exec harbor scan
# source checkout
node /path/to/dsh-harbor/src/cli.mjs scan
# one-off registry run after publication
pnpm dlx @zseven-w/dsh-harbor@next scan
--help and --version are side-effect free. Human-readable output strips terminal control sequences from untrusted package metadata; JSON preserves the original machine data. --no-snapshot prevents baseline writes.
| Surface | Capability ids |
|---|---|
| UI and host routes | client-injection, web-routes |
| Agent and model surface | tool-registration, llm-adapter, global-hook, mcp-server |
| Machine and data access | subprocess, network-egress, env-read, credential-handling, foreign-config |
| Module-realm integrity | realm-risk, realm-copy |
The full, stable definitions and declaration rules live in SPEC.md and SPEC.zh.md. Authors can draft the capabilities member to merge into an existing dsh object:
harbor manifest /path/to/my-plugin
Always review the draft. Detection is deliberately conservative and pattern based; dynamic calls can be missed, and examples or dead code can look live.
link: working trees and file: snapshots stay visible but do not define the registry baseline.behind, current, ahead, local, or unknown.~/.config/dsh-harbor/ and track profile membership as well as artifact identity, so profile swaps and upgrades cannot disappear behind deduplication.pnpm install
pnpm run typecheck
pnpm test
pnpm run build:client
npm run smoke:pack
The test runner is compatible with Node 20 and Windows. CI covers Node 20/24 on Ubuntu and Windows. smoke:pack packs the real payload, installs it with plain npm in an empty directory, imports the public entry, runs the installed CLI, and checks required files and modes.
MIT — Copyright (c) 2026 ZSeven-W
CLASSIFICATION EVIDENCE
系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。当前命中: audit、static-analysis。