---
title: "Software supply-chain security"
description: "How Artifact Server protects source changes, records package evidence, and verifies archives."
---

> Documentation Index
> Fetch the complete documentation index at: https://artifactserver.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Software supply-chain security

Artifact Server includes workflow, dependency, package, and container integrity in its security model. This page documents the controls available in the repository today. It separates continuous-integration evidence from public release proof.

- **Changes are tested** — Pull requests run five parallel product jobs and the macOS job. Changes to `main` run the complete Linux iteration gate.
- **Secrets are scanned** — Gitleaks scans the complete Git history. The workflow verifies the checksum of the downloaded binary. A synthetic token proves the detector before the repository scan.
- **Workflows are audited** — zizmor audits GitHub workflows and Dependabot settings in strict offline mode. A synthetic unsafe workflow proves the detector first.
- **Dependencies are reviewed** — Dependabot scans pnpm and GitHub Actions each week. Routine version updates wait seven days before opening a pull request.

## Pull-request verification

The [CI workflow](https://github.com/plannotator/artifact-server/actions/workflows/ci.yml) uses read-only repository permissions. It pins third-party actions to complete commit SHAs. Checkout does not persist credentials. Dependencies install from the committed lockfile.

The pull-request workflow runs these required jobs:

- Build and static policy.
- Unit and conformance behavior.
- Browser behavior.
- Cloudflare deployment behavior.
- macOS portability.

The complete Linux gate runs after a change reaches `main`. It also runs each day, during a manual full run, and before a release.

The complete gate uses `pnpm verify:iteration`. It includes package, storage, Compose, Helm, OIDC, coverage, and bounded performance verification.

The separate [security workflow](https://github.com/plannotator/artifact-server/actions/workflows/security.yml) runs on the same change events and every Monday:

- Gitleaks scans all repository history with findings redacted from logs.
- zizmor audits workflow and Dependabot files without sending source to a hosted scanner.
- The workflow downloads both scanners at pinned versions and verifies them with SHA-256 before use.
- Both scanners must detect a synthetic problem before their real analysis can pass.

See the [Actions history](https://github.com/plannotator/artifact-server/actions) for individual runs and logs.

## Evidence in package outputs

Artifact Server creates two package formats. Each package includes a machine-readable manifest next to the archive.

| Package | Command | Evidence |
| --- | --- | --- |
| Portable Node archive | `pnpm package:local` | Archive SHA-256, size, package name and version, Node.js requirement, and native-extension status. |
| Multi-platform OCI archive | `pnpm package:oci` | Archive SHA-256, image-index digest, source revision, source-tree status, `linux/amd64` and `linux/arm64` manifests, and the embedded attestation predicate types. |

The OCI builder requests maximum-mode BuildKit provenance and an SPDX software bill of materials for each platform. Before it writes the package manifest, Artifact Server verifies every OCI blob digest and requires both of these predicates:

```text
https://slsa.dev/provenance/v1
https://spdx.dev/Document
```

It also verifies the image entry point, non-root runtime user, working directory, product version, source revision, and source-tree status. The build fails if any required platform, digest, runtime property, or attestation is missing.

## Verify an archive checksum

Build either package from a source checkout:

```sh
pnpm install --frozen-lockfile
pnpm package:local
# or: pnpm package:oci
```

Then compare the archive with its adjacent manifest. This Node.js command works for both package formats:

```sh
node -e '
  const crypto = require("node:crypto");
  const fs = require("node:fs");
  const [archive, manifestPath] = process.argv.slice(1);
  const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
  const expected = manifest.sha256 ?? manifest.archiveSha256;
  const actual = crypto.createHash("sha256")
.update(fs.readFileSync(archive))
.digest("hex");
  if (actual !== expected) throw new Error("Archive checksum mismatch");
  console.log(actual);
' release/<archive> release/<archive>.manifest.json
```

For an OCI build, `pnpm package:oci` also runs the repository's attestation and image-layout verifier before returning. Open the generated `.manifest.json` to inspect the verified revision, platforms, and `attestationPredicates` values.

> **What a checksum proves**
>
> A matching checksum proves that the archive matches its manifest. Until the manifest is published through an authenticated release channel, it does not prove who created either file.

## Public release verification

No tagged public Artifact Server release exists. The release workflow passed private qualification. No public archive or image is available for external verification.

The team will add release commands after the public assets exist. These commands will download checksums and verify GitHub attestations and the immutable GHCR image. Until then, source-build evidence is the available verification boundary.

## Reporting and product boundaries

Supply-chain controls complement the product's [two-origin security boundary](/docs/concepts/security-boundary/index.md). They do not replace authentication, authorization, content isolation, or deployment hardening.

Read the repository's [security policy](https://github.com/plannotator/artifact-server/blob/main/SECURITY.md) before reporting a vulnerability. Do not include real credentials, private artifact contents, or personal data in a report.

Source: https://artifactserver.com/docs/security/index.mdx
