Skip to content

chore(deps): take vta-sdk 0.32 and vta-service 0.23 - #263

Merged
stormer78 merged 1 commit into
mainfrom
chore/vta-sdk-0.32
Aug 29, 2026
Merged

chore(deps): take vta-sdk 0.32 and vta-service 0.23#263
stormer78 merged 1 commit into
mainfrom
chore/vta-sdk-0.32

Conversation

@stormer78

Copy link
Copy Markdown
Contributor

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_transport and tsp_transport built every client with identity: None, so a dispatched Trust Task carried no issuer, no recipient and no proof. The VTA's dispatch spine refuses that 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 — what lets this install correct its own displayName, set once at registration and until now unchangeable. Taken here, used in the follow-up.

Two upstream edges had to move first

vta-sdk is 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.

Edge Was Now
did-git-sign / vgi-core patched to VGI #33 @ 462032c (vta-sdk 0.31) patched to VGI #33 @ d2c091d (vta-sdk 0.32)
vta-service (MockVta dev-dep) 0.22, built on vta-sdk 0.31 0.23
its eleven siblings vta-audit 0.3.0, vta-keys 0.4.0, … 0.3.1, 0.4.1, …
trql-client (trust-registry) pinned rev unchanged
  • did-git-sign 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. The VGI side is verifiable-git-infrastructure#33, which now carries the 0.32 bump (manifest + lockfile, no source change, green on its own pipeline).
  • vta-service matters because leaving it at 0.22 splits the dev graph while the shipped one looks clean — the exact shape the note above trust-tasks-rs records 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.
  • trust-registry does not need a commit. trql-client doesn't depend on vta-sdk at all — its dependencies are trust-tasks-rs, the TDK and the messaging SDK. (The vta-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

ClientIdentity gained verification_method (#1193), so the two sites that built it as a struct literal now use ClientIdentity::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 asserts admin_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 — no vta-sdk, trust-tasks-rs, affinidi-tdk, affinidi-messaging-sdk, vti-common or vta-service duplicate. One vta-sdk v0.32.0.
  • cargo test --workspace -- --include-ignored — this is what actually exercises the bumped server, through the MockVta suites; a green Test job alone would say nothing about them.
  • fmt, clippy --workspace --all-targets, RUSTDOCFLAGS="-D warnings" cargo doc, and cargo 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 in openvtc/Cargo.toml names that release. VGI #33 can't publish while it pins trql-client by 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

- [x] No new reqwest::Client::new() / bare fetch(); all clients have finite timeouts (R1.2) — no new clients
- [x] No lock held across a network await (R1.3)
- [x] No local state committed before its remote effect, or the flow is resumable with an idempotency key (R2.1) — no flow changes
- [x] Every retry is bounded + backed off; non-idempotent ops are not blind-retried (R1.4) — unchanged
- [x] Accept/poll/listen loops survive transient errors (R1.5) — unchanged
- [x] Acks/deletes happen only after durable handoff (R1.6) — unchanged
- [x] New/changed wire types: camelCase, deny_unknown_fields where security-relevant, schema registered, all consumers (incl. JS) updated (R3.*) — none authored here; the point of the bump is that the SDK now emits the envelope members the spec requires (R3.6: verified against the current services, which is what the MockVta suites run)
- [x] Config absence = most restrictive; fail-closed if enforcement can't start (R5.*) — n/a
- [x] Logs/status claim only what was verified; background-job failures are surfaced (R6.*) — unchanged
- [x] "Process dies on the next line" answered for every mutation touched (R2.1) — no mutations
- [x] Deviations from this guide flagged explicitly with rule numbers — none. The git-patched dependency is pre-existing and documented in the manifest with its unwind condition

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>
@stormer78
stormer78 requested a review from a team as a code owner August 29, 2026 02:13
@stormer78
stormer78 merged commit ec45011 into main Aug 29, 2026
14 checks passed
@stormer78
stormer78 deleted the chore/vta-sdk-0.32 branch August 29, 2026 02:21
@affinidi-appsecurity-bot

Copy link
Copy Markdown

🛡️ AI Agentic Security Code Review

1 AI-confirmed issue.

Mandatory to check: 🔒 Security Code Review Report

Details

🛡️ Security Code Review Report — PR #263

Field Value
Repository OpenVTC/openvtc
Branch chore/vta-sdk-0.32main
Validated 2026-08-29
Scan ID c64ff1bb
Validator AI Security Validation Agent

🗺️ Scan Coverage

Modules scanned: 3 · with findings: 1 · files: 5 · findings: 1

Module Files scanned Findings
(root) 2 0
openvtc-core 2 0
openvtc 1 1

Executive Summary

Category Confirmed Must-Review-By-Human
Security Issues 1 0

🔒 Security Issues

Confirmed Vulnerabilities (1)

⚪ Sensitive private key material (admin_private_key_mb / private_key_multibase) handled as plain String rather than secret-wrapped type

Field Detail
Severity INFORMATIONAL
Location openvtc/src/state_handler/setup_vta_actions.rs:460
Finding ID github_pr-19a6952a8cb3
CWE CWE-316, CWE-522, CWE-215
OWASP A02:2021 - Cryptographic Failures, A07:2021 - Identification and Authentication Failures
MITRE ATT&CK T1552.001 - Unsecured Credentials: Credentials In Files, T1555 - Credentials from Password Stores
CAPEC CAPEC-37 - Retrieve Embedded Sensitive Data, CAPEC-116 - Excavation
DREAD 4.6
Reachability 🔴 Reachable
Exploit Maturity conceptual
Detection Source skill_scan

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 secrecy crate elsewhere per Cargo.toml). This increases the risk of key material persisting in memory, being captured in crash dumps, or accidentally logged via a Debug derive.

📝 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.

// `did_key`, not a struct literal: vta-sdk 0.32 lifted
// Trust-Task signing off `did:key` (VTI #1193) ...
VtaClient::authenticated(
    &vta_url,
    ClientIdentity::did_key(
        admin.admin_did.clone(),
        admin.admin_private_key_mb.clone(),
        vta_did.clone(),
    ),
    token_result.access_token,
)
.await

Vulnerable lines: 460, 480

🔎 Evidence: openvtc/src/state_handler/setup_vta_actions.rs:460

VtaClient::authenticated(
    &vta_url,
    ClientIdentity::did_key(
        admin.admin_did.clone(),
        admin.admin_private_key_mb.clone(),
        vta_did.clone(),
    ),
    token_result.access_token,
)
.await

💥 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:

  • Network exposure: internal
  • Auth barrier: basic
  • Attack path: EP-003 (handle_vta_start_provision) → admin.admin_private_key_mb.clone() → ClientIdentity::did_key(...) at setup_vta_actions.rs:~475 → in-memory signing key material

⚖️ Triage Factors:

Factor Value
Fixable ✅ Yes
Exploitability low
Business impact high
Public exploit None known
Environment unknown

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:

⚠️ AI-generated fix. Review, test in staging, and validate against your architecture before applying.

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:

ClientIdentity::did_key(
    admin.admin_did.clone(),
    admin.admin_private_key_mb.clone(),
    vta_did.clone(),
)

Secure code:

use secrecy::{ExposeSecret, SecretString};

// admin.admin_private_key_mb should be typed as SecretString upstream
ClientIdentity::did_key(
    admin.admin_did.clone(),
    admin.admin_private_key_mb.expose_secret().to_string(),
    vta_did.clone(),
)
// AND ensure ClientIdentity / any struct holding the key implements
// a redacted Debug (e.g. via #[derive(Debug)] excluded or custom impl)
// so it never leaks in logs.

🔍 Validation Log

  • Verdict: ✅ Confirmed True Positive
  • Confidence: 75%
  • AI Validation Evidence: EVIDENCE FOUND: In openvtc/src/state_handler/setup_vta_actions.rs (line ~460) the private key is threaded through as a plain String: ClientIdentity::did_key(admin.admin_did.clone(), admin.admin_private_key_mb.clone(), vta_did.clone()) where admin.admin_private_key_mb is typed as a plain field (see mockvta_bootstrap_e2e.rs test fixture: admin_private_key_mb: "zAdminPrivKeyMultibase".to_string()), and in config.rs the same field is wrapped only at the point of storage into KeyBackend::Vta { credential_private_key: SecretString::new(admin.admin_private_key_mb.clone().into()), ... }, confirming the source type (AdminCredentialReply.admin_private_key_mb) is a bare String, not a SecretString/zeroizing type, and is .clone()-d repeatedly in plaintext through connect_tsp/connect_didcomm/did_key calls (&admin.admin_private_key_mb at connect_tsp/connect_didcomm call sites, and admin.admin_private_key_mb.clone() at the did_key call). EVIDENCE NOT FOUND: No secret-wrapping (SecretString/SecretBox/Zeroizing) is applied to admin_private_key_mb before or during these clones/passes; config.rs shows secrecy types ARE used elsewhere (SecretString, SecretBox, secrecy::ExposeSecret) in the same crate, confirming the pattern exists but was not applied to this field at its point of use in setup_vta_actions.rs. CHANGED VS PRE-EXISTING: setup_vta_actions.rs is directly quoted in source_files with the exact flagged code block (lines around 460, the VtaClient::authenticated(...ClientIdentity::did_key(admin.admin_private_key_mb.clone()...)) call), and comments in the file itself reference vta-sdk 0.32 changes (vta-sdk 0.32 lifted Trust-Task signing off did:key (VTI #1193)) consistent with the MR title chore/vta-sdk-0.32, so this is CHANGED code introduced/modified by this MR. VERDICT JUSTIFICATION: The finding is a real, low-severity hygiene issue (informational/low CWE-316/522/215) — plaintext secret material handled as String rather than a secret-wrapped type, increasing risk of exposure via memory dumps, Debug/Display formatting, or accidental logging; the code is quoted directly confirming the pattern, so this is validated at informational severity, matching the reported severity.
  • Validation Effort: Cloned repo, read source file, verified vulnerability claim against actual code. Confirmed exploitability in scan context.


Generated by Agentic Sec — AI Security Validation Agent
This report includes full scan data + AI validation evidence. Feed to engineering copilots for automated fix deployment.

Complementary: 🛡️ **Threat Model & Affect Analysis**
Details

🛡️ Threat Model & Affect Analysis — PR #263

Field Value
Repository OpenVTC/openvtc
Branch chore/vta-sdk-0.32main
Generated 2026-08-29

ℹ️ This report contains theoretical threats and impact analysis for the MR.
Unlike the Security Code Review Report (which contains confirmed, materialised issues),
these are potential risks that may or may not be exploitable. Use this for defence-in-depth planning.


📋 Affect Analysis

Change Summary

Bumps 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
Types: dependency_upgrade, security_fix, refactor, supply_chain

🧩 Affected Components

Component Impact Change What Changed
VTA Client Authentication / Identity Construction high modified All ClientIdentity construction call sites in the analyzed diff migrated from a raw struct literal (client_did, private_key_multibase, vta_d
Trust Infrastructure Dependency Family (vta-/vti-) medium modified Coordinated minor/patch version bump across vta-sdk, vta-service, vta-audit, vta-backup, vta-cli-common, vta-config, vta-keys, vta-keyspaces
Supply-chain Git Pin (verifiable-git-infrastructure) medium modified did-git-sign and vgi-core [patch.crates-io] git rev moved from 462032cfd4adcec9bc00ee957e2e60b7e42c7dac to d2c091d795168357d8bf3d1c4fffce645

📁 File Classifications

Cargo.toml

  • Type: config

Cargo.lock

  • Type: config

openvtc-core/Cargo.toml

  • Type: config

openvtc-core/tests/mockvta_bootstrap_e2e.rs

  • Type: test

openvtc/src/state_handler/setup_vta_actions.rs

  • Type: security

🛡️ STRIDE Threat Model

No STRIDE threats identified for this MR.


🍝 PASTA Threat Model

Technical Scope

Entry 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 ⚠️ Must-Review-By-Human
1 0

Confirmed (1)

  • Sensitive private key material (admin_private_key_mb / private_key_multibase) handled as plain String rather than secret-wrapped type

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants