SPB Git

Repository Public MIT

0007-archive-format-and-static-validation.md 3.0 KB

# ADR-0007 — Archive format and in-memory static validation

Status: accepted, 2026-11-09.

# Format

A release is one gzip-compressed tar (.tar.gz) holding the package directory. agent-registry.json at the root is the registry's wrapper manifest; upstream files (SKILL.md, package.json, pyproject.toml, MCP configuration) are preserved as they are.

The packer (writeArchive) is deterministic: entries sorted by path, mtime 0, uid/gid 0, modes normalised to 0644 or 0755, fixed gzip header. Packing the same directory twice gives the same bytes and therefore the same SHA-256.

# Reader

packages/registry-core/src/tar.ts is a small strict reader written for this project rather than a general tar library:

  • It never touches the filesystem. Bytes in, list of {path, mode, data} out.
  • Decompression has a hard output cap, so a gzip bomb fails early.
  • Regular files and directories only. Symlinks, hardlinks, devices, FIFOs and any other entry type abort the read. Base-256 size fields are refused.
  • Header checksums are verified; a missing end-of-archive marker is an error.
  • Limits: 20 MiB compressed, 64 MiB unpacked, 16 MiB per file, 2000 files.
  • Paths are reported exactly as stored. The reader does not normalise them, so the validator sees what an extractor would see.

# Validation

validatePackage is a pure function over the file list:

  • Path safety: no absolute paths, .., backslashes, control characters, drive letters, empty segments, non-NFC names, reserved device names, case-insensitive collisions; depth 16, length 240.
  • Forbidden files: .git/, node_modules/, .env* (except .env.example, .env.sample, .env.template), .npmrc, .netrc, .ssh/, .aws/, private key files.
  • Manifest: strict zod schema, unknown keys rejected, 64 KiB cap. The manifest name and version must equal the artifact and version being published to.
  • Type rules: a skill needs a spec-compliant SKILL.md whose name equals the slug; an MCP server needs an mcp block and a README; other types need a README; a bundle needs exact-version dependencies.
  • Static scan of every text file: credential patterns (blocking), risky behaviour patterns and prompt-injection phrases (advisory).

The server additionally checks that the manifest type equals the artifact type and that dependencies resolve to visible artifacts with a satisfying published version.

# Outcomes

  • Any blocking finding: the upload is rejected, the staged bytes are deleted, nothing is published.
  • Advisory findings with one of these codes send the release to quarantine for a moderator: exec-pipe-to-shell, exec-encoded-payload, exec-destructive, exec-eval-remote, cred-access, prompt-exfiltration, prompt-concealment, prompt-override, text-bidi-control.
  • Otherwise the release is published with status passed (no findings of medium severity or above) or flagged.

# Non-goals

No package content is executed, imported, rendered as HTML or extracted to disk on the server. The scanner is advisory; passed means "no advisory findings from static checks", never "safe".

Files main
Menu

Theme