diff --git a/AGENTS.md b/AGENTS.md index 0e26fa0..ca1c0f8 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -19,6 +19,7 @@ provider adapters, SDKs, and conformance checks. - Build: `pnpm build` - Tests: `pnpm test` - Public-content scan: `pnpm sanitize` +- All-dependency audit: `pnpm security:audit` (also required by `pnpm check`) ## Contract Rules diff --git a/CHANGELOG.md b/CHANGELOG.md index 152dc3b..b5522b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,14 @@ changes. ## [Unreleased] -No unreleased changes. +### Security + +- Pin transitive `source-map-js` to `1.2.2` to address + [GHSA-68fv-2mgg-jv7q](https://github.com/advisories/GHSA-68fv-2mgg-jv7q) in development tooling. +- Include development and production dependency auditing in `pnpm check`, with a moderate severity + threshold and fail-closed registry handling. Add lockfile and CI-gate regression tests. +- Clarify authentication, ownership, redaction, quotas, native isolation, and generated-media + metadata checks required at a deployment/publication boundary. No portable protocol changes. ## [0.2.0] - 2026-10-09 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d5c8c8d..0677762 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,6 +10,11 @@ pnpm check Use Node.js 22 or later. Keep changes scoped to one protocol or provider concern and add tests for observable behavior. +`pnpm check` includes `pnpm security:audit`, which covers development and production dependencies +at the moderate severity threshold. Registry access is required; advisory-service/network errors +fail the gate rather than silently skipping it. `pnpm test` remains the credential-free local +test command, but does not substitute for the complete check. + ## Contract Changes Public protocol changes must include: diff --git a/README.md b/README.md index d72d8bd..c3354fd 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,10 @@ pnpm dev The reference server listens on `127.0.0.1:4310` and registers the Mock Provider. +`pnpm check` includes a registry-backed audit of all dependencies, including development tooling; +moderate-or-higher advisories and registry failures fail the gate. Run `pnpm security:audit` to +repeat that check independently. See the [security policy](SECURITY.md) for deployment data boundaries. + ```bash conversation_id=$(curl -s -X POST http://127.0.0.1:4310/v1/conversations \ -H 'content-type: application/json' \ diff --git a/README.zh-CN.md b/README.zh-CN.md index 13d378f..ff1903b 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -68,6 +68,10 @@ pnpm check pnpm dev ``` +`pnpm check` 包含开发与生产依赖的完整安全审计,需要访问包注册服务;中危及以上漏洞、 +网络或审计服务失败都会阻断检查。可单独运行 `pnpm security:audit`。真实数据处理与部署边界见 +[安全策略](SECURITY.md)。 + 参考服务默认监听 `127.0.0.1:4310`,并注册 Mock Provider。 ```bash diff --git a/RELEASING.md b/RELEASING.md index 6f15feb..e71b0fd 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -13,13 +13,18 @@ version. pnpm install --frozen-lockfile pnpm check pnpm sanitize -pnpm audit --prod --audit-level high +pnpm security:audit ``` 4. Start the built reference server and verify runtime description, execution, SSE replay, approval, cancellation, capability rejection, and Artifact listing. 5. Confirm generated images and release notes contain no private identifiers or credentials. +Audit the full dependency graph, not only production dependencies: build and test tooling can +also carry advisories. `pnpm check` includes this audit and requires registry access. If a security +fix changes the lockfile, regenerate and verify the source bundle at the new reviewed commit; +old candidate checksums or tag approvals do not apply to the replacement candidate. + ## Versioning - Runtime and package versions use Semantic Versioning. diff --git a/SECURITY.md b/SECURITY.md index a628dbb..9ab61c3 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -36,3 +36,27 @@ and terminal capabilities are disabled; this does not constrain an agent process Permission grants require explicit approval and remembered grants require an explicit option ID. Inbound protocol envelopes are validated before SDK routing to avoid raw diagnostic logging. Apply a deployment-owned sandbox and policies for native events before using real agents. + +## Dependency Gate + +`pnpm security:audit` checks the complete dependency graph, including development tooling, and +fails on moderate-or-higher advisories. `pnpm check` invokes it, so existing CI covers both runtime +and build/test dependencies. Registry/network failures also fail the command; a production-only +audit is not an equivalent substitute. + +The workspace pins the patched `source-map-js@1.2.2` through a targeted override for +[GHSA-68fv-2mgg-jv7q](https://github.com/advisories/GHSA-68fv-2mgg-jv7q). +Keep the override, frozen lockfile, and regression checks aligned when changing this policy. + +## Data Handling Checklist + +- Authenticate callers and authorize each Conversation, Execution, Event, Action, and Artifact + operation before exposing the reference API to untrusted users. Resource IDs are not credentials. +- Inputs, outputs, native events, Provider errors, and Artifact URIs can contain sensitive data. + Restrict access and apply explicit redaction before external logging or export. +- Limit request size, execution concurrency, event volume, and retention at the deployment boundary. + In-memory reference collections are not a bounded retention or deletion policy. +- Isolate the agent's OS privileges, workspace, and network access. Disabling ACP client methods + and using direct argv launch do not sandbox the native process. +- Review both visible image content and metadata, including C2PA/JUMBF containers, before publishing + generated media. Content credentials are provenance metadata, not proof of privacy or safe content. diff --git a/docs/README.md b/docs/README.md index 1815ecb..55257c1 100644 --- a/docs/README.md +++ b/docs/README.md @@ -18,6 +18,7 @@ Current protocol version: `2026-09-02` | Run the reference server | [Quickstart](tutorials/quickstart.md) | | Run an application or implement a Provider | [Runnable examples](../examples/README.md) | | Review delivery acceptance and remaining work | [Delivery plan](development/delivery-plan.md) | +| Review the dependency security repair and gate | [Security maintenance](development/security-maintenance.md) | | Integrate over HTTP/SSE | [OpenAPI 3.1](../spec/openapi.yaml) | | Understand lifecycle semantics | [Protocol](../spec/protocol.md) | | Review state and invariants | [Runtime model](../spec/runtime-model.md) | diff --git a/docs/development/delivery-plan.md b/docs/development/delivery-plan.md index 0dee88b..eca95a5 100644 --- a/docs/development/delivery-plan.md +++ b/docs/development/delivery-plan.md @@ -6,6 +6,11 @@ The accepted ADRs define a portable control/event contract with explicit provide storage, tenant administration, and production scheduling remain deployment responsibilities; this delivery does not claim those features exist in the reference server. +Security maintenance as of 2026-10-13 is tracked separately in the +[security checkpoint](security-maintenance.md). Its full dependency gate supersedes earlier +production-only audit evidence. The old `4902b3f` archive is not the repaired release candidate; +its immutable-tag publication step remains separate from maintenance submission. + ## Acceptance Checklist - [x] DSH compatibility is pinned to an actually tested public SDK, with subprocess integration diff --git a/docs/development/security-maintenance.md b/docs/development/security-maintenance.md new file mode 100644 index 0000000..bf7e012 --- /dev/null +++ b/docs/development/security-maintenance.md @@ -0,0 +1,58 @@ +# Security Maintenance Checkpoint + +As of 2026-10-13. Runtime `0.2.0`, portable protocol `2026-09-02`. + +## Repair + +An all-dependency audit identified +[GHSA-68fv-2mgg-jv7q](https://github.com/advisories/GHSA-68fv-2mgg-jv7q) in the development path +`vitest -> vite -> postcss -> source-map-js@1.2.1`. Production-only auditing did not expose it. +This is a development-tooling denial-of-service advisory, not a demonstrated data-exfiltration +or remote reference-server vulnerability. + +The workspace now overrides only `source-map-js` to the patched `1.2.2`. The frozen lockfile +contains that version and no affected predecessor. Other dependency versions are unchanged. + +## Continuous Gate + +- `pnpm security:audit` checks the full dependency graph at the moderate severity threshold. +- `pnpm check` requires that command after the existing format/lint/type/build/test checks. +- Existing Node 22/24 CI invokes `pnpm check`; no workflow permission expansion is needed. +- Registry/network errors fail the gate rather than silently skipping the audit. +- Two regression tests bind the workspace override, lockfile, command policy, and CI entry point. + +## Local Verification + +The repaired tree passed `pnpm check`: 64 unit/contract tests and 35 credential-free integration +tests, format, lint, type checking, workspace builds, and the all-dependency audit. A separate +`pnpm security:audit` reported no known vulnerabilities. + +## Submission Evidence + +Read-back as of 2026-10-14: the repaired code revision `557ed40` passed +[Node 22/24 CI](https://github.com/capa-cloud/harness-runtime-api/actions/runs/38344351822). +The maintenance change is tracked in [PR 13](https://github.com/capa-cloud/harness-runtime-api/pull/13). +The all-dependency audit was repeated on 2026-10-14 with no known vulnerabilities reported. + +The source/history privacy scan covered 139 tracked files, 32 reachable commits, and 309 unique +historical file objects at that revision, with no credential or private-fingerprint findings. +Local synthetic advisory-service failure returned a nonzero exit, confirming the audit gate does +not silently pass when the registry is unavailable. These are dated, revision-bound observations; +repeat audits for later changes rather than treating the counts as a permanent guarantee. + +## Data And Publication Boundaries + +The [security policy](../../SECURITY.md) and +[production guide](../guides/production-deployment.md) remain normative for deployment controls. +Authentication, resource ownership, event/error redaction, request/state quotas, and OS isolation +are not supplied by this reference implementation. A passing source audit or synthetic integration +test is not approval to expose it to untrusted tenants or process real sensitive data. + +Media review includes visible content and structured provenance metadata such as C2PA/JUMBF. +Keep private audit tooling, raw diagnostics, local handoffs, and workstation/session history outside +the public repository and published assets. Use synthetic data for tests and public examples. + +The earlier `4902b3f` source candidate still contains the affected development dependency; its +archive/checksums are historical evidence, not a repaired release. Security maintenance changes +require a new source bundle and reviewed commit. Immutable tags, GitHub Releases, and npm publication +remain separate authorization steps; this maintenance task does not publish them. diff --git a/docs/guides/production-deployment.md b/docs/guides/production-deployment.md index c2c8a5a..1f1ed21 100644 --- a/docs/guides/production-deployment.md +++ b/docs/guides/production-deployment.md @@ -41,3 +41,19 @@ outside the core package. Authentication, persistence, scheduling, and observability may be implemented by different products. They remain deployment concerns so the portable protocol does not depend on one cloud or proprietary platform. + +## Security Acceptance + +Treat reference-runtime tests as protocol evidence, not production security approval. Before using +real sensitive data or multiple users, verify these controls with synthetic data: + +1. An unauthenticated caller cannot read or mutate any Execution or subscribe to its events. +2. One authenticated actor cannot access another actor's Conversation, Execution, pending Action, + event stream, or Artifact descriptor. Knowing an ID must not bypass ownership checks. +3. Provider errors and native event fields pass the deployment's redaction policy before log/export. +4. Request size, concurrency, retained state, and event volume have enforceable quotas and cleanup. +5. Native processes cannot access another workspace or unapproved host files/network destinations. + +The reference implementation intentionally does not supply these controls. In particular, a +loopback listener is not tenant authentication, an environment allowlist is not an OS sandbox, +and disabling ACP client file/terminal methods does not constrain the native process's own access. diff --git a/package.json b/package.json index 9d6ab62..659a366 100644 --- a/package.json +++ b/package.json @@ -26,12 +26,13 @@ }, "scripts": { "build": "pnpm -r --workspace-concurrency=1 build", - "check": "pnpm format:check && pnpm lint && pnpm typecheck && pnpm test && vitest run --config vitest.integration.config.ts", + "check": "pnpm format:check && pnpm lint && pnpm typecheck && pnpm test && vitest run --config vitest.integration.config.ts && pnpm security:audit", "dev": "pnpm --filter @harness-runtime/server dev", "format": "biome format --write .", "format:check": "biome format .", "lint": "biome lint .", "sanitize": "bash scripts/scan-public.sh .", + "security:audit": "pnpm audit --audit-level moderate", "spec:generate": "pnpm build && node scripts/generate-openapi.mjs", "test": "pnpm build && vitest run", "test:integration": "pnpm build && vitest run --config vitest.integration.config.ts", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 70b3e50..7618aab 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,6 +4,9 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false +overrides: + source-map-js: 1.2.2 + importers: .: @@ -966,8 +969,8 @@ packages: siginfo@2.0.0: resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} - source-map-js@1.2.1: - resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + source-map-js@1.2.2: + resolution: {integrity: sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==} engines: {node: '>=0.10.0'} stackback@0.0.2: @@ -1661,7 +1664,7 @@ snapshots: dependencies: nanoid: 3.3.18 picocolors: 1.1.1 - source-map-js: 1.2.1 + source-map-js: 1.2.2 require-from-string@2.0.2: {} @@ -1687,7 +1690,7 @@ snapshots: siginfo@2.0.0: {} - source-map-js@1.2.1: {} + source-map-js@1.2.2: {} stackback@0.0.2: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 924b55f..5955099 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,2 +1,4 @@ packages: - packages/* +overrides: + source-map-js: 1.2.2 diff --git a/tests/security-policy.test.ts b/tests/security-policy.test.ts new file mode 100644 index 0000000..407706d --- /dev/null +++ b/tests/security-policy.test.ts @@ -0,0 +1,30 @@ +import { readFile } from 'node:fs/promises' +import { describe, expect, it } from 'vitest' +import { parse } from 'yaml' + +const read = (path: string) => readFile(new URL(`../${path}`, import.meta.url), 'utf8') + +describe('dependency security policy', () => { + it('audits development and production dependencies through the existing CI check command', async () => { + const manifest = JSON.parse(await read('package.json')) + expect(manifest.scripts['security:audit']).toBe('pnpm audit --audit-level moderate') + expect(manifest.scripts.check).toMatch(/&& pnpm security:audit$/) + const workflow = parse(await read('.github/workflows/ci.yml')) + expect( + workflow.jobs.check.steps.some((step: { run?: string }) => step.run === 'pnpm check'), + ).toBe(true) + }) + + it('locks the patched source-map dependency without retaining the vulnerable version', async () => { + const workspace = parse(await read('pnpm-workspace.yaml')) + const lockfile = parse(await read('pnpm-lock.yaml')) + expect(workspace.overrides['source-map-js']).toBe('1.2.2') + expect(lockfile.overrides['source-map-js']).toBe('1.2.2') + expect( + Object.keys(lockfile.packages).filter((name) => name.startsWith('source-map-js@')), + ).toEqual(['source-map-js@1.2.2']) + expect( + Object.keys(lockfile.snapshots).filter((name) => name.startsWith('source-map-js@')), + ).toEqual(['source-map-js@1.2.2']) + }) +})