Comprehensive code audit

Audit Report

Security audit, spec compliance verification, test coverage analysis, and code quality review across the entire KYA Daml codebase. Two issues found and fixed. No critical vulnerabilities.

Date February 2026
Daml SDK 3.4.0
Modules 5 source + 3 test
Lines of code 1,597 total

13

of 15 checks

Security — Pass

96%

76 of 79

Spec compliance

38

Daml Script tests

Test coverage

2

issues fixed

Remediated findings

Authorization, access control,
and input validation

Every Daml template, choice, and verification function was reviewed for authorization gaps, missing validations, time-of-check/time-of-use issues, and data integrity problems. 28 individual checks were performed.

Findings requiring action

ID Finding Module Status
SEC-014 rewardSplit had no validation — values >1.0 or negative would produce invalid reward weights in FeaturedAppActivityMarker

Fixed: added ensure rewardSplit >= 0.0 && rewardSplit <= 1.0 to KyaSettlementHook template

Settlement.daml Fixed
SEC-008 agentParty on verification request was not validated against agentCredential.holder — proof could attribute verification to wrong agent

Fixed: added assertMsg checking holder == agentParty in KyaVerificationRequest_Verify

Application.daml Fixed
SEC-028 principalParty on proof is derived from agentCredential.issuer rather than principalCredential.holder

Noted: the current derivation is correct for the two-hop delegation model where the principal issues the agent credential. Documented for future review if the delegation model changes.

Application.daml Noted

Passing checks

ID Check Module Status
SEC-001 Credential signatory requires both issuer and holder Credential.daml Pass
SEC-002 KyaVerificationRequest signatory is requester only Application.daml Pass
SEC-003 KyaVerificationRequest_Verify controlled by kyaProvider Application.daml Pass
SEC-004 KyaVerificationProof signatory is kyaProvider Application.daml Pass
SEC-005 KyaVerificationProof_Consume controlled by verifier Application.daml Pass
SEC-006 Proof expiry checked on consumption Application.daml Pass
SEC-007 Credential validFrom/validUntil checked in verification Verifier.daml Pass
SEC-009 Schema version validated during verification Verifier.daml Pass
SEC-010 Transaction value checked against maxTransactionValue Verifier.daml Pass
SEC-011 Required capability checked against credential capabilities list Verifier.daml Pass
SEC-012 Delegation chain validates issuer is in trusted issuers list Verifier.daml Pass
SEC-013 Settlement hook requires bilateral signatures (kyaProvider + integratingApp) Settlement.daml Pass
SEC-015 KyaSettlementHook_Execute is nonconsuming (reusable) Settlement.daml Pass

Warnings — acceptable risk

ID Warning Status
SEC-016 proofValiditySeconds has no upper bound — KYA provider is trusted, and excessively long proofs are an operational concern not a security one Warn
SEC-017 Claim values are all Text — no type enforcement at the Daml level. Schema validation happens in verifier functions. Warn
SEC-018 parseDecimalText is partial — returns None on failure which is handled correctly by callers Warn
SEC-019 No on-chain revocation mechanism — revocation is handled by Canton's credential lifecycle (archive) Warn
SEC-020 Agent can hold multiple credentials simultaneously — by design, allows credential rotation Warn

Every requirement in spec.md
mapped to code

76

Implemented

1

N/A (off-ledger)

2

Deferred (CIP doc)

Coverage by category

15 / 15

Credential Schema

All kya: prefixed claim properties defined in Schema.daml with constants and parsing functions

12 / 12

Agent Verification

Schema version, validity, capabilities, transaction limits, agent identity extraction

10 / 10

Delegation Chain

Two-hop chain validation, trusted issuer check, principal credential ID matching

8 / 8

Verification Request

Request creation, provider-controlled verify choice, proof generation with all fields

9 / 9

Verification Proof

On-ledger proof with expiry, verifier-controlled consumption, all agent metadata

7 / 7

Settlement Hook

Bilateral agreement, nonconsuming execute, proof consumption, reward split with beneficiaries

6 / 6

Result Types

VerificationResult, ChainResult with isValid, failureReason, and extracted metadata

5 / 5

Data Parsing

findClaim, parseDecimalText, splitOn for capabilities, currentSchemaVersion constant

4 / 6

Integration & CIP

Path A and B integration patterns implemented. CIP document and governance proposal deferred to formal submission phase.

38 Daml Script tests
across three test modules

KyaTest.daml

20

Verifier & schema tests

KyaApplicationTest.daml

8

Application layer tests

KyaSettlementTest.daml

10

Settlement hook tests

Identified gaps

24 test gaps cataloged. These represent edge cases and negative paths not yet covered. 6 are high priority.

Structure, naming,
and complexity

5

Source modules

595

Source LOC

3

Test modules

1,002

Test LOC

Naming Consistent kya: prefix for all claim properties. Template and choice names follow Daml conventions (PascalCase with underscore-separated choice names).
Imports All imports are explicit with listed symbols. No wildcard imports. Clean dependency graph: Types ← Schema ← Verifier ← Application ← Settlement.
Complexity No function exceeds 30 lines. Cyclomatic complexity is low across all modules. Verification logic is pure (no ledger effects) and composed from small helpers.
Dead code Two unused helper functions identified: hasClaim and parseAgentClass in Schema.daml. Candidates for removal.
Separation Clean layer separation: Types (data) → Schema (constants) → Verifier (pure logic) → Application (on-ledger) → Settlement (reward integration). Each layer depends only on the ones below it.

Recommended follow-ups

01 Install Daml SDK 3.4 and run the full test suite
Validate all 38 tests pass with the actual compiler
02 Add tests for the 6 high-priority gaps
Expired proof consumption, boundary values, future-dated credentials, empty capabilities
03 Integration test KyaSettlementHook_Execute on DevNet
Requires splice-api-featured-app-v1.dar and a running Canton participant
04 Remove dead code: hasClaim and parseAgentClass
Or add tests if they are intended for future use
05 Monitor SEC-028 (principalParty derivation) if delegation model evolves
Current behavior is correct for the two-hop model

Review the code yourself

View on GitHub Back to home