Attested Builds

Attested builds are a new approach to verifiable software distribution. Source code is compiled inside hardware-isolated environments that produce cryptographic proof linking binaries to their exact inputs.

Architecture

A Kettle build moves a project from "source on a developer's machine" to "artifact accompanied by hardware-rooted evidence" without trusting anything between those two endpoints. The system has three logical pieces. The client provides a random nonce and a version control reference (such as a git repository and commit ID). The host schedules the build but is otherwise untrusted. The Kettle CVM is a confidential virtual machine that boots from a reproducible Kettle image, runs the build inside the TEE, and emits an evidence bundle verifiable against the CPU vendor's root of trust.

          Developer machine                                           Build host
   ┌──────────────────────────────┐                     ┌─────────────────────────────────────┐
   │                              │                     │                                     │
   │            Client            │                     │              launches               │
   │                              │                     │                 │                   │
   │  Commit inputs to VCS        │                     │                 ▼                   │
   │                              │  Build request      │  ╔═══════════════════════════════╗  │
   │                              ├────────────────────►│  ║         Kettle CVM            ║  │
   │                              │                     │  ║                               ║  │
   │                              │  Attestation        │  ║   Measured boot               ║  │
   │                              │◄────────────────────┤  ║   Verify inputs               ║  │
   │  Verify launch measurement   │                     │  ║   Generate provenance         ║  │
   │  Check vendor signature      │                     │  ║   Run build                   ║  │
   │                              │                     │  ║                               ║  │
   │                              │                     │  ║   ┌─────────────────────┐     ║  │
   │                              │                     │  ║   │ TEE processor signs │     ║  │
   │                              │                     │  ║   │ with vendor key     │     ║  │
   │                              │                     │  ║   └─────────────────────┘     ║  │
   │                              │                     │  ╚═══════════════╤═══════════════╝  │
   │                              │                     │                  ▼                  │
   │                              │                     │   ┌─────────────────────────────┐   │
   │                              │  Bundle             │   │ artifact                    │   │
   │                              │◄────────────────────┤   │   + provenance.json         │   │
   │  Verify bundle               │                     │   │   + evidence [attestation]  │   │
   │                              │                     │   └─────────────────────────────┘   │
   │                              │                     │                                     │
   └──────────────────────────────┘                     └─────────────────────────────────────┘

Kettle build at a glance. The client commits the input and requests a build. The build runs inside a freshly-launched CVM, which generates a provenance document and emits an attestation signed by the TEE processor with a key chained to the CPU vendor root. The bundle returned to the client is verifiable locally against that root.

The result is a single bundle (the artifact, provenance.json, and the raw attestation evidence) that any verifier can check locally. The rest of this page describes each part of that flow in detail.

Build Flow

An attested build runs across four actors. These are the developer's CLI, the host (or CI runner) that schedules the work, the Kettle CVM that performs the build, and the TEE hardware that anchors the attestation. The host can start, stop, and route IO for the CVM, but cannot observe its memory. Everything between the CVM boot and the emitted evidence is shielded by the hardware boundary.

   Developer CLI               Host                     Kettle CVM                     TEE hardware
       │                       │                           │                               │
       │ 1. Create VCS commit  │                           │                               │
       │    for build          │                           │                               │
       │                       │                           │                               │
       │ 2. Submit request     │                           │                               │
       │    and build nonce    │                           │                               │
       ├──────────────────────►│                           │                               │
       │                       │                           │                               │
       │                       │ 3. Launch CVM             │                               │
       │                       ├──────────────────────────►│                               │
       │                       │                           │                               │
       │                       │                           │ 4. Measured boot              │
       │                       │                           │    request launch digest      │
       │                       │                           ├──────────────────────────────►│
       │                       │                           │                               │ Extend measurement
       │                       │                           │ Launch digest                 │
       │                       │                           │◄──────────────────────────────┤
       │                       │                           │                               │
       │                       │                           │ 5. Fetch repo, commit,        │
       │                       │                           │    dependencies               │
       │                       │                           │                               │
       │                       │                           │ 6. Run build,                 │
       │                       │                           │    Digest outputs             │
       │                       │                           │                               │
       │                       │                           │ 7. Assemble SLSA 1.2          │
       │                       │                           │    provenance JSON            │
       │                       │                           │                               │
       │                       │                           │ 8. Request attestation        │
       │                       │                           │    report_data =              │
       │                       │                           │    SHA-256(provenance.json)   │
       │                       │                           ├──────────────────────────────►│
       │                       │                           │                               │ Sign with vendor key
       │                       │                           │ Signed attestation report     │
       │                       │                           │◄──────────────────────────────┤
       │                       │                           │                               │
       │                       │ 9. Emit bundle            │                               │
       │                       │◄──────────────────────────┤                               │
       │                       │                           │                               │
       │ 10. Return bundle     │                           │                               │
       │◄──────────────────────┤                           │                               │
       │                       │                           │                               │

Kettle build sequence. The developer creates a VCS commit and submits the build request to the host (1–2). The host launches the CVM (3). Inside the CVM, measured boot extends the launch digest in TEE hardware (4). Kettle fetches the repo, commit, and dependencies, then (5) runs the build and digests outputs (6), and assembles the provenance document as SLSA 1.2 build provenance JSON (7). It then requests an attestation report whose report_data field contains SHA-256(provenance.json) and the build request nonce. (8). The hardware signs the report with the platform attestation key. The artifact and evidence are emitted back to the host (9) and returned to the developer (10).

Input Merkle Tree describes the input manifest committed to the provenance document. TEE Environment Setup covers measured boot and the attestation report. Build Execution and Provenance covers provenance generation, build execution, output digesting, and how the provenance is committed to the attestation. Evidence Chain and Verification specifies the verification procedure. Confidential Builds describes an optional confidential variant of the flow above, in which the requester pre-attests the CVM and sends the source over a TLS channel terminated inside it. The verifier-facing chain is unchanged.

Input Merkle Tree

Before any build starts, the project's dependencies and source state are locked. This step runs locally, outside the TEE, and produces the input manifest that the CVM will consume.

Locking dependencies. The project must carry a lockfile that pins every dependency to a specific version and a cryptographic digest. This is standard practice in modern package managers, and the lockfile captures the exact dependency graph at a point in time. Ecosystems without first-class lockfiles require the developer to supply an equivalent pinned manifest of resolved versions and digests as part of the build configuration.

Input enumeration. Kettle walks every build input and computes its cryptographic digest:

  • Source code: the git commit identifier, tree digest (a content-addressed digest of the file tree), and repository signature where present.
  • Dependencies: each package identified by name, version, and digest taken from the lockfile.
  • Toolchain: digests of compiler and build-tool binaries.

Cached artifacts are checked against their expected digests at this stage, and any mismatch fails the build before the CVM is launched.

Merkle tree construction. All input digests become leaves in a Merkle tree. The tree is constructed in a deterministic order, with git information first, then the lockfile digest, then dependencies in lexicographic order by name, and toolchain digests last. The ordering is fixed by convention so that any third party can reconstruct the same tree from the same inputs. Kettle uses SHA-256 for both leaf and node digests. The Merkle structure (fixed-size inputs concatenated with explicit length prefixes at each internal node) does not admit length-extension attacks against the underlying digest.

                        input_merkle_root
                                │
                  ┌─────────────┴─────────────┐
                 h₀₁                         h₂₃
           ┌──────┴──────┐             ┌──────┴──────┐
          h₀            h₁            h₂            h₃
           │             │             │             │
        Source       Lockfile        Deps        Toolchain
        commit        digest        digests       digests

Input manifest as a Merkle tree. Each declared input is digested into a leaf, leaves are paired and hashed into internal nodes, and the procedure repeats until a single root remains. The root is recorded in the provenance document, whose digest is committed to the attestation report. Any change to any input bubbles up and changes the root.

The root of this tree is a single digest that uniquely identifies the complete set of build inputs. Any change to any input, even of a single byte, changes the root.

The Merkle structure also enables selective disclosure. To prove inclusion of a specific dependency without revealing the rest of the input set, the builder publishes the path from that dependency's leaf to the root. The verifier checks the path against the published root and confirms that the dependency was part of the build. Selective disclosure matters most when the dependency set is itself sensitive, for example a vendor that does not wish to enumerate proprietary internal packages to an external auditor.

Optional developer signature. The manifest may be signed locally before submission. The signature does not strengthen the cryptographic chain (the attestation report and provenance signature already pin inputs to outputs), but it adds an identity-bound declaration that a specific developer or release engineer approved this set of inputs. Verifiers that require human accountability check the signature, while verifiers that do not can ignore it. Manifest signing is orthogonal to the TEE-rooted evidence and protects against neither a compromised developer machine nor a malicious developer.

TEE Environment Setup

The build environment boots inside a TEE with measured boot. From this point onward, every step of the build is bound to evidence rooted in hardware that no software on the host can forge. Concretely, Kettle currently targets confidential VMs implemented by AMD SEV-SNP and Intel TDX. The architecture below is described in vendor-agnostic terms but maps directly onto the launch-measurement and attestation primitives those platforms expose.

Measured boot chain. As the TEE initializes, the hardware measures every component that loads. The security processor computes a digest of each component and extends it into a cumulative measurement register, where the extension operation is new_measurement = digest(old_measurement || component_digest). Extension is one-way. A measurement register cannot be "un-extended", so the final value depends on exactly what was loaded and in what order. The measurement chain covers:

ComponentWhat gets measured
FirmwareUEFI/boot code that initializes the TEE
KernelKernel image and the kernel command line
InitrdInitial RAM filesystem used to bring up the build environment
VM imageThe hardened operating system image
KettleThe attested build orchestrator

Including the kernel command line in the measurement is important. A parameter passed at boot can change kernel behavior (security features, mount options, init binary) without altering the kernel image itself. A measurement chain that omitted the command line would let the host silently change those parameters between builds. Kettle itself is part of this initial measurement. The resulting attestation report identifies the environment as a TEE running a specific Kettle release at a known cumulative measurement, so a verifier can confirm that the entity producing the report is a genuine instance of Kettle rather than arbitrary code making the same claim.

Isolation as the primary defense. By requiring a CVM, Kettle inherits hardware-enforced isolation rather than relying on container-level boundaries. Root access inside the CVM grants no visibility into other build jobs, the host, or other tenants on the same physical hardware, and each build runs in its own fresh CVM, so cross-build contamination is structurally precluded. The base VM image contains only the components required to run Kettle and execute builds, and is built deterministically so that its measurement is predictable across releases.

Reproducible CVM image. Because the CVM image itself does not depend on the inputs of any individual build, it can be produced once per Kettle release as a fully reproducible artifact. Its digest, and the cumulative launch measurement that the platform will report when a CVM boots from it, are public, stable, and tied to a specific Kettle version. Anyone can rebuild the image from the published source and confirm that the resulting launch measurement matches the value pinned in their allow-list (see Measurement Allow-Lists). This is the foundation that lets a verifier recognize a "genuine Kettle build CVM" without trusting the operator that hosts it, and it is what enables the optional confidential-input flow described under Confidential Builds.

Defence in depth (roadmap). Several additional hardening layers complement CVM isolation but are not yet implemented in the current Kettle release. These include a mandatory access control policy applied to the build process, system-call filtering that allow-lists only the syscalls needed for compilation and file I/O, and severing network access at the kernel level once inputs are loaded. They are discussed alongside other planned work under Open Directions.

Loading inputs. The CVM consumes inputs in one of two ways. In the simpler mode, Kettle fetches each declared dependency over the network from inside the CVM and only then severs network access. In the stronger mode, all inputs are bundled with the source archive and become part of the initial CVM image, so they are themselves covered by the launch measurement. This eliminates network trust during the build at the cost of a larger image. In both cases, no input is used unless it is part of the commit from the build request, and any mismatch aborts the build before any project code runs.

Provenance binding via attestation. Kettle binds the provenance document to hardware by committing its digest into the attestation report's report-data field. The attestation report itself, signed by the platform attestation key, is the signature on that document. The platform attestation key is provisioned by the hardware vendor and held by the CPU's security processor, so the signing identity behind every Kettle build chains directly to the vendor root of trust. Forging Kettle provenance requires forging an attestation report from genuine TEE hardware.

Attestation report. Once the build has run and the provenance document has been assembled (see Build Execution and Provenance), Kettle requests an attestation report from the platform. The report contains the cumulative launch measurement, platform information (CPU model, firmware version, enabled security features), and a report-data field that the guest fills in. Kettle places a SHA-256 digest of the provenance document and the one-time build nonce into the report-data field,

  report_data = SHA-256( provenance_document ), nonce

where provenance_document is the canonical-JSON serialization of the in-toto Statement described under in-toto Statement Layer, and the digest covers everything in that document including the input Merkle root, the resolved-dependency list, the output artifact digests, the build metadata, and the build-request nonce supplied by the requester. SEV-SNP and TDX expose a 64-byte report-data field. The SHA-256 digest occupies the leading 32 bytes, and the remaining bytes carry the build-request nonce.

The report signature chains to the CPU vendor's root certificate, so a verifier can confirm in one signature check that the report was produced by genuine TEE hardware, that the measured environment matches an expected Kettle build configuration, and that this report corresponds to one specific provenance document. Any change to the provenance document changes its digest and therefore the report-data the platform signed over.

  ┌──────────────────────────── Attestation report ────────────────────────────┐
  │                                                                            │
  │   measurement    : extend[firmware, kernel+cmdline, initrd, VM image,      │
  │                           Kettle]                                          │
  │                                                                            │
  │   report_data    : SHA-256( provenance_document )                          │
  │                    Build request nonce                                     │
  │                                                                            │
  │   platform_info  : { cpu_model, firmware_version, ... }                    │
  │                                                                            │
  │   signature      : platform attestation key                                │
  │                                                                            │
  └────────────────────────────────────────────────────────────────────────────┘

Measured boot extends each loaded component into a single cumulative launch measurement, which becomes the measurement field of the attestation report. The report_data field carries a SHA-256 digest of the canonical provenance document and the nonce from the build request. The whole report is signed by the platform attestation key. The attestation report is therefore the signature on the provenance, with no additional in-guest key required.

The attestation report is the bridge between software claims and hardware proof. The VCS commit determines which inputs will be used, and the attestation proves that a measured Kettle environment used those inputs, ran the build, and produced exactly the provenance document the report-data digest commits to, all within a single hardware-signed object.

Build Execution and Provenance

With the environment measured and inputs verified, the build executes inside the TEE. The output of this stage is a provenance document whose digest is then committed to hardware via the attestation report described under TEE Environment Setup.

Build execution. Kettle invokes the project's existing build toolchain according to the build configuration. Compilation, linking, and packaging proceed exactly as they would on any developer machine, and Kettle does not modify the build process, only the environment it runs in. CVM isolation remains active throughout, and any of the in-CVM hardening layers planned under Open Directions will apply at this stage when introduced.

Output digests. On completion, Kettle computes a SHA-256 digest over each output artifact, and these digests are recorded in the provenance document. Because digest calculation happens inside the TEE, the output digests inherit the same isolation guarantees as the build itself, so a malicious host cannot substitute artifacts between the build finishing and the digests being recorded.

Provenance assembly. Kettle assembles the provenance document inside the CVM. The document is an in-toto Statement carrying an SLSA Provenance v1.2 predicate (see Provenance Format and Standards) and contains the input manifest (Merkle root and all input digests), the digests of all output artifacts, build metadata, and the build-request nonce supplied by the requester. Kettle then serializes the document under a canonical JSON encoding so that any verifier can recompute the exact byte sequence the platform will sign over. The SHA-256 digest of that canonical serialization is what Kettle places in the report-data field of the attestation request.

Hardware-bound provenance. Provenance integrity comes from the attestation report itself. Once the platform returns a signed report whose report-data matches SHA-256(provenance_document), the document is bound to the measured Kettle environment. A verifier reconstructs the chain by recomputing the digest from the provenance document, checking it against report-data, and validating the report signature against the CPU vendor's root.

Build outputs. A complete build emits three evidence artifacts alongside the built outputs. provenance.json is the SLSA v1.2 build record carried inside an in-toto Statement, recording inputs, output digests, and build metadata, in the canonical JSON form whose SHA-256 digest the attestation report committed to. evidence.json includes the TEE attestation report whose report-data field carries the provenance digest and build nonce. Together with the source commit, these three artifacts form the complete evidence chain. The provenance binds inputs to outputs, and the attestation binds the whole document to a measured TEE for a specific build request. Provenance Format and Standards specifies the format of these artifacts in detail.

Evidence Chain and Verification

The result is a cryptographic chain from declared inputs to artifact bytes. Verification walks that chain in order, checking each binding. Each check is meaningful only if the previous check passed.

                 ┌────────────────┐
                 │  Vendor root   │
                 └───────┬────────┘
                         │
                         │  Step 1: Report signature chains to vendor root,
                         │      launch measurement is allow listed
                         ▼
                 ┌────────────────┐
                 │  Attestation   │
                 │     report     │
                 └───────┬────────┘
                         │
                         │  Step 2: SHA-256(provenance.json)
                         │      matches report_data
                         ▼
                 ┌────────────────┐
                 │   Provenance   │
                 └───────┬────────┘
                         │
                         │  Step 3: Expected digest of artifact
                         │
                         ▼
                 ┌────────────────┐
                 │    Artifact    │
                 │     bytes      │
                 └───────┬────────┘
                         │
                         │
                         │
                         ▼
            ┌──────────────────────────┐
            │    Accept if all pass    │
            │   Reject if any fails    │
            └──────────────────────────┘

Evidence chain and verification. Each link binds to the next, and each numbered check verifies one link. Verification is local. Consumer tooling reads the artifact, provenance.json, and the raw evidence blob from a single bundle and runs the checks in order, with no remote service contacted.

StepWhat consumer tooling checks
Step 1: Verify the TEE attestationThe attestation signature chains to the hardware vendor's root of trust, the cumulative launch measurement matches an allow-listed Kettle measurement (see Measurement Allow-Lists), and the freshness nonce embedded in the provenance matches the build-request nonce.
Step 2: Verify the provenance bindingThe verifier recomputes SHA-256(provenance.json) over the canonical serialization of the provenance document and checks that it matches the leading 48 bytes of the report-data field. This is the step that turns the attestation report into a signature on the provenance.
Step 3: Verify the artifact bindingThe digests of the distributed output artifacts match the digests recorded in the provenance.

Each link in the chain rejects a corresponding attack:

AttackMechanism that detects it
Source modified after commitThe tree digest changes, the Merkle root changes, and the provenance file no longer matches the published build.
Dependency substituted before the buildThe dependency's digest does not match the lockfile entry, so input verification fails before the build starts.
Build machine compromisedThe build runs inside the TEE, so the host cannot read memory or inject code. Loading different inputs changes the provenance commitment or causes input verification to fail.
Malicious Kettle binaryThe launch measurement differs from the expected Kettle measurement, and the verifier rejects the attestation.
Output artifact swapped after buildThe artifact digest no longer matches the digest recorded in the provenance.
Provenance forgedThe SHA-256 digest of the forged provenance does not match the report-data field of the hardware-signed attestation report, so the binding check at step 2 fails.

When all checks pass, consumer tooling has cryptographic proof that the artifact in hand was produced by a specific build of Kettle running inside attested TEE hardware, over a specific list of inputs, and that every link in that chain is independently verifiable. Verification consists entirely of digest comparisons and one hardware-attestation signature check against the CPU vendor's root, all of which are local operations.

Measurement Allow-Lists

Step 1 above presupposes that a verifier can recognize an allow-listed Kettle measurement. In practice the cumulative launch measurement covers firmware, kernel and command line, initrd, VM image, and Kettle itself, so an allow-list entry is not a single value but a set of acceptable measurements, one per signed Kettle release. A verifier maintains (or imports) a list of these measurements together with the Kettle version, target platform (SEV-SNP, TDX), and any required platform-firmware level it implies. Verification policy is then expressible as "accept attestations whose measurement appears in the allow-list at version v or later, on platform p with firmware ≥ f."

The allow-list itself needs trustworthy origin. Because each Kettle release ships as a reproducible CVM image (see TEE Environment Setup), its launch measurement is recomputable from the published source. A verifier, or any independent observer, rebuilds the image and confirms that the resulting measurement matches the value published with the release before adding it to their allow-list. Verifiers that do not wish to track Kettle releases directly can delegate to a third party that publishes a signed allow-list.

Confidential Builds

The flow described so far yields integrity at the hardware level. A verifier can be sure that the bytes claimed as inputs were the bytes the build observed. It does not, on its own, hide those inputs from the host. In the simple flow the host receives the source archive in plaintext from the developer's CLI and hands it to the CVM at launch, so a malicious operator can still inspect or copy it before the CVM boots.

When the source is itself sensitive (proprietary code, customer data, an unreleased product) the requester can take the additional step of refusing to send any input until the CVM has proven it is a genuine Kettle release, and then sending the input over a confidential channel terminated inside the CVM. The reproducible CVM image (see TEE Environment Setup) is what makes this practical. Because the launch measurement of a Kettle release is public and stable, the requester can decide, before transmitting any source, whether the CVM they are about to talk to is one they trust.

The flow has three stages and reuses the same report_data mechanism that already binds inputs and outputs.

   Requester CLI                             Host                    Kettle CVM                     TEE hardware
        │                                      │                          │                              │
        │ Generate nonce_p                     │                          │                              │
        │ Pre launch: requester knows          │                          │                              │
        │ expected Kettle measurement          │                          │                              │
        │ from public allow list               │                          │                              │
        │                                      │                          │                              │
        │ Request CVM launch with nonce_p      │                          │                              │
        ├─────────────────────────────────────►│                          │                              │
        │                                      │ Launch CVM with          │                              │
        │                                      │ host_data = nonce_p      │                              │
        │                                      ├─────────────────────────►│                              │
        │                                      │                          │ Measured boot                │
        │                                      │                          ├─────────────────────────────►│
        │                                      │                          │ Launch measurement           │
        │                                      │                          │◄─────────────────────────────┤
        │                                      │                          │                              │
        │                                      │                          │ Generate TLS keypair         │
        │                                      │                          │ inside CVM                   │
        │                                      │                          │                              │
        │                                      │                          │ Request attestation          │
        │                                      │                          │ report_data:                 │
        │                                      │                          │ H[tls_pubkey || nonce_p]     │
        │                                      │                          ├─────────────────────────────►│
        │                                      │                          │ Signed attestation:          │
        │                                      │                          │   measurement                │
        │                                      │                          │   host_data = nonce_p        │
        │                                      │                          │   report_data                │
        │                                      │                          │◄─────────────────────────────┤
        │                                      │                          │                              │
        │ Pre attestation                      │                          │                              │
        │ [TLS pubkey + report]                │                          │                              │
        │◄─────────────────────────────────────┼──────────────────────────┤                              │
        │                                      │                          │                              │
        │ Verify:                              │                          │                              │
        │  - signature chains to vendor root   │                          │                              │
        │  - launch measurement is Kettle      │                          │                              │
        │  - host_data equals nonce_p          │                          │                              │
        │  - report_data equals                │                          │                              │
        │    H[tls_pubkey || nonce_p]          │                          │                              │
        │                                      │                          │                              │
        │ Open TLS to CVM, send                │                          │                              │
        │ encrypted source                     │                          │                              │
        ├──────────────────────────────────────┼─────────────────────────►│  Decrypt inside CVM          │
        │                                      │                          │                              │
        │                                      │                          │ Continue with standard flow. │
        │                                      │                          │ Second attestation           │
        │                                      │                          │ commits SHA-256 of the       │
        │                                      │                          │ provenance document          │
        │                                      │                          │                              │

Pre-attested confidential build. The requester generates a single nonce that the hypervisor commits into the CVM's host_data field at launch and that Kettle inside the CVM also includes in report_data. The first attestation therefore proves three things at once. The CVM is running Kettle code, it was uniquely launched for this requester, and the report itself is fresh. Source is then delivered over a TLS channel terminated inside the CVM, and the standard attestation over the provenance document (see TEE Environment Setup) follows.

Stage 1, pre-attestation. The requester generates a fresh nonce_p and submits it with the CVM-launch request. The hypervisor writes nonce_p into the CVM's host_data field, which the platform records before the guest boots and includes in every attestation report the CVM produces. Once booted, the CVM generates a TLS keypair inside its memory and requests an attestation report whose report_data field carries SHA-256(tls_pubkey || nonce_p). The report is returned to the requester along with the TLS public key. The TLS keypair is used only to terminate the channel inside the CVM and plays no role in signing provenance.

Stage 2, verification before transmission. The requester checks the attestation locally. The signature must chain to the CPU vendor's root of trust, the launch measurement must match an allow-listed Kettle release on the expected platform, host_data must equal the nonce_p the requester just submitted, and report_data must match SHA-256(tls_pubkey || nonce_p) for the TLS public key just received. Each check answers a different freshness question. The launch measurement covers code identity, host_data covers CVM uniqueness (this is a freshly launched VM provisioned for this requester and not a replay or shared instance), and report_data covers attestation freshness plus the channel binding. Because the Kettle CVM image is reproducible and its measurement is published with each release, the requester can perform every one of these checks without trusting the operator that hosts the CVM. If any check fails, the requester walks away without ever revealing the source.

Stage 3, confidential delivery and build. The requester opens a TLS session to the CVM using the verified public key as the channel endpoint, and transmits the source archive over that session. The host can observe ciphertext and the launch measurement, but cannot read the inputs. Inside the CVM, Kettle decrypts the inputs, and proceeds with the standard build flow (see TEE Environment Setup and Build Execution and Provenance). A second attestation report is produced after the build, with report_data = SHA-256(provenance_document) exactly as in the non-confidential flow. The two attestations share a launch measurement (the same Kettle CVM produced both) and chain together. The first proves the channel, the second proves the build.

This flow does not change the verifier-facing evidence chain at all. Verifiers consume the same provenance.json and evidence files and run the same checks (see Evidence Chain and Verification). What it changes is the requester-facing trust posture. Confidentiality of the source is enforced cryptographically rather than by trusting the host, so a build can run inside infrastructure the requester would otherwise be unwilling to send code to.

The confidential flow is opt-in. Public open-source builds can use the simpler path described under Build Flow with no loss of integrity guarantees, and only requester with sensitive inputs incur the extra round trip and the additional pre-launch verification step.

References