pluginarchive

package
v0.2.0-alpha.8 Latest Latest
Warning

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

Go to latest
Published: Sep 6, 2026 License: Apache-2.0 Imports: 12 Imported by: 0

Documentation

Overview

Package archive packs and extracts a plugin package.

A published release is bytes somebody else produced, so extraction is the place this feature can be attacked. Every guard here exists because a tar reader that trusts its input will happily write outside the directory it was given, follow a link into somebody's home, or expand a kilobyte into a disk.

It depends only on the standard library so both sides can run it: the client packs and installs, and internal/server validates the same bytes without reaching into internal/config.

Index

Constants

View Source
const DigestPrefix = "sha256:"

DigestPrefix labels the one hash this format uses. Recording the algorithm beside the value means a later change cannot be mistaken for a mismatch.

View Source
const GitDir = ".git"

GitDir is excluded when packing. A checkout's history is not plugin content, it is usually larger than everything that is, and it carries branches and remotes the author never meant to publish.

Variables

View Source
var (
	ErrTraversal    = errors.New("archive entry escapes the destination")
	ErrLink         = errors.New("archive contains a link")
	ErrIrregular    = errors.New("archive contains a file that is not a regular file or directory")
	ErrDuplicate    = errors.New("archive contains the same path twice")
	ErrTooManyFiles = errors.New("archive holds more files than the limit allows")
	ErrTooLarge     = errors.New("archive is larger than the limit allows")
	ErrPathTooLong  = errors.New("archive entry path is longer than the limit allows")
	ErrDigest       = errors.New("digest does not match")
)

Violations extraction refuses. Each is a way an archive can reach outside what it was given.

Functions

func Digest

func Digest(r io.Reader) (string, error)

Digest reads r fully and returns its labelled hash.

func VerifyDigest

func VerifyDigest(r io.Reader, want string) error

VerifyDigest reports whether r hashes to want.

Types

type Limits

type Limits struct {
	MaxFiles           int
	MaxFileBytes       int64
	MaxTotalBytes      int64
	MaxCompressedBytes int64
	MaxPathLength      int
}

Limits bound what an archive may cost to accept. Zero fields take the default, so a caller cannot accidentally disable a guard by leaving one out.

func ResolveLimits

func ResolveLimits(lim Limits) Limits

ResolveLimits fills in the zero fields of lim, so a caller outside this package can see the same bounds extraction will apply.

type Summary

type Summary struct {
	Files int
	Bytes int64
	// Digest is set by Pack, over exactly the bytes it wrote.
	Digest string
}

Summary describes what was packed or extracted.

func Extract

func Extract(r io.Reader, destDir string, lim Limits) (Summary, error)

Extract writes an archive into destDir, which must already exist.

Nothing in the archive decides where a byte lands: every path is cleaned and checked against the destination before a file is opened, links are refused outright rather than resolved, and modes come from the extractor rather than from the header.

func Pack

func Pack(w io.Writer, root fs.FS, lim Limits) (Summary, error)

Pack writes root as a gzipped tar and returns the digest of what it wrote.

The output is deterministic: entries are walked in lexical order, timestamps and ownership are zeroed, and modes are normalised. Packing one tree twice therefore produces one digest, which is what lets a publisher and a consumer compare notes about the same release.

Jump to

Keyboard shortcuts

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