Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

confidential-space-verify

Offline verifier for Google Confidential Space attestation tokens.

A Confidential Space workload proves what it is by presenting a signed attestation token. Google's documented verification path is online: fetch the signer's JWKS over the network and trust the transport. Google ships no library for verifying these tokens offline, which is exactly what an auditor, a relying party with no network egress, or anyone re-checking historical evidence needs. This package is that missing piece:

  • No network, ever. The token must carry its full x5c certificate chain. There is no JWKS fallback and no fetch of any kind.
  • Pinned PKI root. The chain must terminate in a certificate whose SHA-256 fingerprint matches Google's published Confidential Space attestation root (confidential_space_root.pem), compiled in as GOOGLE_CONFIDENTIAL_SPACE_PKI_ROOT_SHA256.
  • Exact workload matching. Image digest, GCE project, service account, audience, and the container's effective environment variables are compared against a caller-supplied policy; every relaxation is explicit.
  • Dependency-free. Pure node:crypto (X509Certificate, createVerify, timingSafeEqual). No runtime dependencies.

Usage

import { verifyConfidentialSpaceAttestation } from "confidential-space-verify";

const verification = verifyConfidentialSpaceAttestation({
  token: attestationJwt,
  // The nonce your protocol asked the workload to bind, e.g. the SHA-256 of
  // the document the workload produced alongside this token.
  expectedNonce: documentSha256,
  // When that document claims to have been produced. The token must have
  // been issued within [-1 minute, +20 minutes] of this instant.
  referenceTime: document.issuedAt,
  policy: {
    audience: "https://verifier.example.org",
    imageDigest: "sha256:…",
    projectId: "my-workload-project",
    serviceAccount: "workload@my-workload-project.iam.gserviceaccount.com",
    expectedEnvironment: { WORKLOAD_MODE: "production" },
  },
});
// verification: { audience, certificateRootSha256, debugStatus, imageDigest,
//                 issuedAt, projectId, serviceAccounts, subject }

verifyConfidentialSpaceAttestation throws an Error with a stable snake_case message (for example unexpected_attestation_root_certificate, attestation_nonce_mismatch, unexpected_attestation_environment:NAME) as soon as any check fails, and returns the verified facts otherwise.

Policy defaults

Only the four workload identity fields are required. Everything else defaults to the strictest setting:

Field Default Meaning
expectedEnvironment {} Required effective env vars (override-aware).
requireExactEnvironment true Reject operator env_override names outside expectedEnvironment.
debugAllowed false Require dbgstat: disabled-since-boot.
stable true Require the STABLE image support attribute.
memoryMonitoringDisabled true Require monitoring_enabled.memory === false.
trustedRootCertificateSha256 pinned Google root Accepted PKI root fingerprints.

Checks performed

Compact JWS shape and RS256 under the Google issuer; an x5c chain of exactly leaf + intermediate + root terminating in the pinned fingerprint, with every link's issuance and signature verified; coherent time claims, certificate validity at issuance, and issuance within one minute before to twenty minutes after referenceTime; timing-safe eat_nonce binding; and the full workload policy — CONFIDENTIAL_SPACE software name, debug status, image digest, project, service account, effective environment (image env overlaid with operator env_override), support attributes, and memory monitoring.

Threat model

The verifier assumes the attacker controls the token bytes and the network, and may operate Confidential Space workloads of their own. It defends:

  • Substituted workloads — a token from a different image, project, service account, or with unexpected environment variables is rejected even though Google legitimately signed it.
  • Forged or re-anchored chains — a syntactically valid chain that does not terminate in the pinned Google root is rejected; so is any broken link or a payload not signed by the leaf.
  • Replayed tokens — the eat_nonce binding ties the token to the caller's own payload hash, and the referenceTime window rejects tokens issued at a different time than the evidence they claim to support.
  • Downgraded environments — debug mode, non-STABLE images, enabled memory monitoring, and operator environment injection are rejected by default.

Out of scope: compromise of Google's attestation root key, vulnerabilities in the attested workload itself, and revocation (the pinned fingerprint is the trust decision; rotate it deliberately).

Verifying the pinned root

Do not take this repository's word for the fingerprint. Fetch the root independently and compare:

curl -fsSLO https://confidentialcomputing.googleapis.com/.well-known/confidential_space_root.pem
openssl x509 -in confidential_space_root.pem -noout -fingerprint -sha256

The output must equal GOOGLE_CONFIDENTIAL_SPACE_PKI_ROOT_SHA256 (14:8B:29:38:…:6C:39).

API

  • verifyConfidentialSpaceAttestation({ token, expectedNonce, referenceTime, policy })
  • attestationIssuedAt(token)iat as a Date, without verification.
  • parseAttestationJwt(token) — decode header/payload/signature, without verification.
  • normalizeCertificateFingerprint(value) — canonical AA:BB:… form.
  • GOOGLE_CONFIDENTIAL_SPACE_ISSUER, GOOGLE_CONFIDENTIAL_SPACE_PKI_ROOT_SHA256
  • Types: ConfidentialSpaceAttestationPolicy, ConfidentialSpaceAttestationVerification

Development

bun install
bun run check   # tsc --noEmit && bun test

The test suite builds a throwaway three-tier RSA PKI with openssl and signs synthetic attestation tokens against it, so it runs fully offline too.

Related repositories

License

Apache-2.0. See LICENSE.

About

Offline verifier for Google Confidential Space attestation tokens

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages