contract audit proposal#168
Conversation
meiersi-da
left a comment
There was a problem hiding this comment.
Thanks a lot. This is a good first stab at the problem.
I think the biggest missing item is support for computing the target vetting state of wallet providers. See my comments.
It might make sense to call out their computation in the intro, and consider the main goal to compute vetting states that allow as many benign apps to be used by users of as many wallet providers as possible, while minimizing the chance of users being exposed to a malicious app.
|
|
||
| ## Abstract | ||
|
|
||
| This CIP proposes a standardized protocol for secure interaction between three parties in the Daml application ecosystem: **AppProviders**, **WalletProviders**, and **SecurityAuditors**. The standard defines how AppProviders publish Daml packages (.dar files) with cryptographically verifiable build metadata, how they request security audits from independent SecurityAuditors, and how WalletProviders can discover and verify audit results to make informed security decisions before integrating third-party packages. |
There was a problem hiding this comment.
| This CIP proposes a standardized protocol for secure interaction between three parties in the Daml application ecosystem: **AppProviders**, **WalletProviders**, and **SecurityAuditors**. The standard defines how AppProviders publish Daml packages (.dar files) with cryptographically verifiable build metadata, how they request security audits from independent SecurityAuditors, and how WalletProviders can discover and verify audit results to make informed security decisions before integrating third-party packages. | |
| This CIP proposes a standardized protocol for secure interaction between three parties in the Daml application ecosystem: **App Providers**, **Wallet Providers**, and **Security Auditors**. The standard defines how AppProviders publish Daml packages (.dar files) with cryptographically verifiable build metadata, how they request security audits from independent SecurityAuditors, and how WalletProviders can discover and verify audit results to make informed security decisions before integrating third-party packages. |
We usually don't use camel case for roles in flow-text. See https://github.com/canton-foundation/cips/blob/main/cip-0056/cip-0056.md#overview for prior art on defining roles.
| #### Parties | ||
|
|
||
| - **AppProvider**: An organization or individual developing Daml applications and publishing Daml packages (.dar files) | ||
| - **WalletProvider**: A service provider managing digital assets on behalf of users, integrating third-party Daml applications |
There was a problem hiding this comment.
| - **WalletProvider**: A service provider managing digital assets on behalf of users, integrating third-party Daml applications | |
| - **Validator Node Provider**: A service provider providing users with access t to a Canton Network validator node hosting their parties. |
There was a problem hiding this comment.
Please check all text wrt "managing digital assets", as that is something reserved to properly licensed asset managers. Neither wallet providers nor node provider ever do that; and they do not want to do that as that requires special licenses in most jurisdictions.
|
|
||
| #### Package Metadata Format | ||
|
|
||
| The `metadata.json` file for each package version follows this JSON schema: |
There was a problem hiding this comment.
consider using JSON schema to specify the schema itself, as done by Ledger for ClearSign here: https://github.com/LedgerHQ/clear-signing-erc7730-registry/tree/master/specs
| app-provider-repo/ | ||
| ├── README.md | ||
| ├── packages/ | ||
| │ ├── v1.0.0/ |
There was a problem hiding this comment.
use full package name, e.g., splice-amulet-0.1.16 to avoid conflicts.
Also support a _<pkgId> suffix for the case where an app provider did accidentally publish multiple packages for the same version and needs to publish metadata about both of them.
There was a problem hiding this comment.
Consider making this the default format so that we never have a conflict, but still get the good human readability.
| ├── audits.json | ||
| └── build-configs/ | ||
| ├── v1.0.0/ | ||
| │ └── build-config.json |
There was a problem hiding this comment.
why are build configs separate? seems like extra work to maintain the copy of the structure for what could have just been another file in the same directory.
| "severity_rating": "none", | ||
| "expiration_date": "2027-02-27T00:00:00Z" | ||
| } | ||
| ] |
There was a problem hiding this comment.
Why not inline the audits as well into the package itself to avoid repeating the same structure?
| | 1.0.0 | SecurityAuditorCompany | 2026-02-20 | ✓ Passed | [Audit Report](https://github.com/auditor/audit-reports/blob/main/reports/app-provider-name/1.0.0/audit-report.json) | | ||
| | 1.1.0 | SecurityAuditorCompany | 2026-02-26 | ✓ Passed | [Audit Report](https://github.com/auditor/audit-reports/blob/main/reports/app-provider-name/1.1.0/audit-report.json) | | ||
| | 1.1.0 | AnotherAuditor | 2026-02-25 | ✓ Passed | [Audit Report](https://github.com/another-auditor/audits/blob/main/reports/app-provider/1.1.0/audit.json) | | ||
|
|
There was a problem hiding this comment.
What about exposing this as a TypeScript script that produces the summary from the information in the packages/ dir?
| "authorization_logic", | ||
| "party_confidentiality", | ||
| "contract_integrity", | ||
| "dependency_safety", | ||
| "daml_best_practices" |
There was a problem hiding this comment.
Where are these properties defined?
| "decision_notes": "string" | ||
| } | ||
| ] | ||
| } |
There was a problem hiding this comment.
Why do we need a separate process for this?
I was thinking that a wallet provider would
- define the app repositories for apps to integrate, using git submodules
- define the auditor repositories to use, using git submodules
- a trust policy that defines how to compute the target vetting state on their nodes from the data in the above repositories
-
where needed they list themselves as their own auditor
-
justification for changes comes as part of git commits / PRs and does not need to reflected into the repo itself
-
the repo provides automation to compute the commands to apply to a node to make it ready to run an app, which typically requires two steps
- which .dars to upload using https://github.com/digital-asset/canton/blob/298886b8b27077bbef52a8c6811b72cfcd47d5d6/community/ledger/ledger-json-api/src/test/resources/json-api-docs/openapi.yaml#L376-L385 with
vetAllPackages = false - how to set the packag vetting state using https://github.com/digital-asset/canton/blob/298886b8b27077bbef52a8c6811b72cfcd47d5d6/community/ledger/ledger-json-api/src/test/resources/json-api-docs/openapi.yaml#L601-L608. The typical structure there I expect is to do in one pass: unvet existing packages of an app, vet currently required packages of an app
- which .dars to upload using https://github.com/digital-asset/canton/blob/298886b8b27077bbef52a8c6811b72cfcd47d5d6/community/ledger/ledger-json-api/src/test/resources/json-api-docs/openapi.yaml#L376-L385 with
-
On the last point, I believe we are missing one crucial part of metadata in the App Provider's repos: which vetting state to use for their apps. I'd suggest to address this by introducing a top-level directory that lists the apps, and then within that directory define the packages that are contributed by this app.
Here's a sketch how that would look like for the apps contributed by Splice:
canton-coin/
packages/
splice-util-0.1.5_5a58024e2cc488ca9e0c952ec7ef41da3a1ed0a78ba23bacd819e5b30afb5546/
splice-amulet-0.1.16_c208d7ead1e4e9b610fc2054d0bf00716144ad444011bce0b02dcd6cd0cb8a23/
...
vetting-states/
mainnet.json
devnet.json
testnet.json
global-sync-governance/
packages/
splice-dso-governance-0.1.22_5c28530209b9ab37c5f187132cd826709bb18b0efe28411488ab750870414738/
vetting-states/
mainnet.json
testnet.json
devnet.json
...
The ... at the bottom refers to like app definitions for the token standard APIs and other packages in in https://github.com/hyperledger-labs/splice/blob/main/daml/dars.lock
There was a problem hiding this comment.
I would then also like to see a script for computing the target vetting state as part of the reference implementation of this CIP. The target vetting state will need to be computed in a single pass to take into account dependencies.
I'd probably even consider that wallet providers will want to check-in the vetting state command to use, as that gives a great way on the diff of adding/removing/updating apps.
|
|
||
| We do not require authentication on audit result URLs because: | ||
| - All data is expected to be public | ||
| - URLs are hard to guess (based on package hashes and identifiers) |
There was a problem hiding this comment.
package hashes are part of the publicly available topology state. So everybody sees all package hashes.
The question is though why the mechanisms of git repo access controls are not sufficient.
| │ │ ├── package.dar | ||
| │ │ └── metadata.json | ||
| │ └── ... | ||
| ├── audits.json |
There was a problem hiding this comment.
suggest the audits.json and build-configs should be under the specific version of the package
that way it can be retrieved directly -- and it is also clear which applies to which version
So
app-provider-repo/
├── README.md
├── packages/
│ ├── v1.0.0/
│ │ ├── package.dar
│ │ └── metadata.json
│ │ └── audits.json
│ │ └── build-configs/
│ │ └──── ...
│ ├── v1.1.0/
│ │ ├── package.dar
│ │ └── metadata.json
│ │ └── audits.json
│ │ └── build-configs/
│ │ └──── ...
Also this structure should ideally be something that can be followed for OCI
So we can retrieve an artifact with
oci:///dars/app-providers-repo:1.0.0
and within the layer of that oci artifact it has structure
│ │ ├── package.dar
│ │ └── metadata.json
│ │ └── audits.json
│ │ └── build-configs/
The metadata fields in metadata.json could also become OCI annotations to be able to query / filter on the desired fields to find the artifacts without having to download them
For instance -- "return me any dar that has been audited by auditor X" or "return me only dar versions that have been audited", etc
{
"org.opencontainers.image.title": "my-artifact",
"org.opencontainers.image.description": "Example OCI artifact with security metadata",
"org.opencontainers.image.version": "1.0.0",
"org.opencontainers.image.licenses": "Apache-2.0",
"org.opencontainers.image.vendor": "Your Company Name",
"org.opencontainers.image.authors": "security-team@yourcompany.com",
"com.security.properties": "{\"daml_stdlib_version\":\"2.5.0\",\"uses_external_bindings\":false,\"uses_party_operations\":true,\"uses_authorization\":true,\"uses_contract_fetch\":true,\"notable_modules\":[{\"module_name\":\"App.Security.Authorization\",\"description\":\"Custom authorization logic\"}]}",
"com.licenses.detail": "{\"package_license\":\"Apache-2.0\",\"dependency_licenses\":[{\"package_name\":\"string\",\"license\":\"Apache-2.0\"}]}"
}
|
|
||
| #### Problem Statement | ||
|
|
||
| As the Daml ecosystem grows, WalletProviders need a reliable mechanism to: |
There was a problem hiding this comment.
As per Simon's comment above, we should replace WalletProviders with Validator Node Operators / Providers throughout this document.
| 2. Verify the integrity and authenticity of security audit reports | ||
| 3. Make informed decisions about package integration based on transparent audit results | ||
| 4. Establish trust without performing redundant security validations | ||
|
|
There was a problem hiding this comment.
I'd add a fifth point here:
"Understand version compatibility between composed applications"
| "audit_status": "passed", | ||
| "severity_rating": "none", | ||
| "expiration_date": "2027-02-27T00:00:00Z" | ||
| } |
There was a problem hiding this comment.
package_hash should also be included here so that the node operator can confirm the exact package which was vetted.
davidrichards-da
left a comment
There was a problem hiding this comment.
Yuri, I've made a suggestion based on the conversations that I've had with wallet providers.
| - SecurityAuditors can publish results in verifiable repositories | ||
| - WalletProviders can discover and verify audits without conducting redundant validations | ||
| - All parties operate with cryptographic verification and transparency | ||
|
|
There was a problem hiding this comment.
| In recent conversations between Digital Asset and wallet providers (both reatil and enterprise) who host their own validator nodes, the following feedback was consistently communicated: | |
| **Security Risks and Malicious Code** | |
| Node operators are highly concerned about uploading malicious DAR files. There are two primary concerns here: | |
| 1. Risk to their validator and environment: They fear potential exploits and the risk that a DAR could break their validator. | |
| 2. Risk to their end-users: unknowingly signing malicious transactions. | |
| Node operators also want to ensure that source code which has been vetted equates exactly to the DAR files uploaded to their nodes. | |
| **Version Control, Composability & Operational Overhead** | |
| There is anxiety surrounding the continual maintenance and testing required for initial DARs and subsequent new versions. Providers specifically called out "version hell", the sparse matrix of version compatibility for composability, and how dependencies are handled and enforced. | |
| Providers are concerned about the operational effort required to load DARs onto validators. They’d like this as automated as possible. |
No description provided.