trustdex 0.9.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ko.md +53 -5
- package/README.md +54 -5
- package/bin/trustdex.mjs +136 -0
- package/docs/ARCHITECTURE.ko.md +12 -0
- package/docs/ARCHITECTURE.md +12 -0
- package/docs/CLAUDE.ko.md +13 -1
- package/docs/CLAUDE.md +14 -1
- package/docs/CODEX.ko.md +15 -4
- package/docs/CODEX.md +16 -4
- package/docs/DEFENSIVE_USE_CASE.ko.md +8 -0
- package/docs/DEFENSIVE_USE_CASE.md +9 -0
- package/docs/EVALUATION.ko.md +25 -0
- package/docs/EVALUATION.md +25 -0
- package/docs/ROADMAP.ko.md +10 -4
- package/docs/ROADMAP.md +10 -4
- package/docs/RUNTIME_EVIDENCE.ko.md +89 -0
- package/docs/RUNTIME_EVIDENCE.md +96 -0
- package/docs/THREAT_MODEL.ko.md +9 -0
- package/docs/THREAT_MODEL.md +9 -0
- package/examples/adversarial/README.ko.md +1 -1
- package/examples/adversarial/README.md +1 -1
- package/examples/adversarial/bindings/README.ko.md +8 -0
- package/examples/adversarial/bindings/README.md +8 -0
- package/examples/adversarial/bindings/expected.json +12 -0
- package/examples/adversarial/bindings/runtime-after.json +21 -0
- package/examples/adversarial/bindings/runtime-before.json +13 -0
- package/package.json +3 -3
- package/schemas/effective-runtime-tools-diff-v1.schema.json +50 -0
- package/schemas/effective-runtime-tools-diff-v2.schema.json +51 -0
- package/schemas/effective-runtime-tools-v1.schema.json +68 -0
- package/schemas/effective-runtime-tools-v2.schema.json +98 -0
- package/schemas/runtime-tool-inventory-attestation-v1.schema.json +27 -0
- package/schemas/runtime-tool-inventory-v1.schema.json +27 -0
- package/src/bindings.mjs +4 -0
- package/src/runtime-attestation.mjs +202 -0
- package/src/runtime-evidence.mjs +392 -0
|
@@ -46,6 +46,7 @@ This work is defensive engineering. It does not require credential theft, persis
|
|
|
46
46
|
| Keep secrets out of evidence | tests for redaction from output, snapshots, and configuration fingerprints |
|
|
47
47
|
| Make approval drift visible | deterministic snapshots, Ed25519 review records, and recheck commands |
|
|
48
48
|
| Reconcile source trust with automatic grants | value-free Claude/Codex binding snapshots, schemas, diffs, and inert fixtures |
|
|
49
|
+
| Compare reviewed intent with explicit runtime evidence | value-free inventory contract, short-lived Ed25519 producer attestations, effective-boundary reconciliation, and exposure drift tests |
|
|
49
50
|
| Reduce supply-chain ambiguity | explicit provenance observations, artifact digest verification, release checksums, SBOMs, and build attestations |
|
|
50
51
|
| Keep research reproducible | inert fixtures, documented expectations, cross-platform CI, and CodeQL |
|
|
51
52
|
|
|
@@ -70,6 +71,14 @@ source decision/provenance state to its automatic tool-grant shape. This makes b
|
|
|
70
71
|
or blocked grants reviewable without retaining tool names or permission specifiers.
|
|
71
72
|
It remains static evidence and does not enforce runtime calls.
|
|
72
73
|
|
|
74
|
+
`snapshot-runtime-tools` accepts a value-free inventory from an authorized runtime
|
|
75
|
+
adapter and reconciles it with those bindings. `sign-runtime-inventory` and
|
|
76
|
+
`verify-runtime-inventory` bind the exact capture to a pinned Ed25519 producer key with
|
|
77
|
+
short expiry and optional capture-age enforcement. This can surface loaded blocked
|
|
78
|
+
sources and unexpected servers without retaining tool names. Authentication does not
|
|
79
|
+
prove capture completeness or protect a compromised adapter; see
|
|
80
|
+
[Authenticated runtime evidence](RUNTIME_EVIDENCE.md).
|
|
81
|
+
|
|
73
82
|
## CVP application boundary
|
|
74
83
|
|
|
75
84
|
Anthropic's current Cyber Verification Program application asks for verifiable identity or organization details, a description of security work, and an attestation to the controls for the requested tier. This repository can support the security-work description, but repository changes cannot establish the operator's identity or satisfy account and device controls by themselves.
|
package/docs/EVALUATION.ko.md
CHANGED
|
@@ -94,6 +94,31 @@ Claude 및 Codex 자동 도구 권한과 연결합니다. 회귀 테스트는
|
|
|
94
94
|
스냅샷을 인증할 수 있지만 스키마나 서명 모두 런타임 강제 또는 도구 안전성을
|
|
95
95
|
증명하지 않습니다.
|
|
96
96
|
|
|
97
|
+
## 실제 런타임 인벤토리 사례
|
|
98
|
+
|
|
99
|
+
`runtime-before.json`, `runtime-after.json` 및 `test/runtime-evidence.test.mjs`는 옵트인
|
|
100
|
+
런타임 인벤토리 계약을 검사합니다. 다음을 요구합니다.
|
|
101
|
+
|
|
102
|
+
- 재검토가 필요 없는 관찰된 ALLOW 소스는 일치
|
|
103
|
+
- 관찰된 BLOCK 소스 또는 설정되지 않은 서버는 실제 경계를 차단
|
|
104
|
+
- 관찰된 ASK/광범위 권한 연결은 재검토
|
|
105
|
+
- 설정되었지만 관찰되지 않은 서버는 제한적으로만 변경
|
|
106
|
+
- 새로 관찰된 서버와 도구 개수 증가는 확대
|
|
107
|
+
- 노출이 일치해도 인증하지 않은 스키마 v2 인벤토리는 `needs-review` 유지
|
|
108
|
+
- 원시 도구 목록, 중복 서버 이름, 예상 밖 필드, 잘못된 타임스탬프 및 변조된 증거는 안전하게 실패
|
|
109
|
+
- 출력에는 서버 이름, 도구 개수, 고정 정책/출처 열거 값 및 다이제스트만 보관
|
|
110
|
+
|
|
111
|
+
`test/runtime-attestation.test.mjs`는 추가로 Ed25519 서명이 정확한 인벤토리,
|
|
112
|
+
런타임 메타데이터, 생성자 키 ID, 생성 시각 및 만료를 연결하도록 요구합니다. 다른 키,
|
|
113
|
+
변경된 인벤토리, 만료되거나 오래된 캡처, 과도한 수명 및 미래 시각 증거는 안전하게
|
|
114
|
+
실패합니다. CLI 테스트는 비공개 키 자료를 출력하지 않고 인증된 대조만 `matched`에
|
|
115
|
+
도달하도록 요구합니다.
|
|
116
|
+
|
|
117
|
+
픽스처는 어댑터 형태의 증거이지 실제 Claude 또는 Codex 캡처가 아닙니다. 유효한
|
|
118
|
+
생성자 서명은 전달된 바이트와 고정 키를 인증하지만 완전성이나 진실성을 증명하지
|
|
119
|
+
않습니다. 값 없는 계약이 도구 이름을 의도적으로 제외하므로 도구 개수는 같고
|
|
120
|
+
집합만 바뀌는 대체는 감지할 수 없습니다.
|
|
121
|
+
|
|
97
122
|
## 병합 설정 스택 사례
|
|
98
123
|
|
|
99
124
|
`test/settings-stack.test.mjs`는 두 런타임의 명시적 소스 스택을 검사합니다. 다음을 요구합니다.
|
package/docs/EVALUATION.md
CHANGED
|
@@ -96,6 +96,31 @@ The snapshot schemas validate the stable report shape. A signed trust record can
|
|
|
96
96
|
authenticate a reviewed snapshot, but neither the schema nor signature proves runtime
|
|
97
97
|
enforcement or tool safety.
|
|
98
98
|
|
|
99
|
+
## Effective runtime inventory cases
|
|
100
|
+
|
|
101
|
+
`runtime-before.json`, `runtime-after.json`, and `test/runtime-evidence.test.mjs`
|
|
102
|
+
exercise the opt-in runtime inventory contract. They require:
|
|
103
|
+
|
|
104
|
+
- an observed ALLOW source with no review-required binding to match
|
|
105
|
+
- an observed BLOCK source or unconfigured server to block the effective boundary
|
|
106
|
+
- an observed ASK/broad-grant binding to require review
|
|
107
|
+
- configured but unobserved servers to be restriction-only
|
|
108
|
+
- newly observed servers and tool-count growth to be expansion
|
|
109
|
+
- unauthenticated schema-v2 inventories to remain `needs-review` even when exposure matches
|
|
110
|
+
- raw tool lists, duplicate server names, extra fields, invalid timestamps, and tampered evidence to fail closed
|
|
111
|
+
- output to retain only server names, tool counts, fixed policy/provenance enums, and digests
|
|
112
|
+
|
|
113
|
+
`test/runtime-attestation.test.mjs` additionally requires an Ed25519 signature to bind
|
|
114
|
+
the exact inventory, runtime metadata, producer key ID, creation time, and expiry. Wrong
|
|
115
|
+
keys, modified inventories, expired/stale captures, excessive lifetimes, and future-dated
|
|
116
|
+
evidence fail closed. The CLI test requires authenticated reconciliation to reach
|
|
117
|
+
`matched` without printing private-key material.
|
|
118
|
+
|
|
119
|
+
The fixture is adapter-shaped evidence, not a live Claude or Codex capture. A valid
|
|
120
|
+
producer signature authenticates the supplied bytes and pinned key, not completeness or
|
|
121
|
+
truthfulness. Same-count tool-set substitutions are invisible because the value-free
|
|
122
|
+
contract intentionally omits tool names.
|
|
123
|
+
|
|
99
124
|
## Merged settings stack cases
|
|
100
125
|
|
|
101
126
|
`test/settings-stack.test.mjs` exercises explicit source stacks for both runtimes. It requires:
|
package/docs/ROADMAP.ko.md
CHANGED
|
@@ -16,6 +16,11 @@ TrustDex는 초기 단계입니다. 이 로드맵은 방향을 공유하며 릴
|
|
|
16
16
|
검사, 스키마 v2 소스 구성 증거 및 안전하게 실패하는 스택 테스트를 추가합니다.
|
|
17
17
|
- TrustDex 0.9.0은 MCP 정책/출처 결과와 자동 도구 권한 사이의 값 없는 Claude/Codex
|
|
18
18
|
연결, 버전 지정 스키마, 드리프트 검토 및 비활성 픽스처를 추가합니다.
|
|
19
|
+
- TrustDex 0.10.0은 명시적인 값 없는 런타임 인벤토리 계약, 실제 경계 대조,
|
|
20
|
+
노출 드리프트 검토, 버전 지정 스키마 및 픽스처를 추가합니다.
|
|
21
|
+
- TrustDex 0.11.0은 정확한 런타임 인벤토리의 Ed25519 생성자 인증, 제한된 만료/캡처
|
|
22
|
+
나이, 스키마 v2 인증 상태와 재사용·다른 키·미래 시각·변조·미인증 증거를
|
|
23
|
+
안전하게 실패시키는 테스트를 추가합니다.
|
|
19
24
|
|
|
20
25
|
## 현재: 경계 강화
|
|
21
26
|
|
|
@@ -28,10 +33,11 @@ TrustDex는 초기 단계입니다. 이 로드맵은 방향을 공유하며 릴
|
|
|
28
33
|
|
|
29
34
|
## 다음: 실제 런타임 증거 강화
|
|
30
35
|
|
|
31
|
-
-
|
|
32
|
-
-
|
|
33
|
-
-
|
|
34
|
-
-
|
|
36
|
+
- 런타임이 권한 있는 안정적 인터페이스를 제공할 때만 구체적인 옵트인 어댑터 게시
|
|
37
|
+
- 배포용 공개 키 허용 목록, 교체 및 폐기 연결 지점 추가
|
|
38
|
+
- 메시지 수준 생성자 서명 주변의 전송 보호 문서화
|
|
39
|
+
- 값 없는 보고서를 유지하면서 MCP 표시 범위 밖으로 실제 증거 확장
|
|
40
|
+
- 지원하는 어댑터/런타임 버전의 테스트 기반 호환성 매트릭스 게시
|
|
35
41
|
|
|
36
42
|
## 그다음: 무결성 증명
|
|
37
43
|
|
package/docs/ROADMAP.md
CHANGED
|
@@ -16,6 +16,11 @@ TrustDex is early-stage. This roadmap communicates direction and is not a releas
|
|
|
16
16
|
and Codex precedence, schema-v2 source topology evidence, and fail-closed stack tests.
|
|
17
17
|
- TrustDex 0.9.0 adds value-free Claude/Codex bindings between MCP policy/provenance
|
|
18
18
|
results and automatic tool grants, versioned schemas, drift review, and inert fixtures.
|
|
19
|
+
- TrustDex 0.10.0 adds an explicit value-free runtime inventory contract, effective
|
|
20
|
+
boundary reconciliation, exposure-drift review, versioned schemas, and fixtures.
|
|
21
|
+
- TrustDex 0.11.0 adds Ed25519 producer authentication for exact runtime inventories,
|
|
22
|
+
bounded expiry/capture age, schema-v2 authentication state, and fail-closed tests for
|
|
23
|
+
replay, wrong-key, future-time, mutation, and unauthenticated evidence.
|
|
19
24
|
|
|
20
25
|
## Now: harden the boundary
|
|
21
26
|
|
|
@@ -28,10 +33,11 @@ TrustDex is early-stage. This roadmap communicates direction and is not a releas
|
|
|
28
33
|
|
|
29
34
|
## Next: strengthen effective-runtime evidence
|
|
30
35
|
|
|
31
|
-
-
|
|
32
|
-
-
|
|
33
|
-
-
|
|
34
|
-
-
|
|
36
|
+
- ship concrete opt-in adapters only where a runtime exposes an authorized stable interface
|
|
37
|
+
- add deployment-facing public-key allowlists, rotation, and revocation hooks
|
|
38
|
+
- document transport hardening around the message-level producer signature
|
|
39
|
+
- extend effective evidence beyond MCP visibility while retaining value-free reports
|
|
40
|
+
- publish a tested compatibility matrix for supported adapter/runtime versions
|
|
35
41
|
|
|
36
42
|
## Then: prove integrity
|
|
37
43
|
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# 인증된 런타임 증거
|
|
2
|
+
|
|
3
|
+
<p align="right">
|
|
4
|
+
<a href="./RUNTIME_EVIDENCE.md">English</a> | <strong>한국어</strong>
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
TrustDex는 권한이 있는 Claude 또는 Codex 통합이 생성한 값 없는 런타임 인벤토리를
|
|
8
|
+
인증할 수 있습니다. 인증은 고정된 어떤 Ed25519 키가 정확한 인벤토리에 서명했는지와
|
|
9
|
+
수명이 짧은 증명이 신선한지를 확인합니다. 어댑터가 침해되지 않았거나 인벤토리가
|
|
10
|
+
완전하거나 런타임이 검토된 정책을 강제했다는 사실까지 증명하지는 않습니다.
|
|
11
|
+
|
|
12
|
+
## 종단 간 워크플로
|
|
13
|
+
|
|
14
|
+
전용 생성자 키 쌍을 한 번 만드세요. 비공개 키는 어댑터에 보관하고, 공개 키는
|
|
15
|
+
신뢰할 수 있는 채널을 통해 각 검증자에게 배포합니다.
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
node ./bin/trustdex.mjs keygen \
|
|
19
|
+
--private .trustdex/runtime-producer-private.pem \
|
|
20
|
+
--public .trustdex/runtime-producer-public.pem
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
권한 있는 어댑터는 런타임, 캡처 시각/방식, 서버 이름 및 서버별 도구 개수만 담은
|
|
24
|
+
`agent-runtime-tool-inventory` JSON을 작성합니다. 그 파일에 즉시 서명하세요. 기본
|
|
25
|
+
수명은 5분이고 최대 수명은 24시간입니다.
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
node ./bin/trustdex.mjs sign-runtime-inventory \
|
|
29
|
+
./runtime-tool-inventory.json \
|
|
30
|
+
--private .trustdex/runtime-producer-private.pem \
|
|
31
|
+
--out .trustdex/runtime-attestation.json \
|
|
32
|
+
--ttl-seconds 300
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
대조 전에 생성자 신원, 서명, 만료 및 캡처 신선도를 검증합니다.
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
node ./bin/trustdex.mjs verify-runtime-inventory \
|
|
39
|
+
./runtime-tool-inventory.json \
|
|
40
|
+
--attestation .trustdex/runtime-attestation.json \
|
|
41
|
+
--public .trustdex/runtime-producer-public.pem \
|
|
42
|
+
--max-age-seconds 120 \
|
|
43
|
+
--json
|
|
44
|
+
|
|
45
|
+
node ./bin/trustdex.mjs snapshot-runtime-tools \
|
|
46
|
+
.trustdex/claude-bindings.json \
|
|
47
|
+
./runtime-tool-inventory.json \
|
|
48
|
+
--attestation .trustdex/runtime-attestation.json \
|
|
49
|
+
--public .trustdex/runtime-producer-public.pem \
|
|
50
|
+
--max-age-seconds 120 \
|
|
51
|
+
--require-authenticated \
|
|
52
|
+
--out .trustdex/runtime-tools.json
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
잘못되거나 만료되거나 오래되거나 미래 시각이거나 다른 키를 사용하거나 인벤토리와
|
|
56
|
+
불일치하는 증명은 종료 코드 `2`를 반환합니다. 인증하지 않은 스키마 v2 실제 증거는
|
|
57
|
+
항상 최소 `needs-review`가 되며, 관찰된 차단/미설정 서버는 계속 `block`이 됩니다.
|
|
58
|
+
|
|
59
|
+
## 서명 범위
|
|
60
|
+
|
|
61
|
+
Ed25519 서명은 스키마/알고리즘 식별자, 정규 인벤토리 다이제스트, 런타임, 캡처
|
|
62
|
+
시각과 방식, 생성자 공개 키 ID, 생성 시각 및 만료 시각을 포함합니다. 키 ID는 공개
|
|
63
|
+
SPKI 바이트의 SHA-256 다이제스트입니다. 별도 인벤토리 스키마가 원시 도구 목록과
|
|
64
|
+
임의 필드를 거부하므로 증명과 실제 보고서에는 도구 이름, 엔드포인트, 자격 증명 또는
|
|
65
|
+
비공개 키 자료가 포함되지 않습니다.
|
|
66
|
+
|
|
67
|
+
선택적인 `--max-age-seconds`는 증명 만료와 별개입니다. 만료는 서명 사용 가능 시간을,
|
|
68
|
+
최대 나이는 원본 캡처의 허용 나이를 제한합니다. TrustDex는 제한된 시계 오차만
|
|
69
|
+
허용하기 위해 5분보다 먼 미래의 캡처와 증명도 거부합니다.
|
|
70
|
+
|
|
71
|
+
## 운영 및 키 교체
|
|
72
|
+
|
|
73
|
+
- 생성자 전용 키를 사용하고 비공개 파일을 최소 권한으로 보호하며 커밋하지 마세요.
|
|
74
|
+
일반 검토 기록 키도 암호학적으로 작동하지만 운영 역할은 분리해야 합니다.
|
|
75
|
+
- 예상 공개 키는 인벤토리/증명 채널 밖에서 고정하세요. 공격자가 증거와 공개 키를
|
|
76
|
+
모두 바꿀 수 있다면 서명은 신원 주장이 아닙니다.
|
|
77
|
+
- 감사 보존이 필요하면 인벤토리, 증명, 고정 키 ID, 결합 스냅샷 및 실제 보고서를
|
|
78
|
+
함께 보관하세요. 실제 보고서는 자체 일관성을 확인하지만 독립적으로 서명되지는 않습니다.
|
|
79
|
+
- 키 교체 시 새 공개 키를 먼저 배포하고, 제한된 중첩 기간 동안 오케스트레이션에서
|
|
80
|
+
이전 또는 새 고정 키를 허용한 뒤 생성자를 전환하고 이전 키를 폐기하세요. TrustDex는
|
|
81
|
+
호출당 전달된 키 하나를 검증하며 키 허용 목록과 폐기는 배포 환경의 책임입니다.
|
|
82
|
+
- `producer-key-changed`와 `inventory-authentication-changed` 차이를 검토 이벤트로
|
|
83
|
+
취급하세요. 비공개 키 탈취가 의심되면 검증자에서 키를 제거하고 새 키로 증거를 다시 발급하세요.
|
|
84
|
+
|
|
85
|
+
계약은
|
|
86
|
+
[`runtime-tool-inventory-v1.schema.json`](../schemas/runtime-tool-inventory-v1.schema.json),
|
|
87
|
+
[`runtime-tool-inventory-attestation-v1.schema.json`](../schemas/runtime-tool-inventory-attestation-v1.schema.json),
|
|
88
|
+
[`effective-runtime-tools-v2.schema.json`](../schemas/effective-runtime-tools-v2.schema.json),
|
|
89
|
+
[`effective-runtime-tools-diff-v2.schema.json`](../schemas/effective-runtime-tools-diff-v2.schema.json)에 정의되어 있습니다.
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Authenticated runtime evidence
|
|
2
|
+
|
|
3
|
+
<p align="right">
|
|
4
|
+
<strong>English</strong> | <a href="./RUNTIME_EVIDENCE.ko.md">한국어</a>
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
TrustDex can authenticate a value-free runtime inventory produced by an authorized
|
|
8
|
+
Claude or Codex integration. Authentication proves which pinned Ed25519 key signed the
|
|
9
|
+
exact inventory and whether the short-lived attestation is fresh. It does not prove
|
|
10
|
+
that the adapter is uncompromised, that the inventory is complete, or that the runtime
|
|
11
|
+
enforced the reviewed policy.
|
|
12
|
+
|
|
13
|
+
## End-to-end workflow
|
|
14
|
+
|
|
15
|
+
Generate a dedicated producer key pair once. Keep the private key with the adapter and
|
|
16
|
+
distribute the public key through a trusted channel to each verifier:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
node ./bin/trustdex.mjs keygen \
|
|
20
|
+
--private .trustdex/runtime-producer-private.pem \
|
|
21
|
+
--public .trustdex/runtime-producer-public.pem
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
The authorized adapter writes `agent-runtime-tool-inventory` JSON containing only the
|
|
25
|
+
runtime, capture time/method, server names, and per-server tool counts. Sign that exact
|
|
26
|
+
file immediately; the default lifetime is five minutes and the maximum is 24 hours:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
node ./bin/trustdex.mjs sign-runtime-inventory \
|
|
30
|
+
./runtime-tool-inventory.json \
|
|
31
|
+
--private .trustdex/runtime-producer-private.pem \
|
|
32
|
+
--out .trustdex/runtime-attestation.json \
|
|
33
|
+
--ttl-seconds 300
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Verify producer identity, signature, expiry, and capture freshness before reconciliation:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
node ./bin/trustdex.mjs verify-runtime-inventory \
|
|
40
|
+
./runtime-tool-inventory.json \
|
|
41
|
+
--attestation .trustdex/runtime-attestation.json \
|
|
42
|
+
--public .trustdex/runtime-producer-public.pem \
|
|
43
|
+
--max-age-seconds 120 \
|
|
44
|
+
--json
|
|
45
|
+
|
|
46
|
+
node ./bin/trustdex.mjs snapshot-runtime-tools \
|
|
47
|
+
.trustdex/claude-bindings.json \
|
|
48
|
+
./runtime-tool-inventory.json \
|
|
49
|
+
--attestation .trustdex/runtime-attestation.json \
|
|
50
|
+
--public .trustdex/runtime-producer-public.pem \
|
|
51
|
+
--max-age-seconds 120 \
|
|
52
|
+
--require-authenticated \
|
|
53
|
+
--out .trustdex/runtime-tools.json
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
An invalid, expired, stale, future-dated, wrong-key, or inventory-mismatched attestation
|
|
57
|
+
exits `2`. Without authentication, schema-v2 effective evidence is always at least
|
|
58
|
+
`needs-review`; observed blocked or unconfigured servers still produce `block`.
|
|
59
|
+
|
|
60
|
+
## What is signed
|
|
61
|
+
|
|
62
|
+
The Ed25519 signature covers the schema and algorithm identifiers, canonical inventory
|
|
63
|
+
digest, runtime, capture time and method, producer public-key ID, creation time, and
|
|
64
|
+
expiry. The key ID is the SHA-256 digest of the public SPKI bytes. The separate inventory
|
|
65
|
+
schema rejects raw tool lists and arbitrary fields, so neither the attestation nor the
|
|
66
|
+
effective report contains tool names, endpoints, credentials, or private-key material.
|
|
67
|
+
|
|
68
|
+
The optional `--max-age-seconds` limit is independent of attestation expiry: expiry caps
|
|
69
|
+
how long the signature is usable, while maximum age caps how old the underlying capture
|
|
70
|
+
may be. TrustDex also rejects captures and attestations more than five minutes in the
|
|
71
|
+
future to tolerate only bounded clock skew.
|
|
72
|
+
|
|
73
|
+
## Operations and key rotation
|
|
74
|
+
|
|
75
|
+
- Use a producer-specific key, protect the private file with least privilege, and never
|
|
76
|
+
commit it. A generic review-record key may work cryptographically but should remain a
|
|
77
|
+
separate operational role.
|
|
78
|
+
- Pin the expected public key outside the inventory/attestation channel. A signature is
|
|
79
|
+
not an identity claim if an attacker can replace both the evidence and its public key.
|
|
80
|
+
- Archive the inventory, attestation, pinned key ID, binding snapshot, and effective
|
|
81
|
+
report together when audit retention is required. The effective report is
|
|
82
|
+
self-consistent but is not independently signed.
|
|
83
|
+
- For rotation, distribute the new public key first, update orchestration to accept the
|
|
84
|
+
old or new pinned key during a bounded overlap, then switch the producer and retire the
|
|
85
|
+
old key. TrustDex verifies one supplied key per invocation; key allowlists and revocation
|
|
86
|
+
remain deployment responsibilities.
|
|
87
|
+
- Treat `producer-key-changed` and `inventory-authentication-changed` diffs as review
|
|
88
|
+
events. If a private key is suspected to be stolen, remove that key from verifiers and
|
|
89
|
+
reissue evidence with a new key.
|
|
90
|
+
|
|
91
|
+
The contracts are defined by
|
|
92
|
+
[`runtime-tool-inventory-v1.schema.json`](../schemas/runtime-tool-inventory-v1.schema.json),
|
|
93
|
+
[`runtime-tool-inventory-attestation-v1.schema.json`](../schemas/runtime-tool-inventory-attestation-v1.schema.json),
|
|
94
|
+
[`effective-runtime-tools-v2.schema.json`](../schemas/effective-runtime-tools-v2.schema.json),
|
|
95
|
+
and [`effective-runtime-tools-diff-v2.schema.json`](../schemas/effective-runtime-tools-diff-v2.schema.json).
|
|
96
|
+
|
package/docs/THREAT_MODEL.ko.md
CHANGED
|
@@ -26,6 +26,9 @@ TrustDex는 하나의 좁은 질문을 다룹니다.
|
|
|
26
26
|
- 명시적으로 전달된 Claude 또는 Codex 설정 소스 사이의 우선순위 변경
|
|
27
27
|
- 서버의 정책/출처 결과와 더 이상 일치하지 않는 자동 MCP 도구 권한
|
|
28
28
|
- 실제 도구 경계를 가리는 와일드카드, 일치하지 않거나 모호한 권한
|
|
29
|
+
- 차단·검토 필요·미설정 MCP 서버를 노출한다고 명시적으로 보고한 런타임 인벤토리
|
|
30
|
+
- 서버 표시 범위 또는 도구 개수로 확대되는 실제 런타임 인벤토리
|
|
31
|
+
- 서명된 런타임 인벤토리의 변조, 만료/캡처 나이 이후 재사용, 미래 시각 지정 또는 다른 키 대체
|
|
29
32
|
|
|
30
33
|
## 신뢰 경계
|
|
31
34
|
|
|
@@ -54,11 +57,17 @@ TrustDex는 익숙한 프로젝트 이름, 스타 수, 패키지 이름 또는
|
|
|
54
57
|
- 서명되지 않은 권한 상태 스냅샷 작성자의 인증
|
|
55
58
|
- 결합 스냅샷이 실행 중인 에이전트가 실제로 불러온 파일을 반영함을 증명하는 것
|
|
56
59
|
- 개별 MCP 도구 호출을 런타임에서 가로채거나 강제하는 것
|
|
60
|
+
- 인벤토리 완전성 증명 또는 침해된 어댑터나 탈취된 생성자 키의 거짓 증거 서명 방지
|
|
61
|
+
- 실제 Claude/Codex 세션을 자동으로 찾거나 비공개 상태를 읽는 것
|
|
57
62
|
|
|
58
63
|
## 중요한 실패 모드
|
|
59
64
|
|
|
60
65
|
유효한 서명은 신뢰 기록이 해당 비공개 키로 서명되었고 연결된 스냅샷 다이제스트가 변경되지 않았음을 증명합니다. 원래 검토가 정확했다는 것은 증명하지 않습니다.
|
|
61
66
|
|
|
67
|
+
마찬가지로 유효한 런타임 인벤토리 증명은 고정된 생성자 키가 검사된 시간 제한 안에서
|
|
68
|
+
정확한 값 없는 인벤토리에 서명했음을 증명합니다. 생성자가 로드된 모든 도구를
|
|
69
|
+
관찰했거나 런타임을 진실하게 보고했다는 사실은 증명하지 않습니다.
|
|
70
|
+
|
|
62
71
|
## 설계 원칙
|
|
63
72
|
|
|
64
73
|
TrustDex는 누락된 증거를 신뢰로 변환해서는 안 됩니다. 알 수 없는 출처는 추측할 이유가 아니라 정책 입력입니다.
|
package/docs/THREAT_MODEL.md
CHANGED
|
@@ -26,6 +26,9 @@ TrustDex addresses one narrow question:
|
|
|
26
26
|
- precedence changes across explicitly supplied Claude or Codex settings sources
|
|
27
27
|
- automatic MCP tool grants that no longer match the server's policy/provenance result
|
|
28
28
|
- wildcard, unmatched, or ambiguous grants that hide the effective tool boundary
|
|
29
|
+
- explicitly reported runtime inventories that expose blocked, review-required, or unconfigured MCP servers
|
|
30
|
+
- effective runtime inventories expanding by server visibility or tool count
|
|
31
|
+
- mutation, replay past expiry/capture-age limits, future dating, or wrong-key substitution of signed runtime inventories
|
|
29
32
|
|
|
30
33
|
## Trust boundaries
|
|
31
34
|
|
|
@@ -54,11 +57,17 @@ TrustDex does **not** treat a familiar project name, star count, package name, o
|
|
|
54
57
|
- authenticating the author of an unsigned permission posture snapshot
|
|
55
58
|
- proving that a binding snapshot reflects the files actually loaded by a running agent
|
|
56
59
|
- intercepting or enforcing individual MCP tool calls at runtime
|
|
60
|
+
- proving inventory completeness or preventing a compromised adapter or stolen producer key from signing false evidence
|
|
61
|
+
- discovering live Claude/Codex sessions or reading their private state automatically
|
|
57
62
|
|
|
58
63
|
## Important failure mode
|
|
59
64
|
|
|
60
65
|
A valid signature proves that a trust record was signed by the corresponding private key and that its bound snapshot digest has not changed. It does not prove that the original review was correct.
|
|
61
66
|
|
|
67
|
+
Likewise, a valid runtime-inventory attestation proves that the pinned producer key
|
|
68
|
+
signed the exact value-free inventory within the checked time limits. It does not prove
|
|
69
|
+
that the producer observed every loaded tool or reported the runtime truthfully.
|
|
70
|
+
|
|
62
71
|
## Design principle
|
|
63
72
|
|
|
64
73
|
TrustDex should never convert missing evidence into trust. Unknown provenance is a policy input, not a reason to guess.
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
- `expected.json`은 필수 결정과 최소 신호를 기록합니다.
|
|
12
12
|
- `drift-before.json`과 `drift-after.json`은 검토된 패키지에 비밀 정보를 포함하는 환경 키가 추가되는 상황을 모델링합니다.
|
|
13
13
|
- [`permissions/`](permissions/README.ko.md)는 값이 제거된 Claude/Codex 권한 상태 드리프트를 다룹니다.
|
|
14
|
-
- [`bindings/`](bindings/README.ko.md)는 MCP 출처와 자동
|
|
14
|
+
- [`bindings/`](bindings/README.ko.md)는 MCP 출처와 자동 권한 연결 및 명시적 런타임 인벤토리 대조를 다룹니다.
|
|
15
15
|
|
|
16
16
|
모든 패키지 이름은 가상이며, 모든 원격 엔드포인트는 예약된 `.invalid` 최상위 도메인을 사용하고, 자격 증명으로 보이는 모든 값은 자리표시자입니다. 이를 실제 값으로 바꾸지 마세요. TrustDex는 이 파일을 읽지만 나열된 명령을 실행하거나 나열된 엔드포인트에 연결하지 않습니다.
|
|
17
17
|
|
|
@@ -11,7 +11,7 @@ These files provide a reproducible defensive test of TrustDex's policy boundary.
|
|
|
11
11
|
- `expected.json` records the required decisions and minimum signals.
|
|
12
12
|
- `drift-before.json` and `drift-after.json` model a reviewed package gaining a secret-bearing environment key.
|
|
13
13
|
- [`permissions/`](permissions/README.md) covers value-free Claude/Codex permission posture drift.
|
|
14
|
-
- [`bindings/`](bindings/README.md) covers MCP provenance-to-automatic-grant bindings.
|
|
14
|
+
- [`bindings/`](bindings/README.md) covers MCP provenance-to-automatic-grant bindings and explicit runtime inventory reconciliation.
|
|
15
15
|
|
|
16
16
|
All package names are fictional, all remote endpoints use the reserved `.invalid` top-level domain, and all apparent credentials are placeholders. Do not replace them with real values. TrustDex reads these files but never executes the listed commands or contacts the listed endpoints.
|
|
17
17
|
|
|
@@ -13,6 +13,10 @@ node ../../../bin/trustdex.mjs snapshot-claude-bindings ./claude.mcp.json \
|
|
|
13
13
|
node ../../../bin/trustdex.mjs snapshot-codex-bindings ./codex.toml \
|
|
14
14
|
--trust-store ./trust-store.json \
|
|
15
15
|
--out ./codex.bindings.json
|
|
16
|
+
|
|
17
|
+
node ../../../bin/trustdex.mjs snapshot-runtime-tools \
|
|
18
|
+
./claude.bindings.json ./runtime-after.json \
|
|
19
|
+
--out ./runtime.evidence.json
|
|
16
20
|
```
|
|
17
21
|
|
|
18
22
|
검토된 Claude 서버의 범위 제한 승인은 `ALLOW` 결과와 결합됩니다. 출처를 알 수
|
|
@@ -22,3 +26,7 @@ node ../../../bin/trustdex.mjs snapshot-codex-bindings ./codex.toml \
|
|
|
22
26
|
|
|
23
27
|
생성된 보고서는 엔드포인트 경로, 권한 지정자, 도구 이름 및 마커 값을 의도적으로
|
|
24
28
|
제외합니다. `expected.json`은 안정적인 구조적 결과만 기록합니다.
|
|
29
|
+
런타임 인벤토리는 명시적으로 제공되는 값 없는 어댑터 출력입니다. 도구 이름 대신
|
|
30
|
+
서버 이름과 도구 개수만 포함합니다. `runtime-after.json`은 차단된 설정 서버와 예상
|
|
31
|
+
밖 서버가 노출되는 상황을 모델링합니다. TrustDex는 런타임 상태를 자동으로 찾거나
|
|
32
|
+
인벤토리 생성자를 인증하지 않습니다.
|
|
@@ -14,6 +14,10 @@ node ../../../bin/trustdex.mjs snapshot-claude-bindings ./claude.mcp.json \
|
|
|
14
14
|
node ../../../bin/trustdex.mjs snapshot-codex-bindings ./codex.toml \
|
|
15
15
|
--trust-store ./trust-store.json \
|
|
16
16
|
--out ./codex.bindings.json
|
|
17
|
+
|
|
18
|
+
node ../../../bin/trustdex.mjs snapshot-runtime-tools \
|
|
19
|
+
./claude.bindings.json ./runtime-after.json \
|
|
20
|
+
--out ./runtime.evidence.json
|
|
17
21
|
```
|
|
18
22
|
|
|
19
23
|
The reviewed Claude server has a scoped grant bound to an `ALLOW` result. Its
|
|
@@ -23,3 +27,7 @@ review because `default_tools_approval_mode = "approve"` grants every tool.
|
|
|
23
27
|
|
|
24
28
|
Generated reports intentionally omit endpoint paths, permission specifiers, tool
|
|
25
29
|
names, and marker values. `expected.json` records only stable structural outcomes.
|
|
30
|
+
The runtime inventories are explicit, value-free adapter outputs: they contain server
|
|
31
|
+
names and tool counts, not tool names. `runtime-after.json` models a blocked configured
|
|
32
|
+
server and an unexpected server becoming visible. TrustDex does not discover runtime
|
|
33
|
+
state or authenticate the inventory producer.
|
|
@@ -11,5 +11,17 @@
|
|
|
11
11
|
"automaticGrantCount": 2,
|
|
12
12
|
"reviewCount": 1,
|
|
13
13
|
"blockedCount": 1
|
|
14
|
+
},
|
|
15
|
+
"runtimeBefore": {
|
|
16
|
+
"status": "needs-review",
|
|
17
|
+
"observedServerCount": 1,
|
|
18
|
+
"matchedCount": 1,
|
|
19
|
+
"notObservedCount": 1
|
|
20
|
+
},
|
|
21
|
+
"runtimeAfter": {
|
|
22
|
+
"status": "block",
|
|
23
|
+
"observedServerCount": 3,
|
|
24
|
+
"blockedCount": 1,
|
|
25
|
+
"unexpectedCount": 1
|
|
14
26
|
}
|
|
15
27
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"kind": "agent-runtime-tool-inventory",
|
|
4
|
+
"runtime": "claude",
|
|
5
|
+
"capturedAt": "2026-10-24T00:05:00.000Z",
|
|
6
|
+
"captureMethod": "runtime-adapter",
|
|
7
|
+
"servers": [
|
|
8
|
+
{
|
|
9
|
+
"name": "reviewed",
|
|
10
|
+
"toolCount": 2
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"name": "unknown",
|
|
14
|
+
"toolCount": 1
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"name": "unexpected",
|
|
18
|
+
"toolCount": 1
|
|
19
|
+
}
|
|
20
|
+
]
|
|
21
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "trustdex",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "A local-first trust, provenance, and review gate for AI agent tools, MCP servers, skills, and plugins.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
10
|
"test": "node --test",
|
|
11
|
-
"test:research": "node --test test/research-fixtures.test.mjs test/claude-settings.test.mjs test/codex-settings.test.mjs test/posture.test.mjs test/settings-stack.test.mjs test/bindings.test.mjs",
|
|
12
|
-
"check": "node --check bin/trustdex.mjs && node --check src/bindings.mjs && node --check src/canonical.mjs && node --check src/claude-config.mjs && node --check src/claude-settings.mjs && node --check src/codex-config.mjs && node --check src/codex-settings.mjs && node --check src/extensions.mjs && node --check src/gate.mjs && node --check src/inspect.mjs && node --check src/policy.mjs && node --check src/policy-packs.mjs && node --check src/posture.mjs && node --check src/provenance.mjs && node --check src/provenance-online.mjs && node --check src/review.mjs && node --check src/snapshot.mjs && node --check src/trust-record.mjs",
|
|
11
|
+
"test:research": "node --test test/research-fixtures.test.mjs test/claude-settings.test.mjs test/codex-settings.test.mjs test/posture.test.mjs test/settings-stack.test.mjs test/bindings.test.mjs test/runtime-evidence.test.mjs test/runtime-attestation.test.mjs",
|
|
12
|
+
"check": "node --check bin/trustdex.mjs && node --check src/bindings.mjs && node --check src/runtime-evidence.mjs && node --check src/runtime-attestation.mjs && node --check src/canonical.mjs && node --check src/claude-config.mjs && node --check src/claude-settings.mjs && node --check src/codex-config.mjs && node --check src/codex-settings.mjs && node --check src/extensions.mjs && node --check src/gate.mjs && node --check src/inspect.mjs && node --check src/policy.mjs && node --check src/policy-packs.mjs && node --check src/posture.mjs && node --check src/provenance.mjs && node --check src/provenance-online.mjs && node --check src/review.mjs && node --check src/snapshot.mjs && node --check src/trust-record.mjs",
|
|
13
13
|
"prepublishOnly": "npm test && npm run check"
|
|
14
14
|
},
|
|
15
15
|
"engines": {
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://github.com/grigent/trustdex/blob/main/schemas/effective-runtime-tools-diff-v1.schema.json",
|
|
4
|
+
"title": "TrustDex effective runtime tool boundary diff v1",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"additionalProperties": false,
|
|
7
|
+
"required": ["schemaVersion", "runtime", "status", "baselineDigest", "currentDigest", "summary", "changes"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"schemaVersion": { "const": 1 },
|
|
10
|
+
"runtime": { "enum": ["claude", "codex"] },
|
|
11
|
+
"status": { "enum": ["unchanged", "restricted", "needs-review"] },
|
|
12
|
+
"baselineDigest": { "$ref": "#/$defs/digest" },
|
|
13
|
+
"currentDigest": { "$ref": "#/$defs/digest" },
|
|
14
|
+
"summary": {
|
|
15
|
+
"type": "object",
|
|
16
|
+
"additionalProperties": false,
|
|
17
|
+
"required": ["expansions", "restrictions", "reviews"],
|
|
18
|
+
"properties": {
|
|
19
|
+
"expansions": { "$ref": "#/$defs/count" },
|
|
20
|
+
"restrictions": { "$ref": "#/$defs/count" },
|
|
21
|
+
"reviews": { "$ref": "#/$defs/count" }
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"changes": {
|
|
25
|
+
"type": "array",
|
|
26
|
+
"items": {
|
|
27
|
+
"type": "object",
|
|
28
|
+
"additionalProperties": false,
|
|
29
|
+
"required": ["impact", "type", "name", "field", "before", "after"],
|
|
30
|
+
"properties": {
|
|
31
|
+
"impact": { "enum": ["expansion", "restriction", "review"] },
|
|
32
|
+
"type": {
|
|
33
|
+
"enum": [
|
|
34
|
+
"bindings-changed", "capture-method-changed", "server-added", "server-removed",
|
|
35
|
+
"observation-changed", "tool-count-changed", "binding-state-changed", "server-status-changed"
|
|
36
|
+
]
|
|
37
|
+
},
|
|
38
|
+
"name": { "oneOf": [{ "type": "string", "minLength": 1 }, { "type": "null" }] },
|
|
39
|
+
"field": { "type": "string", "minLength": 1 },
|
|
40
|
+
"before": {},
|
|
41
|
+
"after": {}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
"$defs": {
|
|
47
|
+
"digest": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
|
|
48
|
+
"count": { "type": "integer", "minimum": 0 }
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://github.com/grigent/trustdex/blob/main/schemas/effective-runtime-tools-diff-v2.schema.json",
|
|
4
|
+
"title": "TrustDex authenticated effective runtime tool boundary diff v2",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"additionalProperties": false,
|
|
7
|
+
"required": ["schemaVersion", "runtime", "status", "baselineDigest", "currentDigest", "summary", "changes"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"schemaVersion": { "const": 2 },
|
|
10
|
+
"runtime": { "enum": ["claude", "codex"] },
|
|
11
|
+
"status": { "enum": ["unchanged", "restricted", "needs-review"] },
|
|
12
|
+
"baselineDigest": { "$ref": "#/$defs/digest" },
|
|
13
|
+
"currentDigest": { "$ref": "#/$defs/digest" },
|
|
14
|
+
"summary": {
|
|
15
|
+
"type": "object",
|
|
16
|
+
"additionalProperties": false,
|
|
17
|
+
"required": ["expansions", "restrictions", "reviews"],
|
|
18
|
+
"properties": {
|
|
19
|
+
"expansions": { "$ref": "#/$defs/count" },
|
|
20
|
+
"restrictions": { "$ref": "#/$defs/count" },
|
|
21
|
+
"reviews": { "$ref": "#/$defs/count" }
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"changes": {
|
|
25
|
+
"type": "array",
|
|
26
|
+
"items": {
|
|
27
|
+
"type": "object",
|
|
28
|
+
"additionalProperties": false,
|
|
29
|
+
"required": ["impact", "type", "name", "field", "before", "after"],
|
|
30
|
+
"properties": {
|
|
31
|
+
"impact": { "enum": ["expansion", "restriction", "review"] },
|
|
32
|
+
"type": {
|
|
33
|
+
"enum": [
|
|
34
|
+
"bindings-changed", "capture-method-changed", "inventory-authentication-changed",
|
|
35
|
+
"producer-key-changed", "server-added", "server-removed", "observation-changed",
|
|
36
|
+
"tool-count-changed", "binding-state-changed", "server-status-changed"
|
|
37
|
+
]
|
|
38
|
+
},
|
|
39
|
+
"name": { "oneOf": [{ "type": "string", "minLength": 1 }, { "type": "null" }] },
|
|
40
|
+
"field": { "type": "string", "minLength": 1 },
|
|
41
|
+
"before": {},
|
|
42
|
+
"after": {}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"$defs": {
|
|
48
|
+
"digest": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
|
|
49
|
+
"count": { "type": "integer", "minimum": 0 }
|
|
50
|
+
}
|
|
51
|
+
}
|