pack

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 21, 2026 License: Apache-2.0 Imports: 14 Imported by: 0

Documentation

Overview

Package pack implements the offline data bundle: a signed, self-describing archive of the reference data a scanner needs and cannot look up.

The problem it solves is narrow and specific. Everything Tessera computes from a model file is local — parsing, drift, hashing, the walk for executable payloads. Three things are not: matching a component against known vulnerabilities, matching bytes against malware signatures, and any rule set that is updated more often than the binary. Every tool in this space solves those by reaching out to a service, which is exactly what an air-gapped enclave forbids.

A bundle is how that data crosses the gap. It is one file, it carries a manifest describing what is inside and where each part came from, and the manifest is signed. The verifier re-derives every digest from the bytes it actually received rather than trusting what the manifest claims, because a manifest that is only read is a table of contents, not evidence.

The format is deliberately dull: a tar archive, gzip-compressed, with the manifest first. A dull format can be inspected with tools the enclave already has when this program is unavailable, which is a real consideration on the far side of an air gap.

Index

Constants

View Source
const FormatVersion = 1

FormatVersion guards the bundle format itself. A reader that does not recognize the version refuses rather than guessing, because guessing at the layout of a signed archive is how a downgrade begins.

View Source
const ManifestName = "tessera-bundle.json"

ManifestName is the entry every bundle carries first.

Variables

This section is empty.

Functions

This section is empty.

Types

type Entry

type Entry struct {
	// Path is the entry's location inside the bundle, always slash-separated
	// and always relative.
	Path string `json:"path"`
	Size int64  `json:"size"`
	// SHA256 is what the surrounding ecosystem reads. SHA512 is what BSI
	// TR-03183-2 requires. Both are recorded, computed in one pass, because a
	// bundle carrying only one of them is unusable to somebody who needs the
	// other and there is no way to add it later without the original bytes.
	SHA256 string `json:"sha256"`
	SHA512 string `json:"sha512"`
}

Entry is one file in the bundle.

type Kind

type Kind string

Kind names what a bundle carries. It is advisory — the manifest lists the actual entries — but a consumer that wanted a vulnerability database and received a rule pack should be able to say so before unpacking anything.

const (
	KindVulnerability Kind = "vulnerability-database"
	KindMalware       Kind = "malware-signatures"
	KindRules         Kind = "rule-pack"
	KindMixed         Kind = "mixed"
)

type Manifest

type Manifest struct {
	FormatVersion int    `json:"formatVersion"`
	Kind          Kind   `json:"kind"`
	Name          string `json:"name"`
	Version       string `json:"version,omitempty"`
	Description   string `json:"description,omitempty"`
	// CreatedAt is when the bundle was assembled, distinct from when its
	// contents were retrieved.
	CreatedAt string   `json:"createdAt"`
	Sources   []Source `json:"sources,omitempty"`
	Entries   []Entry  `json:"entries"`
}

Manifest describes a bundle. It is the signed object: signing the manifest rather than the archive means verification needs one signature regardless of how many files are inside, and the per-entry digests below extend that signature to cover every one of them.

func Create

func Create(root string, meta Manifest, out io.Writer) (*Manifest, error)

Create writes a bundle containing the files under root.

Entry order is sorted so the same inputs produce the same archive: a bundle that differed run to run could not be compared against a previously approved one, and comparing is most of what a reviewer on the far side of a gap can do.

func Extract

func Extract(r io.ReadSeeker, dest string) (*Manifest, error)

Extract verifies a bundle and writes its contents under dest.

Verification happens first and completely. Writing files as they are read would leave a partially unpacked, partially verified tree on disk when an entry fails, and something downstream would eventually read it.

func Verify

func Verify(r io.Reader) (*Manifest, error)

Verify reads a bundle and re-derives every digest from the bytes actually present, returning the manifest only if all of them agree.

The manifest is not trusted to describe itself. An entry whose recorded digest does not match the bytes is a failure, and so is an entry present in the archive that the manifest never mentions — an undocumented file is the shape a smuggled payload takes, and a verifier that only checked the listed entries would walk straight past it.

func (*Manifest) TotalSize

func (m *Manifest) TotalSize() int64

TotalSize is the sum of the entries' sizes.

type Source

type Source struct {
	// Name identifies the upstream data set, e.g. "osv.dev" or "clamav-main".
	Name string `json:"name"`
	// URL is where it was obtained, when there is one.
	URL string `json:"url,omitempty"`
	// Version is the upstream's own version or snapshot identifier.
	Version string `json:"version,omitempty"`
	// RetrievedAt is when it was fetched. Required: a data bundle without a
	// retrieval date cannot be assessed for staleness, which is the first
	// question anybody sensible asks of one.
	RetrievedAt string `json:"retrievedAt"`
}

Source records where the data in a bundle came from, so somebody on the far side of an air gap can tell what they are trusting.

This is the field that makes a bundle auditable rather than merely portable. A vulnerability database is a claim about the world, and a claim with no stated origin and no date is not one a reviewer can act on — it could be today's feed or three years stale, and the bytes look identical.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL