Skip to content

contract audit proposal#168

Open
pixelplex wants to merge 5 commits into
canton-foundation:mainfrom
pixelplex:contracts_audit_proposal
Open

contract audit proposal#168
pixelplex wants to merge 5 commits into
canton-foundation:mainfrom
pixelplex:contracts_audit_proposal

Conversation

@pixelplex
Copy link
Copy Markdown

No description provided.

Copy link
Copy Markdown
Contributor

@meiersi-da meiersi-da left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- **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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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/
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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"
}
]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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) |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about exposing this as a TypeScript script that produces the summary from the information in the packages/ dir?

Comment on lines +265 to +269
"authorization_logic",
"party_confidentiality",
"contract_integrity",
"dependency_safety",
"daml_best_practices"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where are these properties defined?

"decision_notes": "string"
}
]
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need a separate process for this?

I was thinking that a wallet provider would

  1. define the app repositories for apps to integrate, using git submodules
  2. define the auditor repositories to use, using git submodules
  3. a trust policy that defines how to compute the target vetting state on their nodes from the data in the above repositories

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Copy link
Copy Markdown

@dasormeter dasormeter Mar 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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"
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

package_hash should also be included here so that the node operator can confirm the exact package which was vetted.

Copy link
Copy Markdown
Contributor

@davidrichards-da davidrichards-da left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@davidrichards-da: note that version hell should go away with packages moving away from depending on other app's templates directly and only compose via interfaces.

Copy link
Copy Markdown

@jonathanreedmevs jonathanreedmevs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall looks great. I think language surrounding things such as security_properties_to_verify needs to be strengthened throughout

"organization": "string",
"repository_url": "https://github.com/org/repo"
},
"package_information": {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The CIP appears to strongly bind audits to exact package hashes/package IDs. How are minor or operationally trivial upgrades expected to be handled for live Featured Apps? For example, adding a read-only function would still produce a new package hash and invalidate the existing audit linkage. Is a full re-audit expected for every package change, or should the standard support lighter-weight mechanisms such as delta reviews, audit extensions, or auditor attestations that a previous audit substantially still applies?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right now, a basic audit needs to be done on every change to a package, as each of them could in principle introduce a choice that abuses an existing delegation of a user's authority.

I would expect that audit though to be done in a delta form of new sources against the previously audited sources.

],
"dependency_analysis": {
"total_dependencies": 5,
"dependencies_reviewed": [
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may help to clarify what is meant by dependency statuses. In practice, many audit reports only list the dependencies and note observed risks or notable characteristics, rather than making strong security assertions about whether a dependency is “approved.” This distinction seems especially important for community-maintained or widely adopted third-party libraries, where an auditor may be comfortable documenting its usage without wanting to formally endorse the dependency. Some additional guidance or softer terminology here may better reflect an auditor's dependency analysis.

"evidence_url": "https://github.com/auditor/audit-reports/blob/main/reports/app-provider/1.0.0/evidence/finding-F001.md"
}
],
"positives": [
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels like a new ask of audit firms that is not normally incorporated into our existing audit processes. I anticipate it being left empty by most firms as it produces overhead to report delivery.

That being said in my experience any positives regarding a specific project would be mentioned in the executive summary of the report.

"risk_assessment": "string",
"remediation": "string",
"remediation_status": "open|in_progress|resolved|accepted_risk",
"evidence_url": "https://github.com/auditor/audit-reports/blob/main/reports/app-provider/1.0.0/evidence/finding-F001.md"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm unclear on what should be contained in evidence_url and am worried that it may be redundant on what is already present in findings.description

│ │ │ ├── audit-report.json
│ │ │ ├── detailed-findings.md
│ │ │ └── evidence/
│ │ │ ├── code-sample-1.daml
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is unclear and could be redundant with what is already present in the report.

Copy link
Copy Markdown
Contributor

@meiersi-da meiersi-da left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this second iteration. I've focused my review on the CIP draft.

Overall I think it contains most of the elements required for a first solution to the problem. However, it also contains quite a few pieces whose role in solving the key problem (see my comments) is not (yet) clear to me.

For standards, I'd dare say that "less is more". So I'd appreciate if you could have a look at my comments and the CIP text itself, and see what content can be culled without impacting the CIP's fitness for purpose.

Happy to make another pass once you've done so.


## Abstract

This CIP proposes a standardized protocol for secure interaction between three parties in the Daml application ecosystem: **App Providers**, **Validator Node Providers**, and **Security Auditors**. The standard defines how App Providers publish Daml packages (.dar files) with cryptographically verifiable build metadata, how they request security audits from independent Security Auditors, and how Validator Node Providers can discover and verify audit results to make informed security decisions before integrating third-party packages.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
This CIP proposes a standardized protocol for secure interaction between three parties in the Daml application ecosystem: **App Providers**, **Validator Node Providers**, and **Security Auditors**. The standard defines how App Providers publish Daml packages (.dar files) with cryptographically verifiable build metadata, how they request security audits from independent Security Auditors, and how Validator Node Providers 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**, **Validator Node Providers**, and **Security Auditors**. The standard defines how App Providers publish Daml packages (.dar files) with cryptographically verifiable build metadata, how they request security audits from independent Security Auditors, and how Validator Node Providers can discover and verify audit results to make informed security decisions before deploying third-party packages on their nodes.

- **Security Auditor**: An independent security firm or team validating the security properties of Daml packages

#### Problem Statement

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To me the core problem is how to ensure that:

  1. app users can safely use all the applications they would like to use
  2. app providers can easily roll-out upgrades to their applications

We can the observe that validator node operators take the role of shielding app users from the technical challenge of determining what app upgrades to accept when. And for validator node operators to do that efficiently and effectively, they need information from both app providers and security auditors.

So with that perspective, I'd suggest:

  1. add "app user" to the parties list above
  2. review the list of properties below, as to whether they are really required for validator node operators to make good decisions as to what apps and app upgrades to deploy on their nodes.

App Providers benefit from:
1. Clear specification of what information to provide for auditing
2. Decentralized publication of audit results
3. Reuse of existing audits across multiple Validator Node Providers
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm missing the aspect of low friction roll-out of apps and their upgrades to a wide user-base here. To me that's the most important aspect.

app-provider-repo/
├── README.md
├── apps/
│ ├── canton-coin/
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like an example, but above it reads like this is mandatory structure.

"public_key_id": "string",
"repository_url": "https://github.com/org/repo"
},
"package_hash": {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this the hash of the .dar file or the package-id of the .dalf files in there?

- 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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@davidrichards-da: note that version hell should go away with packages moving away from depending on other app's templates directly and only compose via interfaces.

#### Why Git-based Publishing

Git provides:
- **Cryptographic verification** via commit signatures
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Who verifies these signatures and where does this verification happen?

An implementation of this standard should include:

1. **App Provider tooling**:
- CLI tool to generate `metadata.json` and `build-config.json` from .dar files
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- CLI tool to generate `metadata.json` and `build-config.json` from .dar files

As written above, I believe build reproducibility is better solved by changing dpm to check the sources of a .dar matching its contents.

So I'm not sure about this tool being built.

However, a tool that does seem useful is one that generates a target vetting state from a set of .dars

3. **Validator Node Provider tooling**:
- Library to fetch and verify audit reports
- Decision engine implementing verification procedures
- UI components for displaying audit results to users
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do they need to publish this to users?


3. **Validator Node Provider tooling**:
- Library to fetch and verify audit reports
- Decision engine implementing verification procedures
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this the script that computes the target vetting state for their validator nodes from a spec of the apps that they would like to deploy and the security audit reports to use?

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.

6 participants