Contract Source Validation SEP #1573
Replies: 7 comments 26 replies
-
|
I have been using your action for my project and it's great 👍 It's very important for the whole supply chain security that we get that part right. Some comments/suggestions:
|
Beta Was this translation helpful? Give feedback.
-
|
👋🏻 This proposal is really important and it's wonderful to see it starting to get use already. I think the proposal bundles together three super valuable things that need more specification, independently:
Why:
1️⃣ Linking built wasms to source code – The proposal achieves this with GitHub Attestations and Sigstore's Rekor (transparency log) 👏🏻. GitHub Attestations are sufficient for proving the wasm to source code link. We know this because it's now a software engineering best practice adopted by other ecosystems (npm, pypi, homebrew). The rest of the proposal provides other guarantees and benefits that aren't critical for proving a link between a binary (wasm) and code. The less we add to this verification process that is bespoke, the more we lean on the software engineering industries best practices, the more we can benefit from development outside the Stellar ecosystem. For example, using common tools like the For the purposes of defining how to verify code, the proposal would be sufficient to set it's scope on: Currently the proposal doesn't indicate how to do (b) or (c), other than use the
The proposal suggests SDF take ownership of the bespoke workflow, but if we reduce the verification proposal to the above, there will be no need for any trust in any workflow owner, other than GitHub. Assuming the use of Rekor in the verification process, GitHub on its own would only be trusted at build time, not at verification time. It would be awesome if the proposal could discuss the sigstore primitives that are being used. Because really this solution is platform agnostic already. A payload is produced, signed, published to the sigtore transparency log (rekor), and if you trust the signer, you can verify the payload. But being most practical I think it's fine if it relies on GitHub APIs and maybe in the future a compatible SEP is written that describes the process at the sigstore layer. 2️⃣ Linking built wasms to home domains – The proposal includes instructions for how to store This 'home_domain' linking could be an independent SEP and doesn't need to be coupled with source code verification. The wasm file home_domain linking may also not be sufficient for all use cases. Not all deployments of a wasm hash should be associated with the same home domain. Contract deployments/instances also need a way to report their home_domain linkage, and so it may be better to do linking at the instance level instead of the wasm file meta level. 3️⃣ A convenient common build process or common build containers – The proposal as written requires the use of a GitHub build workflow where contracts are built in a specific Ubuntu docker image, and attestation/verification requires releasing:
The workflow is opinionated and makes assumptions about how a developer wants to build and release their contracts. In other ecosystems that use attestation, building is not opinionated or coupled to attestation, for e.g.: The workflow expands the surface area of a contract developers risk, because they must be concerned with a third parties action, and the additional third party components that workflow pull in and may be supply chain exploitable. For example: It shifts control away from the developer and requires developers to use a specific approach to releasing and building their applications. Ideally developers can be in full control of their own build and release processes and still be permitted to participate in verification. I think a standard GitHub Action that builds Rust Stellar contracts would be good for the ecosystem, but it seems unnecessary to couple it with source code verification. A standard Docker image for building could further the goal of reproducible builds as another method for making it possible to verify builds. This proposal would need more than what exists here though, such as a fully and truly reproducible build image, and a way to securely link wasm builds back to their build image. That effort is much more likely to be iterative and require more work because reproducible builds in Rust are hard (something @brson has spent some effort on improving ❤️) and building other peoples Rust code is unsafe (because building Rust code executes it on the host). In an example contract repo I've written a build process that I think should be compatible with the verification proposal, because it uses attestation reasonably to prove linkage between a wasm and code. Currently it doesn't show up as verified on stellar.expert because it doesn't use the stellar-expert workflow: In my own learning I wrote a prototype CLI command that verifies the code links to the binary using only the @orbitlens and folks, wdyt? Are there three proposals here we can separate? @tupui given your experience with pypi I'm interested if separating this proposal makes sense, specifically separately 1️⃣ and 3️⃣, given that ecosystem has as far as I can tell. |
Beta Was this translation helpful? Give feedback.
-
|
Separate to my other comment which is more about making changes to the SEP, could SEP go into greater detail about what parts of the attestation, it's payload, etc are used for verification? For example, could it discuss what GitHub APIs are used, what fields out of the in-toto.io/Statement/v1 payload data are verified (e.g. the runtime environment == github-hosted?), and information about if the attestation is verified in the Rekor transparency log (imo it's important this is checked as a way to reduce the surface area of the trust in the provider). |
Beta Was this translation helpful? Give feedback.
-
|
I updated the SEP proposal to include the "Attestation Verification Flow" following @leighmcculloch's advice. We also updated the workflow to remove Docker dependency and the step that sends information to StellarExpert API. Our ingestion engine will be able to retrieve this information directly from the contract, so that's not needed anymore. @leighmcculloch could you please take a look at the workflow before we merge it to the master branch? |
Beta Was this translation helpful? Give feedback.
-
|
I'd like to move this over the finish line. After a lot of internal discussion, we came to the conclusion that we can simplify the proposal a little bit, without heavily relying on a hosted workflow. I drafted an updated version and would love to have your thoughts, @orbitlens @leighmcculloch. Contract Build Verification SEPPreambleSimple SummaryA toolkit for the verification of the contract WASM build. MotivationStellar doesn't store the source code of contracts in the blockchain, so it may be quite challenging for users to make sure that a contract they are going to invoke is not malicious and behaves as advertised. AbstractThis SEP describes an approach to contract build verification using GitHub Attestations. It provides the ability to display information about the contract that's been deployed and the build pipeline that generated the WASM file. This proposal makes no assumptions on how your WASM file is generated, but requires developers to add a metadata entry to the WASM, as well as making an artifact attestion using GitHub Actions. Once the contract is deployed, anyone can verify and inspect the build pipeline that generated the WASM file. It's important to be aware that this doesn't mean that the contract is safe to use, but it does provide a way to verify how the contract was built, by giving access to the workflow file that was used to build the contract. SpecificationThe verification mechanism relies on the GitHub automation and Attestations build artifacts generated during the automated smart contract compilation. Each attestation contains:
In addition to the source code repository link, the workflow can also store a home domain in the contract to provide a consistent off-chain organization and/or token information resolution using a standard SEP-0001 During the compilation, the pipeline stores a repository address in every compiled contract by adding WASM metadata to the Metadata entries stored in the contract WASM:
Based on this information anyone can verify the authenticity of the smart contract source code, and perform a reverse lookup of the contract information from the organization's domain. Design RationaleCurrently, the pipeline relies on GitHub platform tools and does not provide the toolkit for other platforms, like GitLab or BitBucket. GitHub has the largest market share, so the initial implementation utilized its standard APIs and instruments. In the future, in response to the demand, similar automated workflow can be created for other platforms as well. The Likewise, this SEP and workflow can be extended in the future to execute automatic contract deployment to the network on build. However, this process has a huge a list of potential security concerns which need to be evaluated, addressed, and documented before including this functionality in the continuous delivery pipeline. Attestation Verification FlowSteps to assemble the trust chain between the deployed smart contract and the source code repository:
If any of the above steps fail, the entire attestation verification process fails. Workflow Setup and ConfigurationPrerequisites
Workflow PermissionsIn order to create a release, the workflow needs permissions:
id-token: write
contents: write
attestations: writeExample: Basic workflow using Stellar CLIThe following workflow uses Stellar CLI to build and optimize the contract. ---
name: Build and Release
on:
push:
# 1️⃣ Create a release whenever a new tag like `v0.0.0 is pushed.
tags:
- "v*"
# 2️⃣ Create a release manually from GitHub's user interface.
workflow_dispatch:
inputs:
release_name:
description: "Release Version (e.g. v0.0.0)"
required: true
type: string
permissions:
id-token: write
contents: write
attestations: write
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: rustup update
- run: rustup target add wasm32-unknown-unknown
- run: cargo version
# 3️⃣ Set up env vars that will be used in the workflow.
- name: Set up env vars
run: |
echo "WASM_FILE=target/wasm32-unknown-unknown/release/hello.wasm" >> $GITHUB_ENV
if [ -n "${{ github.event.inputs.release_name }}" ]; then
echo "TAG_NAME=${{ github.event.inputs.release_name }}" >> $GITHUB_ENV
else
echo "TAG_NAME=${{ github.ref_name }}" >> $GITHUB_ENV
fi
# 4️⃣ Set up the Stellar CLI.
- uses: stellar/[email protected]
with:
version: 22.5.0
# 5️⃣ Build the contract and mark the WASM with the current repository.
- name: Build contract
run: |
stellar contract build \
--meta home_domain=example.com \
--meta source_repo=github:${{ github.repository }}
stellar contract optimize --wasm ${{ env.WASM_FILE }}
file=${{ env.WASM_FILE }}
cp "${file%.*}.optimized.wasm" ${{ env.WASM_FILE }}
# 6️⃣ Upload the WASM file to the artifacts.
- name: Upload to Artifacts
uses: actions/upload-artifact@v4
with:
name: hello.wasm
path: ${{ env.WASM_FILE }}
# 7️⃣ Build the attestation for the wasm file.
- name: Build Attestation for Release
uses: actions/attest-build-provenance@v1
with:
subject-name: hello.wasm
subject-path: ${{ env.WASM_FILE }}
# 8️⃣ Make a new release.
- name: Make a new Release
id: release
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const response = await github.rest.repos.createRelease({
owner: context.repo.owner,
repo: context.repo.repo,
tag_name: '${{ env.TAG_NAME }}',
target_commitish: '${{ github.sha }}',
make_latest: 'true'
});
const { data } = response;
core.setOutput('release_id', data.id);
# 9️⃣ Upload the wasm file to the release.
- name: Upload to Release
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const fs = require('fs');
const path = require('path');
await github.rest.repos.uploadReleaseAsset({
owner: context.repo.owner,
repo: context.repo.repo,
release_id: '${{ steps.release.outputs.release_id }}',
name: path.basename('${{ env.WASM_FILE }}'),
data: fs.readFileSync('${{ env.WASM_FILE }}'),
});Security ConcernsThis SEP does not create any direct security concerns for the Stellar protocol or ecosystem applications. Since the verification routine relies on the GitHub build automation and attestation mechanism, this approach implies the trust in GitHub’s security. If GitHub security is compromised, it means that verification data cannot be trusted. The possibility of such an event looks very low considering the track records of GitHub and its enterprise backers. Unlike other building artifacts, attestations are stored in GitHub forever (or at least until the code repository is removed). Therefore, if developers decide to remove a smart contract repository, the verification chain may be broken. However, downstream systems (like blockchain explorers) may retain the verification information indefinitely, alleviating such risks. While the build process itself is performed in the virtual GitHub environment shielded from an external access, smart contract developers still can potentially use some subtle techniques to inject malicious code into the contract during the compilation phase. Protecting end users from malicious developer actions is out of the scope of this SEP – the primary goal is to provide unfalsifiable evidences that a contract has been compiled automatically using a particular GitHub repository. Changelog
|
Beta Was this translation helpful? Give feedback.
-
|
@fnando I just saw the PR got merged!? I thought we were still in discussion? We did not at least openly vote or anything. The proposal should at least have a discussion on the rejected ideas we discussed there. Both @orbitlens and I spent quite some time on this and I am not even talking about the community push we tried to do towards securing the supply chain. |
Beta Was this translation helpful? Give feedback.
-
|
Cross-posting due to relatedness: |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Contract Source Validation SEP
Preamble
Simple Summary
A toolkit for the verification of the trust chain between contract WASM and its source code.
Motivation
Stellar doesn't store the source code of contracts in the blockchain, so it may be quite challenging for users to make sure that a contract they are going to invoke is not malicious and behaves as advertised.
Abstract
This SEP describes an approach of automated source code matching based on GitHub Actions Workflows and GitHub Attestations. It provides the ability to establish a trust chain from a smart contract deployed on Stellar Network to a specific commit in GitHub repository containing source code of this contract. As a side benefit, this standard workflow streamlines the smart contracts compilation and release process for Soroban WASM runtime.
In order to turn on automatic code attestation, smart contract developers create a simple configuration file in a contract Git repository.
When triggered, this workflow:
Upon successful validation, anyone can retrieve the GitHub repo link from the contract binary and verify the authenticity of the build directly on the contract GitHub repository Attestations page or using a blockchain explorer that supports this SEP. The trust chain can be validated up to a particular point-in-time snapshot of the source code at the given commit used to build the contract.
Specification
The verification mechanism relies on the GitHub automation and Attestations build artifacts generated during the automated smart contract compilation. Each attestation contains:
In addition to the source code repository link, the workflow can also store a home domain in the contract to provide a consistent off-chain organization and/or token information resolution using a standard SEP-0001
stellar.tomlfile.During the compilation, the pipeline stores a repository address in every compiled contract by adding WASM metadata to the
contractmetav0custom sections. Metadata is stored in the contract asSCMetaEntryXDR entry. Downstream systems can retrieve this information directly from the WASM, read repository contents and retrieve corresponding attestation from the GitHub API endpoint:https://api.github.com/repos/<user_name>/<repo_name>/attestations/sha256:<wasm_hash>, wherewasm_hashis the SHA256 hash of the contract WASM binary.Metadata entries stored in the contract WASM:
source_repo=github:<user_name>/<repo_name>- source repository linkexample:
source_repo=github.com:reflector-network/reflector-dao-contracthome_domain=<domain_name>- domain that hosts organization'sstellar.toml(domain name only, without schema or relative path)example:
home_domain=reflector.networkBased on this information anyone can verify the authenticity of the smart contract source code, and perform a reverse lookup of the contract information from the organization's domain.
Workflow Setup and Configuration
Prerequisites
.github/workflows/release.ymlin your repository.Workflow Inputs and Secrets
Basic compilation workflow path:
stellar-expert/soroban-build-workflow/.github/workflows/release.yml@mainThe workflow expects the following inputs in the with section:
release_name(required) - release name template (should include a release version variable, e.g. ${{ github.ref_name }})package (optional) - package name to build, builds contract in working directory by default
relative_path(optional) - relative path to the contract source directory, defaults to the repository root directorymake_target(optional) - make target to invoke, empty by default (useful for contracts with dependencies that must be built before the main contract)Basic workflow for the repository with a single contract
Workflow Permissions
In order to create a release, the workflow needs
id-token: write,contents: writeandattestations: write permissions. Default workflow permissions for a repository can be found at "Settings" -> "Actions" -> "Workflow permissions". It's important to specify permissions on the top level in the.github/workflows/release.ymlconfiguration file itself:Building Multiple Contracts
To build multiple contracts, add a separate job for each contract. The workflow will compile and release each contract independently.
Triggering Build Process Manually
Triggering this workflow manually requires a unique release name prompt. Replace the trigger condition in config and update
release_nameto utilize the value from the prompt.Attestation Verification Flow
Steps to assemble the trust chain between the deployed smart contract and the source code repository:
contractmetav0custom sections.source_repokey. Retrieve GitHubuser_nameandrepo_namefrom the meta value stored in the format described above.https://api.github.com/repos/<user_name>/<repo_name>/attestations/sha256:<wasm_hash>. Parse the response as JSON.attestations[0].bundle.dsseEnvelope.payload. The format follows in-toto.io/Statement/v1 standard. Decode the payload as Base64 and parse resulting string as JSON.subject[0].digest.sha256to match the smart contract hash obtained at step 1.runDetails.builder.idto match the trusted reference build workflow repository address and relative path (https://github.com/stellar-expert/soroban-build-workflow/.github/workflows/release.yml@refs/heads/main).predicate.buildDefinition.resolvedDependencies[0].urito match the GitHub repository obtained at step 4.predicate.buildDefinition.resolvedDependencies[0].digest.gitCommitwill contain the git commit hash at which the attestation has been produced.If any of the above steps fail, the entire attestation verification process fails.
Notes
release_contractjob.Design Rationale
Currently, the pipeline relies on GitHub platform tools and does not provide the toolkit for other platforms, like GitLab or BitBucket. GitHub has the largest market share, so the initial implementation utilized its standard APIs and instruments. In the future, in response to the demand, similar automated workflow can be created for other platforms as well. The
source_repometadata record contains a platform prefix (github:) as an extension point for the smooth integration of other repository hosting providers. In addition, attestations can be also potentially stored on IPFS or other distributed storage to increased the data availability.Likewise, this SEP and workflow can be extended in the future to execute automatic contract deployment to the network on build. However, this process has a huge a list of potential security concerns which need to be evaluated, addressed, and documented before including this functionality in the continuous delivery pipeline.
Security Concerns
This SEP does not create any direct security concerns for the Stellar protocol or ecosystem applications.
Since the verification routine relies on the GitHub build automation and attestations mechanism, this approach implies the trust in GitHub’s security. If GitHub security is compromised, it means that verification data cannot be trusted. The possibility of such an event looks very low considering the track records of GitHub and its enterprise backers.
Unlike other building artifacts, attestations are stored in GitHub forever (or at least until the code repository is removed). Therefore, if developers decide to remove a smart contract repository, the verification chain may be broken. However, downstream systems (like blockchain explorers) may retain the verification information indefinitely, alleviating such risks.
While the build process itself is performed in the virtual GitHub environment shielded from an external access, smart contract developers still can potentially use some subtle techniques to inject malicious code into the contract during the compilation phase. Protecting end users from malicious developer actions is out of the scope of this SEP – the primary goal is to provide unfalsifiable evidences that a contract has been compiled automatically using a particular GitHub repository.
The automation workflow that builds smart contracts is currently hosted by StellarExpert. We suggest transferring its repository ownership to SDF in order to minimize trust concerns.
Implementations
Changelog
v0.3.0- Updated workflow to exclude the Docker image, clarified what attestation fields are used during the verificationv0.2.0- Addedhome_domainmeta, notes on meta XDR and format, design rationale for the GitHub platform lock-inv0.1.1- Defined metadata storage key format explicitlyv0.1.0- Initial draftBeta Was this translation helpful? Give feedback.
All reactions