chore(deps): take vta-sdk 0.32 and vta-service 0.23 - #263
Conversation
Three fixes reach this repo through calls it already makes. VTI #1184 and #1192 are one defect in two halves. `didcomm_transport` and `tsp_transport` built every client with `identity: None`, so a dispatched Trust Task carried no `issuer`, no `recipient` and no proof — which the VTA's dispatch spine refuses as `malformedRequest` over DIDComm and, because the TSP paths back-fill those two members, as `proofRequired` over TSP. Same bug, two names, depending on transport. #1192 then stopped `address_trust_task` rewriting `issuer`/`recipient` *after* signing, which had been turning a valid proof into `proofInvalid` at the far end. Every Trust Task this repo dispatches — agent names, devices, keys, join — goes through those transports. VTI #1193 lifts Trust-Task signing off `did:key`: the signer derived the verification method as `<did>#<multibase>`, which only a `did:key` has, so a provisioned `did:webvh` integration could not sign any of the 210 proof-requiring tasks. VTI #1191 adds `device_heartbeat_named`, which is what will let this install correct its own `displayName` — set once at registration and, until now, unchangeable. Taken here, used next. ## Two upstream edges had to move first `vta-sdk` is 0.x, so a requirement of `"0.31"` excludes 0.32 and any consumer that keeps one ends up with two copies in the graph, which do not unify. - `did-git-sign` (and `vgi-core`) — the `[patch.crates-io]` rev moves from VGI #33's previous head to its new one, which takes vta-sdk 0.32 with no source change. That is the fifth consecutive cycle this crate has been the thing in the way (0.23, 0.25, 0.27, 0.31, 0.32) and the second where the patch block absorbed it instead of a full VGI release cycle. - `vta-service` 0.22 → 0.23, the `MockVta` dev-dependency. 0.22 is built on vta-sdk 0.31, so leaving it would have split the **dev** graph while the shipped one looked clean — the exact shape the note above `trust-tasks-rs` records from the 0.6 → 0.9 move. Its eleven siblings move with it, because the versions cargo had locked (vta-audit 0.3.0, vta-keys 0.4.0, …) also ask for vta-sdk 0.31, and updating only the two named crates left 0.31.1 in the tree. `trql-client`, the third git-pinned edge, does **not** depend on `vta-sdk` at all — its own dependencies are `trust-tasks-rs`, the TDK and the messaging SDK — so the pinned trust-registry rev stays where it is. Nothing else moves either: vta-sdk 0.32 keeps trust-tasks-rs 0.17, affinidi-tdk 0.10 and affinidi-messaging-sdk 0.21. ## The one source change `ClientIdentity` gained `verification_method` (#1193), so the two sites that built it as a struct literal now use `ClientIdentity::did_key`. That is not just mechanical: the constructor is for the one method whose key *is* its identifier, which is what both sites have — provisioning mints the admin as a `did:key`, and the bootstrap e2e asserts it. The assumption is now in the call rather than implicit in a field that happens to be absent. Verified: `cargo tree -d -e normal,build,dev` shows no `vta-sdk`, `trust-tasks-rs`, `affinidi-tdk`, `affinidi-messaging-sdk`, `vti-common` or `vta-service` duplicate; fmt; `clippy --workspace --all-targets`; `cargo test --workspace -- --include-ignored`, which is what actually exercises the bumped server through the MockVta suites; `RUSTDOCFLAGS="-D warnings" cargo doc`; and `cargo deny check sources`, which the moved git rev has to keep passing. Signed-off-by: Glenn Gore <glenn.g@affinidi.com>
🛡️ AI Agentic Security Code Review1 AI-confirmed issue. Mandatory to check: 🔒 Security Code Review Report Details🛡️ Security Code Review Report — PR #263
🗺️ Scan CoverageModules scanned: 3 · with findings: 1 · files: 5 · findings: 1
Executive Summary
🔒 Security IssuesConfirmed Vulnerabilities (1)⚪ Sensitive private key material (admin_private_key_mb / private_key_multibase) handled as plain String rather than secret-wrapped type
Summary: Private key material for admin identities (admin_private_key_mb in setup_vta_actions.rs, private_key_multibase() in the e2e test) is passed into ClientIdentity::did_key(...) as an owned/cloned plain Rust String rather than a secrecy-wrapped type (the workspace already depends on the 📝 Description: If key material is leaked via logs, crash dumps, or swap files, an attacker gains the admin's ed25519 private key and can impersonate the admin DID to the VTA, forging Trust Tasks (agent registration, device registration, key rotation, context join) that grant them administrative control over the Verifiable Trust Architecture instance. 🧪 Proof of Concept: admin.admin_private_key_mb is cloned as a plain String and passed by value into the SDK constructor. Without a secret-wrapper type (e.g. secrecy::SecretString) the compiler will not zero the memory on drop, and any accidental Debug/logging of the ClientIdentity or the surrounding struct could leak the key value into logs. Vulnerable lines: 460, 480 🔎 Evidence: 💥 Impact: If key material is leaked via logs, crash dumps, or swap files, an attacker gains the admin's ed25519 private key and can impersonate the admin DID to the VTA, forging Trust Tasks (agent registration, device registration, key rotation, context join) that grant them administrative control over the Verifiable Trust Architecture instance. 🧭 Reachability:
⚖️ Triage Factors:
Attack scenario: An attacker with local memory or crash-dump access recovers the admin's plaintext-handled private key from setup_vta_actions.rs and forges Trust Tasks to the VTA. 🔧 Remediation:
Wrap the private key field in secrecy::SecretString (already a workspace dependency) so it is zeroed on drop and cannot be accidentally printed via Debug. Only expose the raw value at the point of use via expose_secret(). Vulnerable code: Secure code:
Generated by Agentic Sec — AI Security Validation Agent Details🛡️ Threat Model & Affect Analysis — PR #263
📋 Affect AnalysisChange SummaryBumps vta-sdk 0.31→0.32 and vta-service 0.22→0.23 (plus the associated VGI git-pin move) to pull in three documented upstream authentication/signing defect fixes (VTI #1184, #1192, #1193), and migrates two application/test call sites from a manual ClientIdentity struct literal to the new ClientIdentity::did_key() constructor so Trust-Task proof signing correctly derives a did:key verification method. Diff: +94 / -52 lines 🧩 Affected Components
📁 File ClassificationsCargo.toml
Cargo.lock
openvtc-core/Cargo.toml
openvtc-core/tests/mockvta_bootstrap_e2e.rs
openvtc/src/state_handler/setup_vta_actions.rs
🛡️ STRIDE Threat ModelNo STRIDE threats identified for this MR. 🍝 PASTA Threat ModelTechnical ScopeEntry Points (4): EP-001 FUNCTION_CALL openvtc-core/tests/mockvta_bootstrap_e2e.rs::bootstrap_creates_top_context_and_lists_webvh_server · EP-002 FUNCTION_CALL openvtc-core/tests/mockvta_bootstrap_e2e.rs::persona_did_webvh_mint_round_trips · EP-003 FUNCTION_CALL openvtc/src/state_handler/setup_vta_actions.rs::handle_vta_start_provision · EP-004 SDK_CONSTRUCTOR ClientIdentity::did_key(client_did, private_key_multibase, vta_did) No PASTA analysis available for this MR. Generated by Agentic Sec — Threat Model & Affect Analysis Agent 📊 Summary & findings
Confirmed (1)
|
Takes the VTI release cut by verifiable-trust-infrastructure#1187.
What it buys, all of it on paths this repo already uses
VTI #1184 + #1192 — one defect in two halves.
didcomm_transportandtsp_transportbuilt every client withidentity: None, so a dispatched Trust Task carried noissuer, norecipientand no proof. The VTA's dispatch spine refuses that asmalformedRequestover DIDComm and — because the TSP paths back-fill those two members — asproofRequiredover TSP. Same bug, two names, depending on transport. #1192 then stoppedaddress_trust_taskrewritingissuer/recipientafter signing, which had been turning a valid proof intoproofInvalidat the far end.Every Trust Task this repo dispatches — agent names, devices, keys, join — goes through those transports.
VTI #1193 lifts Trust-Task signing off
did:key. The signer derived the verification method as<did>#<multibase>, which only adid:keyhas, so a provisioneddid:webvhintegration could not sign any of the 210 proof-requiring tasks.VTI #1191 adds
device_heartbeat_named— what lets this install correct its owndisplayName, set once at registration and until now unchangeable. Taken here, used in the follow-up.Two upstream edges had to move first
vta-sdkis 0.x, so a requirement of"0.31"excludes 0.32: any consumer that keeps one ends up with two copies in the graph, and they don't unify.did-git-sign/vgi-core462032c(vta-sdk 0.31)d2c091d(vta-sdk 0.32)vta-service(MockVta dev-dep)trql-client(trust-registry)trust-tasks-rsrecords from the 0.6 → 0.9 move. Its siblings had to follow too: the versions cargo had locked also ask for vta-sdk 0.31, so updating only the two named crates left 0.31.1 in the tree.trql-clientdoesn't depend onvta-sdkat all — its dependencies aretrust-tasks-rs, the TDK and the messaging SDK. (Thevta-sdk = "0.31"line in that repo is its workspace table, used by other crates there.) Nothing else moves either: vta-sdk 0.32 keeps trust-tasks-rs 0.17, affinidi-tdk 0.10 and affinidi-messaging-sdk 0.21.The one source change
ClientIdentitygainedverification_method(#1193), so the two sites that built it as a struct literal now useClientIdentity::did_key.Not purely mechanical: that constructor is for the one DID method whose key is its identifier, which is exactly what both sites have — provisioning mints the admin as a
did:key, and the bootstrap e2e assertsadmin_did.starts_with("did:key:"). The assumption now sits in the call instead of being implicit in a field that happens to be absent.Verification
cargo tree -d -e normal,build,dev— novta-sdk,trust-tasks-rs,affinidi-tdk,affinidi-messaging-sdk,vti-commonorvta-serviceduplicate. Onevta-sdk v0.32.0.cargo test --workspace -- --include-ignored— this is what actually exercises the bumped server, through the MockVta suites; a greenTestjob alone would say nothing about them.clippy --workspace --all-targets,RUSTDOCFLAGS="-D warnings" cargo doc, andcargo deny check sources(which the moved git rev has to keep passing).Still to unwind
The
[patch.crates-io]block stays until VGI publishes 0.4.7 — now on vta-sdk 0.32 — at which point it is deleted and the floor inopenvtc/Cargo.tomlnames that release. VGI #33 can't publish while it pinstrql-clientby git (cargo publish rejects git deps), which waits on affinidi-trust-registry-rs#128. Unchanged by this PR; recorded so it doesn't get lost.Pre-merge checklist