Skip to main content
tracebloc is built so your data never has to leave your network. This page is the summary to hand to your security or compliance team.

What’s shared, what isn’t

How it’s enforced

  • Data locality. Training runs against your data on your hardware. Raw data never crosses the boundary.
  • Isolation. Each training job runs in its own container with restricted system access; Kubernetes namespaces separate workloads.
  • Network policy. The chart applies a Kubernetes NetworkPolicy that denies all inbound to training pods and restricts their outbound traffic — arbitrary pod-to-pod connections and the Kubernetes API are blocked, while the in-cluster MySQL that serves the training data and the in-cluster proxy that reports results and FLOPs stay reachable. Direct outbound HTTPS is still allowed by default today; a stricter lockdown that instead routes it through an in-cluster egress gateway ships with the chart and can be enabled per cluster, and enforcement requires a CNI that honors NetworkPolicy.
  • Model scanning. Submitted models are scanned for vulnerabilities (Bandit) before anything executes.
  • Signed images. Every training image is signed at build time with Sigstore cosign and ships with an SBOM and build provenance, so you can check what you run before you run it — see Verify a training image.
  • Encryption in transit. All workspace ↔ platform traffic is TLS, on an outbound-only connection.
  • Access control. Only contributors you whitelist by email can join a use case.
  • Minimal footprint. The installer touches only Docker and ~/.tracebloc — no system-wide changes.

You control what leaves

Trained weights are shared only when you choose to share them. Whom you collaborate with, and whether weights are downloadable, is set in the admin panel — per use case.

Support bundles are redacted

If support asks for diagnostics, --diagnose produces a bundle with credentials removed (passwords, tokens, and proxy secrets stripped before the archive is written). See Troubleshooting.

Outbound access

Your workspace needs outbound HTTPS to: *.docker.io, ghcr.io, raw.githubusercontent.com, *.github.io, *.tracebloc.io, and pypi.org. Nothing needs to reach in.

Verify a training image

Every training image tracebloc publishes under tracebloc/* on Docker Hub is signed with Sigstore cosign — keyless, with GitHub Actions as the identity provider. There is no private key to leak or rotate: each signature is bound to the GitHub Actions workflow that built the image and recorded in Sigstore’s public transparency log. Task images (tracebloc/client-<task>-cpu and -gpu) also carry a software bill of materials (SBOM) and build provenance as attestations; the base images they build on (tracebloc/base, tracebloc/nlp, tracebloc/cv) are signed the same way. You can check all of this yourself, on any machine, without asking us.
1

Install cosign

Follow the cosign installation guide. Any current release works — check with cosign version.
2

Pull the image and note its digest

Pull the tag you are about to run, then copy the Digest: line that docker pull prints:
Verify the digest that docker pull printed — not one copied from elsewhere. A tag@digest reference resolves by the digest alone and never checks the tag, so verifying a digest you got from somewhere else tells you nothing about the image behind the tag you are running — and docker image inspect’s RepoDigests can be empty (for example under the containerd image store). The Digest: line from your own pull is the only trustworthy source.
3

Verify the signature

With the example above filled in:
The two flags pin who may have signed: the OIDC issuer must be GitHub Actions, and the signing identity must be one of tracebloc’s two image-build workflows — docker-build.yml for task images, docker-build-base.yml for base images — on any branch of tracebloc’s image-build repository. The regexp accepts both the current repository name, tracebloc/tracebloc-engine, and its pre-rename name, tracebloc/tracebloc-client, so images signed before the rename still verify. A signature from anyone else is rejected, however valid it is on its own.
4

Read the result

On success cosign exits 0, lists the checks it performed, and prints a JSON array with the signing certificate’s Issuer and Subject:
A tampered, unsigned, or differently signed image fails: cosign exits with a non-zero code and an error such as no matching signatures. You never need to know how the signature is stored — cosign finds it whichever way it was attached to the registry (the tag-based layout or OCI referrers).

View the SBOM and provenance

Every task image (tracebloc/client-<task>-cpu and -gpu) carries two attestations, stored two different ways because two different tools write them:
  • The SBOM is a cosign attestation on the image digest, and it points at the base image’s SBOM by checksum. A task image is the base image (tracebloc/base, tracebloc/nlp or tracebloc/cv) plus tracebloc’s own code copied into /app — the task Dockerfiles install nothing, and a check in the publish pipeline refuses any change that would. So the packages of a task image are the packages of its base, and the attestation on a task digest is a small SPDX 2.3 document (a few kilobytes) with one package — the base image, by index digest and platform — and one external document reference: the base’s full SPDX SBOM, named by its own documentNamespace and by the SHA-256 of its exact bytes. It is signed with the same keyless identity as the image itself. Read it with cosign, using the digest you just verified:
    One in-toto statement is returned per platform (linux/amd64, and linux/arm64 for CPU images). A digest with no attestation fails with no matching attestations. This regexp is deliberately narrower than the one for cosign verify above, and should stay that way. It names one workflow rather than two, because only the task-image workflow attests — base images carry the SBOM this document references, and are not themselves attested. And it names only tracebloc/tracebloc-engine, without the pre-rename tracebloc/tracebloc-client alternative, because attestation shipped after the rename: no attestation has ever been signed under the old name, so accepting it would widen what you trust without making any image verifiable that is not already. A signing identity regexp is a trust boundary, so it should accept exactly the identities that really signed the artifact and no more. Then follow the reference to the full document:
    The full SBOM is the base image’s inline BuildKit attestation, exactly as buildx wrote it when the base was built. Read it with Docker’s own tooling, at the base digest the reference names (the same digest the task image’s provenance names under resolvedDependencies):
    (For a multi-platform index the output is a platform -> {SPDX} map; for a single platform it is {SPDX}.) Its documentNamespace is the externalDocumentRefs[0].spdxDocument of the reference. To check the bytes, not just the content: checksumValue is the SHA-256 of the SPDX attestation blob on the base index — an OCI blob, so its digest is that checksum, and any registry client can fetch it by that digest and hash it:
    (imagetools inspect re-serialises the JSON, so sha256sum of its output is not the checksum — compare the blob, or compare the layer digest it reports with --raw on the attestation manifest.) A checksum that does not match means the base SBOM you fetched is not the one the task image was attested against; a purl whose digest is not the one in the task image’s provenance means the attestation is not about the base this image was built from.
  • The build provenance lives inside the image index as a BuildKit attestation, so you read it with Docker’s own tooling:
    It is SLSA v1 and records how, and from what, the image was built — including the exact digest of the base image, under buildDefinition.resolvedDependencies (pkg:docker/tracebloc/<base>@<tag>?platform=...). That is the digest the attested SBOM reference names, and the publish pipeline refuses to attest a reference to any other.
The base images carry their SBOM inline, the way the task images did before September 2026, so the same BuildKit command reads it per platform:
Why by reference. cosign attest uploads the whole signed statement — the predicate inline — to the Rekor transparency log, and Rekor has a size ceiling: the CPU bases’ SPDX documents are 21-26 MB per platform and every attempt to attest one was refused (the 10-15 MB GPU documents went through). The full document therefore stays where buildx wrote it, inline on the base image, and the attestation binds the task digest to those exact bytes by checksum. Nothing is lost in transparency: the reference is in Rekor under the workflow’s identity, and the bytes it names are content-addressed in the registry.
Transition, one release. Task digests published before this change (still behind :stg and :prod until the next promotions) carry the SBOM inline, so docker buildx imagetools inspect ... --format '{{ json .SBOM }}' answers for them and cosign verify-attestation --type spdxjson does not; digests published after it are the other way round. If one command returns nothing, try the other. A few GPU digests published on 2026-09-08 carry the full base document as the cosign predicate (no externalDocumentRefs): for those, sbom-ref.json already is the SBOM. The SBOM content is the same in every form: the packages of the base image the task image layers on.

Signatures follow the digest, not the tag

Signatures are attached per digest, so re-tagging an image never breaks verification — the same verified digest stays verified under any tag.