Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
26a9007
feat: add DSH plugin security scanner
EchoOfZion Aug 15, 2026
5413eca
fix: harden DSH scan inputs and reporting
EchoOfZion Aug 15, 2026
9efa5a1
fix: bound Cordis parsing and clarify scan metadata
EchoOfZion Aug 15, 2026
a15e4c6
fix: validate Cordis rows and refine theme mismatch
EchoOfZion Aug 15, 2026
ee9e156
fix: report manifest errors and structure Cordis evidence
EchoOfZion Aug 15, 2026
4243ed7
feat: expose AgentGuard scanner as DSH tool
EchoOfZion Aug 15, 2026
2bc1d2b
feat: calibrate DSH scan review scope
EchoOfZion Aug 15, 2026
c1443e9
feat: refine DSH runtime relevance
EchoOfZion Aug 15, 2026
ea94857
fix: localize DSH auto-update evidence
EchoOfZion Aug 15, 2026
83db977
feat: separate dynamic execution findings
EchoOfZion Aug 15, 2026
a6e1edc
test: freeze DSH phase one baseline
EchoOfZion Aug 15, 2026
840a5f1
feat: add DSH scan provenance and lifecycle checks
EchoOfZion Aug 15, 2026
55224ee
test: verify packaged DSH release lifecycle
EchoOfZion Aug 15, 2026
367227c
fix: harden DSH scanner trust boundaries
EchoOfZion Aug 16, 2026
c1231fc
chore: mark DSH security baseline rc2
EchoOfZion Aug 16, 2026
8318c68
feat: support pinned GitHub refs in DSH scans
EchoOfZion Aug 16, 2026
6589ef2
feat: add bounded DSH batch scanning
EchoOfZion Aug 16, 2026
b4de1e5
feat: compare DSH plugin scan reports
EchoOfZion Aug 16, 2026
d737a65
feat: observe DSH runtime tool calls
EchoOfZion Aug 16, 2026
e42447d
test: exercise DSH runtime observer pipeline
EchoOfZion Aug 16, 2026
42a1e81
feat: summarize DSH runtime observations
EchoOfZion Aug 16, 2026
7871a8f
feat: preserve DSH runtime request context
EchoOfZion Aug 16, 2026
6da5540
feat: detect remote Git package execution
EchoOfZion Aug 16, 2026
5efbe42
feat: observe DSH network tool responses
EchoOfZion Aug 16, 2026
0c67276
feat: plan DSH runtime enforcement
EchoOfZion Aug 17, 2026
67ab5ee
feat: adapt DSH native approval decisions
EchoOfZion Aug 17, 2026
5dcf929
test: verify DSH native approval lifecycle
EchoOfZion Aug 17, 2026
5dc5845
test: verify DSH post-execute containment
EchoOfZion Aug 17, 2026
30ddb03
feat: enforce DSH pre-execute runtime policy
EchoOfZion Aug 17, 2026
43b1855
docs: add DSH acceptance test guide
EchoOfZion Aug 17, 2026
96814b7
docs: clarify DSH native approval UAT
EchoOfZion Aug 17, 2026
d01c846
test: lock DSH remote execution approval path
EchoOfZion Aug 18, 2026
efd680c
feat: add trusted DSH tool owner attribution
EchoOfZion Aug 18, 2026
9005e9b
feat: enforce monotonic DSH owner policies
EchoOfZion Aug 18, 2026
63e90a2
feat: contain blocked DSH network responses
EchoOfZion Aug 18, 2026
4000670
docs: finalize DSH complete candidate
EchoOfZion Aug 18, 2026
2337e26
fix: fail closed on incomplete DSH scans
EchoOfZion Aug 18, 2026
bf64fdd
chore: freeze DSH coverage baseline rc3
EchoOfZion Aug 18, 2026
557f73a
docs: add DSH phase1 rc3 acceptance plan
EchoOfZion Aug 18, 2026
2ded0ae
docs: record DSH phase1 rc3 acceptance
EchoOfZion Aug 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ coverage/
.idea/
.vscode/
tmp/
.dsh-runtime/
.dsh-home/
.dsh-test-reports/
.pnpm-store/
.npmrc
skills/agentguard/scripts/data/
skills/agentguard/scripts/package-lock.json
2 changes: 2 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Compiled tests are useful in the checkout but are not runtime package assets.
dist/tests/
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,20 @@

## Unreleased

### Added
- Added the read-only DSH installation scanner, native DSH tool plugin, dual full-repository/runtime-surface risk views, review priority, generated-code context, evidence aggregation, and explainable Markdown/HTML/JSON reports.
- Added a pinned real-world DSH regression benchmark with deterministic snapshots and manual source-review records for representative LOW-through-CRITICAL artifacts.
- Added structured DSH scan coverage accounting and explicit configured runtime-mode visibility in startup logs and runtime summaries.

### Changed
- MCPB release builds now publish the bundle as `agentguard.mcpb` so Anthropic's
directory auto-pickup keeps matching the asset across version tags.
- Relaxed OpenClaw file read/write handling so ordinary paths are allowed by default, while sensitive paths still require approval and critical system mutations still block.
- Changed `curl/wget | bash/sh` handling to require approval by default and block only when hard indicators or multiple suspicious signals are present.

### Fixed
- DSH scans now fail closed with `DSH_SCAN_INCOMPLETE` and `expert-review-required` when matching files are omitted by the file-count limit, exceed the per-file byte limit, or cannot be read, preventing incomplete scans from returning `safe-to-try`.

## [1.1.28] - 2026-06-16

### Added
Expand Down
56 changes: 54 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,58 @@ agentguard init --agent hermes # native Hermes plugin (add --shell-hooks
agentguard init --agent qclaw
```

### Audit DeepSeek Harness plugins before installation

The Phase 1 DSH scanner understands current `dsh.bundle.patch`, `dsh.profile.bundles`, `dsh.client`, and Cordis configuration structures in addition to JavaScript and TypeScript capabilities.

```bash
# Human-readable report
agentguard dsh-scan ./path/to/dsh-plugin

# Machine-readable report from a GitHub repository
agentguard dsh-scan https://github.com/owner/dsh-plugin --format json

# Reproducible report for a release tag, branch, or exact commit
agentguard dsh-scan https://github.com/owner/dsh-plugin --ref v1.2.3 --format json

# Self-contained shareable report page
agentguard dsh-scan ./path/to/dsh-plugin --format html --output report.html
```

Reports include DSH identification confidence, plugin kind, explainable risk level, permission profile, impact layers, source evidence, structured file-coverage accounting, and an installation recommendation. File-count truncation, oversized matching files, or ordinary read failures produce `DSH_SCAN_INCOMPLETE` and can never return `safe-to-try`. See [AgentGuard for DSH](docs/dsh.md) for the risk model and current limitations.

Install AgentGuard as a native DSH tool plugin, then restart the profile:

```bash
dsh plugin --profile web add @goplus/agentguard
```

DSH will expose the read-only `agentguard_dsh_scan` tool for scanning local plugin directories and HTTPS GitHub repositories before installation.
It also exposes `agentguard_dsh_scan_batch` for a sequential review queue of up to 10 targets per DSH tool call. The CLI accepts larger JSON manifests of up to 25 targets with `agentguard dsh-scan-batch`.
Use `agentguard_dsh_compare` or the `agentguard dsh-compare` CLI command to identify new permissions and runtime risks before updating an approved plugin version.

Update or remove it from the same profile with `dsh plugin --profile web update @goplus/agentguard` or `dsh plugin --profile web remove @goplus/agentguard`. The [DSH operations and report guide](docs/dsh.md#operate-the-dsh-installation) includes verification and troubleshooting steps.

> **DSH runtime guard:** the packaged composition uses non-disruptive `observe` mode. Startup logs and the input-redacted `agentguard_dsh_runtime_summary` tool explicitly show the current configured mode and whether pre-execute enforcement is active. An explicit `runtime.mode: protect` applies AgentGuard's shared allow/warn/require-approval/block policy before DSH dispatches a tool, using DSH's native one-shot approval service and monotonic composition with other policies. Optional `runtime.postResponseMode: block-malicious` suppresses only block-class malicious network results; approval-class post results remain audit-only because DSH has no resumable post-result approval protocol. Exact operator-configured `runtime.attribution.toolOwners` bindings add source ownership without guessing, and `runtime.ownerPolicies` can impose per-owner minimum decisions without weakening shared security policy. Unmapped tools remain `unknown` until DSH exposes a reliable native owner field. See the [DSH runtime guide](docs/dsh-runtime.md).

The complete candidate scope, activation override, acceptance gates, and intentional boundaries are collected in [AgentGuard for DSH complete candidate](docs/dsh-complete-candidate.md).

The enforcing adapter maps approval decisions to DSH's native `ask` contract, emits bounded evidence-free reasons, preserves stronger downstream policies, fails closed on unexpected evaluator errors by default, and is registered only when `protect` is explicitly selected.

Native contract gates cover the full pre-execute approval outcome matrix, concurrent and nested calls, failures, unload, and post-execute result containment. Block-class malicious responses can be suppressed explicitly; approval-class post results remain audit-only because DSH currently exposes no native post-approval resume primitive. The complete candidate passed all 11 guided DSH UAT cases, including native approval/rejection, pre-execute blocking, response containment, redaction, and service stability.

The shared runtime detector treats unpinned Git sources executed through `npx`, `npm exec`, `pnpm dlx`, `yarn dlx`, or `bunx` as high-risk remote code execution. Full commit pins reduce this to a warning rather than making remote code implicitly trusted.

Phase 1.1 keeps the conservative full-repository risk while adding a separate runtime-surface risk, evidence source categories, likely-generated markers, and a human-review priority. Tests, examples, docs, and data findings remain visible instead of being silently discarded.

Phase 1.2 treats active `SKILL.md` and agent-instruction files as runtime-relevant, keeps executable source runtime-relevant even under `data/` or `assets/`, distinguishes computed local module loading from remote code execution, and requires concrete credential APIs before reporting keychain access.

Phase 1.3 localizes compound `AUTO_UPDATE` evidence around the matched update behavior. Large bundled or third-party JavaScript files no longer become critical merely because unrelated network and execution tokens appear elsewhere in the same file; executable files under `assets/` remain visible to prevent path-based evasion.

Phase 1.4 separates eval-like `DYNAMIC_CODE_EXECUTION` from encoded or packed-code `OBFUSCATION`. DSH reports aggregate repeated matches by rule and file, retain the total occurrence count, and keep generated runtime bundles security-relevant instead of treating source maps as proof of safety.

The Phase 1 release candidate freezes those rule semantics and adds an exact-commit real-world regression gate. See [the RC acceptance plan](docs/dsh-phase1-rc.md) and [benchmark policy](benchmarks/dsh/README.md).

<details>
<summary><b>Full install with auto-guard hooks (Claude Code)</b></summary>

Expand Down Expand Up @@ -316,10 +368,10 @@ The report is a self-contained HTML file that opens automatically in your browse

| Category | Rules | Severity |
|----------|-------|----------|
| **Execution** | SHELL_EXEC, AUTO_UPDATE, REMOTE_LOADER | HIGH-CRITICAL |
| **Execution** | SHELL_EXEC, DYNAMIC_MODULE_LOADING, AUTO_UPDATE, REMOTE_LOADER | HIGH-CRITICAL |
| **Secrets** | READ_ENV_SECRETS, READ_SSH_KEYS, READ_KEYCHAIN, PRIVATE_KEY_PATTERN, MNEMONIC_PATTERN | MEDIUM-CRITICAL |
| **Exfiltration** | NET_EXFIL_UNRESTRICTED, WEBHOOK_EXFIL | HIGH-CRITICAL |
| **Obfuscation** | OBFUSCATION, PROMPT_INJECTION | HIGH-CRITICAL |
| **Dynamic execution and obfuscation** | DYNAMIC_CODE_EXECUTION, OBFUSCATION, PROMPT_INJECTION | HIGH-CRITICAL |
| **Web3** | WALLET_DRAINING, UNLIMITED_APPROVAL, DANGEROUS_SELFDESTRUCT, HIDDEN_TRANSFER, PROXY_UPGRADE, FLASH_LOAN_RISK, REENTRANCY_PATTERN, SIGNATURE_REPLAY | MEDIUM-CRITICAL |
| **Trojan & Social Engineering** | TROJAN_DISTRIBUTION, SUSPICIOUS_PASTE_URL, SUSPICIOUS_IP, SOCIAL_ENGINEERING | MEDIUM-CRITICAL |

Expand Down
54 changes: 54 additions & 0 deletions benchmarks/dsh/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# DSH real-world regression benchmark

This benchmark complements the synthetic fixtures under `src/tests/fixtures/dsh-eval/`. It pins reviewed public repositories to exact commits and stores a deterministic subset of each DSH report. It is an engineering regression gate, not a malware leaderboard or a claim that any repository is malicious.

## Baseline

`real-world.manifest.json` is the source list. Every entry must use an HTTPS GitHub repository, a full 40-character commit, and an optional safe repository-relative subpath. `real-world.snapshot.json` records artifact identity, risk outcomes, sorted tags, and aggregated finding counts. Volatile fields such as scan time and duration are intentionally excluded.

The Phase 1 RC baseline contains:

- A UI bundle with an oversized generated runtime asset that deliberately exercises incomplete-coverage fail-closed behavior (`dsh-deep-whale`).
- A medium runtime-risk skill provider (`superdesign-skill`).
- A generated bundle with expected host command execution (`dsh-open-in-vscode`).
- A provider-routing plugin with a user-triggered self-update path (`dsh-vision-router`).
- A large mixed-purpose repository with credential and webhook evidence (`MisakaNet`).

## Run

Build first, then compare the current scanner with the committed snapshot:

```bash
npm run build
npm run benchmark:dsh
```

Run one pinned case while investigating a change:

```bash
node scripts/dsh-benchmark.mjs --case dsh-vision-router
```

The command exits non-zero and prints field-level differences when a result changes. It fetches only the exact pinned commits and checks the resulting HEAD before scanning.

## Updating the baseline

Do not update the snapshot merely to make a failure disappear. First record:

1. The scanner change that caused the difference.
2. Whether the difference fixes a false positive, closes a false negative, or is an intentional model change.
3. Human review of any new or removed HIGH/CRITICAL runtime tag.
4. The exact upstream commit when changing a sample revision.

After review:

```bash
npm run benchmark:dsh:update
npm run benchmark:dsh
```

Repository owners can change or delete public commits. Such an acquisition failure is a benchmark infrastructure failure, not permission to silently follow the default branch.

## Privacy and evidence handling

Snapshots contain rule names and counts, not matched secret values or full source snippets. Human review notes must not reproduce tokens, webhook identifiers, private keys, or other live-looking credentials.
43 changes: 43 additions & 0 deletions benchmarks/dsh/manual-reviews.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Phase 1 RC manual source reviews

These reviews cover the exact commits in `real-world.manifest.json`. They validate what selected static findings mean in source; they do not certify the plugins as safe. Sensitive values are deliberately omitted.

## dsh-vision-router

- Artifact: `ysr666/dsh-vision-router@86268695b1fb537794b33d0fb5267ce64ddbb8ce`
- Static posture: CRITICAL repository / CRITICAL runtime / URGENT review.
- Confirmed behavior: `lib/update-check.js` contacts the configured npm registry for version metadata. `lib/self-update.js` can invoke the already-running DSH CLI to update `dsh-vision-router`; `index.js` exposes that operation through a settings-card endpoint.
- Trigger: startup performs a read-only version check. Mutation requires an update to exist and a POST carrying a process-local token returned by the same-origin update-check flow.
- Controls observed: profile-name validation, ownership verification of the active `@deepseek-ai/dsh` CLI entry, `execFile` argument arrays, `shell: false`, same-origin request checks, token rotation after success, and single-flight update execution.
- Residual risk: the update installs the registry's latest package rather than a reviewed immutable artifact. The plugin also takes over provider routing and exposes broad vision/file capabilities. A version pin alone does not neutralize a user-triggered self-update.
- Evidence nuance: the reported `DYNAMIC_CODE_EXECUTION` representative line is an `exec` alias and overlaps shell execution. The same nearby feature also creates a Worker with `eval: true`, so dynamic source execution exists, but future evidence should point to the precise construct.
- Verdict: confirmed expected-but-sensitive self-update and provider-routing capabilities. Keep CRITICAL/URGENT; use only in an isolated profile with update behavior understood.

## MisakaNet

- Artifact: `Ikalus1988/MisakaNet@90665bad188073cf995fd3ca4428273653f83b81`
- Static posture: CRITICAL repository / CRITICAL runtime / URGENT review.
- Confirmed behavior: notifier implementations POST structured operational data to caller-configured Discord, Slack, and Feishu webhook URLs. Token management reads the OS keyring and falls back to an owner-only plaintext file with an explicit warning. Numerous maintenance and integration paths execute subprocesses.
- Repository data: lesson material contains a live-looking Feishu webhook identifier and a shared-secret-like value from a historical configuration example. The repository security policy also documents an intentionally public, restricted registration PAT. Values are not repeated here; their revocation and rotation cannot be proven by static review.
- Controls observed: notifier URLs are configuration inputs rather than a hardcoded exfiltration destination; network calls use timeouts; keyring is preferred; plaintext fallback attempts mode `0600` and warns.
- Residual risk: this is a very large mixed-purpose repository, not a narrowly scoped DSH plugin artifact. Installing or trusting the repository as one unit exposes substantially more code and data than the Cordis integration alone. Public credential-like history should be removed or demonstrably revoked.
- Evidence nuance: the CRITICAL `WEBHOOK_EXFIL` representative match is a placeholder Discord URL in a module docstring, while the module's actual generic webhook POST capability is real. `hub/orchestrator/skill_indexer.py` calls a machine-learning model's `.eval()` mode; that is not Python's `eval()` and is a known `DYNAMIC_CODE_EXECUTION` false positive.
- Verdict: expert review remains appropriate because of real webhook, keyring, subprocess, and sensitive-history exposure. Individual critical evidence lines include false positives and must not be treated as proof of malicious intent.

## dsh-open-in-vscode

- Artifact: `omdsh-dev/dsh-open-in-vscode@149f21aed3d05d2b392206394c4a023e35d694c7`
- Static posture: HIGH repository / HIGH runtime / ELEVATED review.
- Confirmed behavior: `src/runtime.ts` launches a locally configured editor command with an argument array and a required absolute workspace path. The child is detached and uses no shell.
- Controls observed: strict remote invocation schema, absolute-path rejection, `spawn(executable, args)` rather than shell interpolation, and default command `code`.
- Residual risk: a local profile administrator may configure an arbitrary executable and arguments. That is expected host capability, but the plugin should not be installed where browser-accessible DSH endpoints are exposed to untrusted users.
- Evidence nuance: the generated `new Function` finding originates from bundled Schemastery dependency code, not first-party plugin source. The two large OBFUSCATION groups are generated Unicode locale data. Source maps make both origins reviewable but do not make the runtime bundle safe by definition.
- Verdict: HIGH is justified by intentional process launch. Dynamic-execution and obfuscation evidence are dependency/build context rather than suspicious first-party behavior.

## superdesign-skill control

- Artifact: `superdesigndev/superdesign-skill@dc60b43625426bdd1e88fe494739fd5ea27daedd`
- Static posture: HIGH repository / MEDIUM runtime / ELEVATED review.
- Confirmed behavior: `dsh/index.js` reads its packaged `SKILL.md` and registers a skill provider. It performs no network request, file write, subprocess launch, or lifecycle installation.
- Evidence nuance: the only SHELL_EXEC finding is an inert path example in skill reference documentation and is excluded from runtime surface.
- Verdict: the MEDIUM runtime result accurately reflects packaged file reading. This is the clean control for the RC benchmark.
52 changes: 52 additions & 0 deletions benchmarks/dsh/observed-candidates.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Observed DSH benchmark candidates

This inventory preserves plugin names mentioned in the exploratory batch scans that led to Phase 1. It is not a benchmark snapshot: most entries were scanned from an unrecorded default-branch state, so their old result must not be used as a regression expectation.

The current conversation record contains 39 unique identifiable names, not enough metadata to substantiate the informal “50+” count. Five have been resolved to an exact repository and commit in `real-world.manifest.json`; the remainder must be pinned before inclusion.

## Pinned in phase1-rc1

- `dsh-deep-whale`
- `superdesign-skill`
- `dsh-open-in-vscode`
- `dsh-vision-router`
- `MisakaNet`

## Awaiting repository and commit verification

- `Aegis`
- `argo`
- `distill`
- `DSH-better-sidebar`
- `dsh-ads`
- `dsh-agent-teams`
- `dsh-annotation`
- `dsh-at-file`
- `dsh-browser`
- `dsh-chat-import`
- `dsh-desktop-pet`
- `dsh-genui`
- `dsh-market`
- `dsh-message-edit`
- `dsh-mnemon`
- `dsh-notification`
- `dsh-openpencil`
- `dsh-pet`
- `dsh-tianshu-tui`
- `dsh-TUI`
- `dsh-turn-rewind`
- `dsh-vision-toolkit`
- `dsh-visualize`
- `dsh-web-ui`
- `dsh-workflow`
- `forkprobe`
- `hindsight`
- `mirage`
- `modlens`
- `modsearch`
- `notes`
- `oh-dsh`
- `treg`
- `whale-girl`

To promote an entry, resolve the canonical repository, record a full commit SHA and any scanned subpath, run an initial manual review, and update the snapshot through the documented review process.
34 changes: 34 additions & 0 deletions benchmarks/dsh/real-world.manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"schemaVersion": 1,
"baseline": "phase1-rc3",
"rulesFrozenAt": "2337e266cf78f82e8d07f5555f7cc760b6ddc830",
"snapshot": "real-world.snapshot.json",
"cases": [
{
"id": "dsh-deep-whale",
"repository": "https://github.com/Small-tailqwq/dsh-deep-whale",
"revision": "cdb4da4f9c708571c6303cc1053185c62c8b617b",
"subpath": "maid-atelier"
},
{
"id": "superdesign-skill",
"repository": "https://github.com/superdesigndev/superdesign-skill",
"revision": "dc60b43625426bdd1e88fe494739fd5ea27daedd"
},
{
"id": "dsh-open-in-vscode",
"repository": "https://github.com/omdsh-dev/dsh-open-in-vscode",
"revision": "149f21aed3d05d2b392206394c4a023e35d694c7"
},
{
"id": "dsh-vision-router",
"repository": "https://github.com/ysr666/dsh-vision-router",
"revision": "86268695b1fb537794b33d0fb5267ce64ddbb8ce"
},
{
"id": "misakanet",
"repository": "https://github.com/Ikalus1988/MisakaNet",
"revision": "90665bad188073cf995fd3ca4428273653f83b81"
}
]
}
Loading
Loading