Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@

## Unreleased

### Added
- Added native DSH threat-feed subscription management, advisory self-check discovery, and queued delivery of cron notifications to active DSH sessions.

### Fixed
- Improved DSH subscription cleanup and artifact discovery, and made system cron status failures explicit.

## [1.1.29] - 2026-08-26

### 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.
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ printf '{"tool_name":"Bash","tool_input":{"command":"curl https://example.com/in
agentguard connect

# API-key auth is also supported when you explicitly want that mode.
AGENTGUARD_API_KEY=ag_live_xxxxx agentguard connect --url https://agentguard.gopluslabs.io
AGENTGUARD_API_KEY=ag_live_xxxxx agentguard connect --url https://www.agentguard.one

# Optional: subscribe to AgentGuard's threat-intelligence feed. Pulls newly
# published advisories from Cloud and asks you to review them.
Expand Down Expand Up @@ -159,6 +159,7 @@ dsh plugin --profile web add --allow-build=@goplus/agentguard @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.
The native `agentguard_dsh_subscribe` tool binds system-cron threat-feed polling to the current DSH agent. `agentguard_dsh_subscription_status` reports bounded cron and queue metadata without notice contents, and exact-target `agentguard_dsh_unsubscribe` removes cron, matching queued notices, then saved state in retry-safe order. Notification-worthy pulls are durably queued across DSH downtime and delivered as a safe ordinary follow-up only to that exact live agent; delivery never automatically executes scans or remediation. Scheduled self-checks also discover DSH user/project skills, immediate profile manifests, declared direct dependencies, and home/profile Cordis patches without recursively walking dependency trees. See the [DSH subscription and local testing guide](docs/dsh.md#subscribe-to-threat-intelligence-from-dsh).

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.

Expand Down
2 changes: 1 addition & 1 deletion docs/cloud-connect.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ API-key auth is also supported:

```bash
AGENTGUARD_API_KEY=ag_live_xxxxx \
agentguard connect --url https://agentguard.gopluslabs.io
agentguard connect --url https://www.agentguard.one
```

With API-key auth, `connect` stores the API key locally, fetches `/api/v1/policies/effective`, and caches the policy. With Agent JWT auth, `connect` stores the local agent credential instead of an API key. If Cloud is unavailable, AgentGuard keeps enforcing with cached policy or the bundled default policy.
Expand Down
2 changes: 1 addition & 1 deletion docs/cloud-native-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ This document summarizes the Cloud APIs that a local/native AgentGuard runtime s
Production base URL:

```text
https://agentguard.gopluslabs.io
https://www.agentguard.one
```

All protected runtime APIs require an AgentGuard API key:
Expand Down
111 changes: 109 additions & 2 deletions docs/dsh.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,116 @@ For local development, link the checkout instead:
dsh plugin --profile web add link:/absolute/path/to/agentguard
```

The profile then exposes `agentguard_dsh_scan`, which accepts a local directory or HTTPS GitHub repository URL, an optional GitHub `ref`, and a Markdown or JSON format. It also exposes `agentguard_dsh_scan_batch` for sequentially scanning up to 10 targets, `agentguard_dsh_compare` for comparing an approved version with a candidate, and `agentguard_dsh_runtime_summary` for input-redacted runtime audit aggregates. For example, ask DSH: “Use AgentGuard to compare tags `v1.2.3` and `v1.3.0` of `https://github.com/owner/plugin` before I update.”
The profile then exposes `agentguard_dsh_scan`, which accepts a local directory or HTTPS GitHub repository URL, an optional GitHub `ref`, and a Markdown or JSON format. It also exposes `agentguard_dsh_scan_batch` for sequentially scanning up to 10 targets, `agentguard_dsh_compare` for comparing an approved version with a candidate, `agentguard_dsh_runtime_summary` for input-redacted runtime audit aggregates, and `agentguard_dsh_subscribe`, `agentguard_dsh_subscription_status`, and `agentguard_dsh_unsubscribe` for managing a threat-feed subscription bound to the current DSH agent. For example, ask DSH: “Use AgentGuard to compare tags `v1.2.3` and `v1.3.0` of `https://github.com/owner/plugin` before I update.”

The three static AgentGuard DSH tools preserve the Phase 1 boundary: they do not install or execute the target plugin. The fourth tool only summarizes local runtime audit events and never returns raw tool input. The installed bundle enables `protect` by default; the [DSH runtime guard](dsh-runtime.md) documents audit-only `observe` mode and the available protection settings.

### Subscribe to threat intelligence from DSH

The native `agentguard_dsh_subscribe` tool binds a threat-feed subscription to
the exact DSH agent that invokes it. It subscribes the currently connected
AgentGuard Cloud identity, installs a system crontab poller, and stores the
binding in `~/.agentguard/dsh-threat-feed-subscription.json`.

Before invoking the tool, initialize the DSH integration and connect Cloud:

```bash
agentguard init --agent dsh
agentguard connect
```

Then ask DSH, for example:

```text
Use AgentGuard to subscribe this DSH session to the threat feed every 15 minutes without automatic self-checks.
```

The tool accepts these optional arguments:

- `cron`: a five-field cron expression; defaults to `0 * * * *`;
- `selfCheck`: defaults to `false`; set it to `true` only when scheduled local self-checks are intended;
- `force`: replace a subscription bound to another DSH agent or schedule.

Polling continues while DSH is stopped because the job is owned by system
crontab. The cron runner must be able to find the `agentguard` executable on
its saved `PATH`, and writes output to `~/.agentguard/feed-cron.log`.

When a pull finds new advisories, or a `selfCheck: true` pull finds local
matches, the cron process first writes a bounded notice under
`~/.agentguard/dsh-feed-notifications/`. The DSH plugin delivers queued notices
to the exact bound agent as an ordinary follow-up when it is live and idle.
Notices remain queued while DSH or that agent is unavailable, and are removed
only after DSH accepts the follow-up. Threat-feed data is framed as untrusted
data: delivery does not automatically run a scan, command, or remediation.
Delivery is at-least-once: a process crash after DSH accepts a follow-up but
before its queue file is removed can produce one duplicate carrying the same
notice id after restart.

Use `agentguard_dsh_subscription_status` with no arguments to inspect the
subscription safely. It reports whether state is saved, the subscription and
target agent ids, whether the caller is that target, the configured cron and
self-check mode, whether the exact system cron block is installed, the queued
notice count, and the latest enqueue time. It never returns notification
bodies, matched local paths, credentials, or Cloud remediation text.

Use `agentguard_dsh_unsubscribe` with no arguments from the exact subscribed
DSH session to remove the subscription. Cleanup is ordered transactionally:
the managed system cron is removed or confirmed absent first, then only queue
files for that subscription and agent are deleted, and subscription state is
deleted last. A cron read/removal error or queue cleanup error leaves the saved
state in place so the operation can be retried. Calling it when no subscription
is saved is safe and has no effect.

Scheduled self-check discovery includes `$DSH_HOME/skills` (default
`~/.dsh/skills`), `<current-project>/.dsh/skills`, every immediate
`$DSH_HOME/profiles/*/package.json`, each profile's declared direct and optional
dependencies under `node_modules`, and existing `cordis.patch.yml` or
`cordis.patch.yaml` files in the DSH home and profile directories. Dependency
discovery is deliberately non-recursive: undeclared transitive packages and
dependency names that could escape `node_modules` are excluded. Advisory-level
`inspectPaths` and explicitly supplied self-check roots remain authoritative.

For local checkout testing, install the CLI from a packed tarball but keep the
DSH plugin linked to the checkout. This distinction matters on macOS: a global
`npm link` can leave the cron executable resolving into Desktop, Documents, or
Downloads, where unattended cron may receive `EPERM`. Packing copies the CLI
under the active Node installation instead:

```bash
cd /absolute/path/to/agentguard
npm run build

PACK_DIR="$(mktemp -d)"
npm pack --pack-destination "$PACK_DIR"
npm install -g "$PACK_DIR"/goplus-agentguard-*.tgz

dsh plugin --profile web add link:/absolute/path/to/agentguard
```

Verify both installation paths without requiring `realpath` or `rg`:

```bash
CLI_PATH="$(command -v agentguard)"
node -e 'console.log(require("node:fs").realpathSync(process.argv[1]))' "$CLI_PATH"
grep -F '"@goplus/agentguard"' "$HOME/.dsh/profiles/web/package.json"
```

The first command must resolve under the active Node/npm installation, not the
checkout in a macOS protected user folder. Restart DSH after the plugin add.
Invoke `agentguard_dsh_subscribe` from the DSH conversation, then trigger one
poll without waiting for cron:

```bash
"$HOME/.agentguard/scripts/agentguard-threat-feed.sh"
tail -n 50 "$HOME/.agentguard/feed-cron.log"
find "$HOME/.agentguard/dsh-feed-notifications" -maxdepth 1 -type f -name '*.json' -print
```

An immediate DSH follow-up requires an unseen advisory (or a new self-check
match) and the exact subscribed agent to be live. A no-new-data pull correctly
creates no notice. If DSH was stopped, resume the bound session so activation
can consume its queued notices.

### Operate the DSH installation

DSH forwards plugin lifecycle commands to the profile package manager. Keep the profile name explicit so an update or removal cannot affect a different profile.
Expand All @@ -55,10 +161,11 @@ Restart the DSH process after an add, update, or remove operation. For a local `
Verification checklist:

1. `dsh web --dump-config` contains `id: agentguard-dsh-plugin` and the `@goplus/agentguard/dist/dsh/plugin.js` entry.
2. DSH exposes the `agentguard_dsh_scan`, `agentguard_dsh_scan_batch`, `agentguard_dsh_compare`, and `agentguard_dsh_runtime_summary` tools.
2. DSH exposes the `agentguard_dsh_scan`, `agentguard_dsh_scan_batch`, `agentguard_dsh_compare`, `agentguard_dsh_runtime_summary`, `agentguard_dsh_subscribe`, `agentguard_dsh_subscription_status`, and `agentguard_dsh_unsubscribe` tools.
3. A JSON scan contains `scanner.version`, `scanner.phase`, and `scanner.rulesBaseline`. Keep these fields with a saved report so later rescans can be compared to the same implementation.
4. `~/.agentguard/audit.jsonl` receives DSH events with `agentHost: "dsh"`. The default composition records pre-execute events with `runtimeMode: "protect"` and `enforcementApplied: true`; an explicit audit-only composition records `runtimeMode: "observe"` and does not apply pre-execute enforcement.
5. After removal and restart, the AgentGuard composition row, tools, and runtime listener are absent.
6. A notification-worthy subscribed cron pull reaches only the exact bound live agent; unsuccessful delivery leaves a private JSON notice in `~/.agentguard/dsh-feed-notifications/`.

If `http://127.0.0.1:3080/` returns `ERR_CONNECTION_REFUSED`, the DSH web process is not listening; it is not evidence of a scanner failure. Start or restart DSH and inspect its terminal output. If the tool is missing while DSH is running, check the explicit profile with `--dump-config`, then confirm the package appears in that profile's dependencies.

Expand Down
Loading
Loading