Files
lxcong 8bc275a20b feat(skill): add OAuth-first setup, slim SKILL.md via progressive disclosure (#62)
## What

Two changes to the AgentKey skill, on top of one another:

### 1. Slim `SKILL.md` via progressive disclosure

The high-frequency Query path stays in `SKILL.md`; the rarely-executed
upgrade machinery moves to references that load only when needed.

- **`SKILL.md`: 317 → ~127 lines.** Step 0 collapses from ~165 lines of
inline version-check / upgrade / telemetry logic to a ~12-line preflight
stub.
- **New `references/maintenance.md`** — the full upgrade flow: beacon
protocol contract, 4-option upgrade prompt (With-Bash / No-Bash
branches), snooze + auto-upgrade persistence, `error_class` mapping, and
all `upgrade_decision` / `upgrade_result` telemetry. Loads only on a
version-mismatch signal.

### 2. OAuth-first Setup flow

Now that the hosted MCP server supports **native MCP OAuth**, the Setup
flow prefers OAuth and only falls back to an API key when needed:

- **`SKILL.md` Setup section** rewritten — **try OAuth first** (register
the remote URL `https://api.agentkey.app/v1/mcp` with *no key* and let
the client run its own browser OAuth), **API key as fallback**
(Console-minted key + `Authorization: Bearer`). Written
client-agnostically: no longer hard-codes the `@agentkey/cli
--auth-login` one-liner or singles out one agent.
- **`references/setup.md`** restructured into "OAuth registration"
(per-client examples) + "API-key fallback" sections.
- **`SECURITY.md`** posture aligned — dropped the stale `--auth-login`
references; MCP config is written by the client/agent on registration,
and the only remaining npm egress is the `npx skills update agentkey`
update command.

## Why

Per Anthropic's `skill-creator` guidance, the `SKILL.md` body is loaded
on **every** skill trigger. Previously ~53% of that body was
upgrade/telemetry plumbing that fires <1% of the time. Moving that
machinery behind a reference cuts ~60% of per-query context while
keeping the upgrade flow 100% intact.

The Setup rework lets OAuth-capable clients connect without minting or
pasting an API key — fewer steps, no long-lived secret to store — while
keeping the API-key path for clients that can't do MCP OAuth.

## Behavior

- **Slim part:** pure reorganization — frontmatter `description` (the
triggering mechanism) is byte-for-byte identical; protocol rules,
upgrade options, persistence files, and telemetry shapes are preserved
verbatim in `references/maintenance.md`.
- **Setup part:** new preferred OAuth path; the previous API-key
registration is preserved as the documented fallback.

## Verification

-  `verify-version-sync` logic: all versions consistent at `1.9.1`.
-  `bats tests/`: pass (update script untouched).
-  `npx skills add . --list`: skill discoverable, frontmatter parses.
-  No `--auth-login` references remain in `SKILL.md` /
`references/setup.md` / `SECURITY.md`.

## Note on release type

This branch now carries a `feat(skill):` commit (OAuth-first setup), so
the PR title has been retitled to `feat(skill):` — squash-merging will
cut a release via release-please.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 16:54:52 +08:00

79 lines
5.6 KiB
Markdown

# Security Policy
## Reporting a Vulnerability
**Please do not report security vulnerabilities through public GitHub issues.**
Instead, email `support@chainbase.com` with:
- A description of the issue
- Steps to reproduce
- Potential impact
- Any suggested mitigation
We will acknowledge your report within 72 hours and keep you informed of the fix timeline.
## Supported Versions
| Version | Supported |
|---------|-----------|
| 1.x | ✅ |
| < 1.0 | ❌ |
Pre-1.0 releases are no longer maintained. Please upgrade to the latest 1.x release.
## Disclosure
We follow coordinated disclosure. Once a fix is available, we publish a security advisory via GitHub Security Advisories and credit the reporter (with permission).
## Security Posture
### What this skill does on your machine
The skill ships one helper script that the agent invokes:
- **`skills/agentkey/scripts/check-update.sh`** — **notify-only**. At most every 60 minutes (12 hours once an upgrade is known), it calls `https://api.github.com/repos/chainbase-labs/agentkey/releases/latest`, compares the tag against a version constant embedded in the script itself (synced at release time by release-please via `extra-files`), and prints `UPGRADE_AVAILABLE <old> <new>` if they differ. The script does **no** filesystem traversal — there is no `dirname`/`..` path resolution, no read of `version.txt`, no dependency on `CLAUDE_PLUGIN_ROOT`. It also honors a snooze file (`~/.config/agentkey/update-snoozed`, escalating 24h/48h/7d backoff) and a disable file (`~/.config/agentkey/update-disabled`); both are read-only from this script's perspective. The script never runs `git`, never writes to anything except its TMPDIR cache, and never executes downloaded code.
When the agent sees `UPGRADE_AVAILABLE` it surfaces an `AskUserQuestion` prompt (Yes / Always / Not now / Never). The actual update — `npx skills update agentkey` — runs only after the user picks "Yes" or "Always", or if the user has previously opted into auto-upgrade via `AGENTKEY_AUTO_UPGRADE=1` or `~/.config/agentkey/auto-upgrade`. The agent invokes that command via its own Bash tool, not via this script.
The skill verifies MCP health by calling the MCP `list_tools` endpoint directly (see SKILL.md → "Status"); it does **not** read any agent config file or `AGENTKEY_API_KEY` value from disk.
### Files the skill reads or writes
| Path | Mode | Purpose |
|---|---|---|
| `${TMPDIR}/agentkey-update-check` | read/write | Cache for the update check |
| `~/.config/agentkey/auto-upgrade` | written by the agent on user's "Always keep me up to date" choice; read by Step 0 to skip the prompt | Persistent auto-upgrade opt-in |
| `~/.config/agentkey/update-snoozed` | written by the agent on user's "Not now" choice; read by `check-update.sh` to suppress reminders | Snooze state (`<version> <level> <epoch>`) |
| `~/.config/agentkey/update-disabled` | written by the agent on user's "Never ask again" choice; read by `check-update.sh` to exit silently | Permanent disable for update checks |
| `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) / `%APPDATA%/Claude/...` (Windows) | written by your MCP client / agent when you register the AgentKey server, **not** by the skill | MCP registration |
| `~/.claude.json` | written by your MCP client / agent when you register the AgentKey server (e.g. `claude mcp add`), **not** by the skill | Claude Code MCP registration (+ `AGENTKEY_API_KEY` storage on the API-key fallback path) |
| `~/.cursor/mcp.json` | written by your MCP client / agent when you register the AgentKey server, **not** by the skill | MCP registration |
### Network egress from the skill
| Destination | When | Why |
|---|---|---|
| `api.github.com` | At most every 24 hours | Look up the latest release tag |
| npm registry | When the user accepts a skill update | Resolve and run `npx skills update agentkey` |
### Credential handling
- `AGENTKEY_API_KEY` is stored only in user-local config files (paths above).
- The key leaves the user's machine only as the `Authorization` header to AgentKey's own API endpoints.
- The skill collects no telemetry.
### Supply chain
- Releases are cut by [release-please](https://github.com/googleapis/release-please) from merged Conventional-Commit PRs on `main` — no manual artifact uploads, no manual tag pushes.
- The companion `@agentkey/cli` npm package is published from the same organization. Users invoke it via `npx -y @agentkey/cli`, which resolves to the latest published version at runtime — this is the same threat model as any other `npx`-launched CLI.
- Future work: SLSA provenance attestation via GitHub OIDC + sigstore; signed npm provenance.
## Scanner false-positive notes
Automated scanners (VirusTotal, ClawScan) may flag this skill as `Suspicious` due to one intentional pattern. We document it here so reviewers can verify intent:
1. **`check-update.sh` contacts GitHub.** Pattern may match "remote-controlled binary update" heuristics. **Why this is intentional:** the script is notify-only — it issues a single `GET https://api.github.com/repos/chainbase-labs/agentkey/releases/latest`, compares the tag against a version constant embedded in the script itself, prints a one-line status, and exits. It never writes anywhere except the cache file at `${TMPDIR}/agentkey-update-check`, never invokes `git`, and never executes downloaded code. Update execution lives entirely in the agent's interactive layer (`AskUserQuestion``npx skills update`), gated by explicit user consent or a previously persisted opt-in flag.
If you operate a scanner and need additional context to triage, please email `support@chainbase.com`.