Test: Add installer provenance boundary

This commit is contained in:
Gabriel Brown
2026-08-27 05:43:26 -04:00
parent fc8f226747
commit 27acbe7a95
20 changed files with 915 additions and 0 deletions
+109
View File
@@ -0,0 +1,109 @@
#!/usr/bin/env bash
# Reviewed installer inputs are data, never shell code. Consumers source this
# library, load the data through its parser, and verify each fetched artifact
# before any privileged operation can see it.
declare -gA INSTALLER_PROVENANCE=()
key_fingerprint_matches() {
local file="$1" expected="$2" actual
actual="$(gpg --batch --with-colons --import-options show-only --import "$file" 2>/dev/null \
| awk -F: '$1 == "fpr" { print $10; exit }')"
[[ "$actual" == "$expected" ]]
}
verify_detached_signature() {
local key="$1" signature="$2" content="$3" home
home="$(mktemp -d)" || return 1
chmod 700 "$home"
GNUPGHOME="$home" gpg --batch --quiet --import "$key" >/dev/null 2>&1 \
&& GNUPGHOME="$home" gpg --batch --verify "$signature" "$content" >/dev/null 2>&1
local status=$?
rm -rf -- "$home"
return "$status"
}
download_sha256() {
local url="$1" expected="$2" max_bytes="$3" destination="$4" actual
[[ "$expected" =~ ^[0-9a-f]{64}$ ]] || return 1
actual="$expected"
local part="${destination}.part"
(
trap 'rm -f -- "$part"' EXIT
trap 'exit 130' INT
trap 'exit 143' TERM
[[ "$max_bytes" =~ ^[1-9][0-9]*$ ]] || exit 1
[[ -n "$destination" && -d "$(dirname "$destination")" ]] || exit 1
curl --fail --location --connect-timeout 10 --max-time 600 \
--max-filesize "$max_bytes" --output "$part" "$url" \
|| exit 1
[[ -f "$part" ]] || exit 1
[[ "$(stat -c %s "$part")" -le "$max_bytes" ]] || exit 1
[[ "$(sha256sum "$part" | awk '{ print $1 }')" == "$actual" ]] || exit 1
mv -f -- "$part" "$destination"
)
}
rpm_signature_matches() {
local package="$1" key="$2" expected="$3" home db output status
key_fingerprint_matches "$key" "$expected" || return 1
home="$(mktemp -d)" || return 1
chmod 700 "$home"
db="$home/rpmdb"
mkdir -m 700 "$db" || {
rm -rf -- "$home"
return 1
}
rpmkeys --dbpath "$db" --import "$key" >/dev/null 2>&1 \
&& output="$(rpmkeys --dbpath "$db" --checksig --verbose "$package" 2>&1)"
status=$?
rm -rf -- "$home"
(( status == 0 )) || return 1
grep -Eqi 'OpenPGP.*signature.*: OK' <<<"$output"
}
load_installer_provenance() {
local file="$1" line name value required
local -A parsed=() allowed=() required_values=()
for name in \
BUN_VERSION BUN_X86_64_URL BUN_X86_64_SHA256 BUN_X86_64_MAX_BYTES \
BUN_AARCH64_URL BUN_AARCH64_SHA256 BUN_AARCH64_MAX_BYTES \
NODE_VERSION NODE_X86_64_URL NODE_X86_64_SHA256 NODE_X86_64_MAX_BYTES \
NODE_AARCH64_URL NODE_AARCH64_SHA256 NODE_AARCH64_MAX_BYTES \
CODEX_VERSION CODEX_X86_64_URL CODEX_X86_64_SHA256 CODEX_X86_64_MAX_BYTES \
CODEX_AARCH64_URL CODEX_AARCH64_SHA256 CODEX_AARCH64_MAX_BYTES \
RUSTDESK_VERSION RUSTDESK_X86_64_URL RUSTDESK_X86_64_SHA256 RUSTDESK_X86_64_MAX_BYTES \
FEDORA_RELEASE RPMFUSION_FREE_RELEASE_URL RPMFUSION_FREE_RELEASE_MAX_BYTES \
RPMFUSION_NONFREE_RELEASE_URL RPMFUSION_NONFREE_RELEASE_MAX_BYTES TERRA_BASEURL \
HYPRLAND_COPR_BASEURL FLATHUB_DESCRIPTOR_URL FLATHUB_DESCRIPTOR_MAX_BYTES \
CLAUDE_CODE_BASEURL CLAUDE_DESKTOP_BASEURL TERRA_FINGERPRINT CLAUDE_CODE_FINGERPRINT \
BUN_FINGERPRINT RPMFUSION_FREE_FINGERPRINT RPMFUSION_NONFREE_FINGERPRINT \
HYPRLAND_COPR_FINGERPRINT FLATHUB_FINGERPRINT CLAUDE_DESKTOP_FINGERPRINT; do
allowed["$name"]=1
required_values["$name"]=1
done
[[ -r "$file" ]] || return 1
while IFS= read -r line || [[ -n "$line" ]]; do
[[ "$line" == *=* && "${line#*=}" != *=* ]] || return 1
IFS='=' read -r name value <<<"$line"
[[ -n "${allowed[$name]:-}" && -n "$value" && -z "${parsed[$name]:-}" ]] || return 1
[[ "$value" != *'$('* && "$value" != *'`'* ]] || return 1
parsed["$name"]="$value"
done < "$file"
for required in "${!required_values[@]}"; do
[[ -n "${parsed[$required]:-}" ]] || return 1
done
INSTALLER_PROVENANCE=()
for name in "${!parsed[@]}"; do
INSTALLER_PROVENANCE["$name"]="${parsed[$name]}"
done
}
+74
View File
@@ -0,0 +1,74 @@
# Installer provenance
Reviewed on 2026-08-27. `installers.conf` is data, not a shell fragment: the
installer reads it only with `load_installer_provenance`. Its versions, URLs,
SHA-256 values, byte limits, and complete primary fingerprints are reviewed
inputs. No installer path may substitute a `latest` URL or execute fetched
content before the applicable verification succeeds.
## Key retrieval and verification
Each command below was run in a private temporary directory on 2026-08-27.
The resulting armored public key is vendored under `keys/`; each output was
checked with the listed complete primary fingerprint before it was committed.
| Key | Source URL | Expected primary fingerprint | Verification command |
| --- | --- | --- | --- |
| Terra 44 | `https://repos.fyralabs.com/terra44/key.asc` | `AE09157A4DE88B497EA1D5D300CDAB43DE226D6F` | `gpg --batch --with-colons --import-options show-only --import terra44.asc \| awk -F: '$1 == "fpr" { print $10; exit }'` |
| Anthropic Claude Code | `https://downloads.claude.ai/keys/claude-code.asc` | `31DDDE24DDFAB679F42D7BD2BAA929FF1A7ECACE` | `gpg --batch --with-colons --import-options show-only --import claude-code.asc \| awk -F: '$1 == "fpr" { print $10; exit }'` |
| Bun releases | `https://keys.openpgp.org/vks/v1/by-fingerprint/F3DCC08A8572C0749B3E18888EAB4D40A7B22B59` | `F3DCC08A8572C0749B3E18888EAB4D40A7B22B59` | `gpg --batch --with-colons --import-options show-only --import bun.asc \| awk -F: '$1 == "fpr" { print $10; exit }'` |
| RPM Fusion free | `https://download1.rpmfusion.org/free/fedora/RPM-GPG-KEY-rpmfusion-free-fedora-2020` | `E9A491A3DE247814E7E067EAE06F8ECDD651FF2E` | `gpg --batch --with-colons --import-options show-only --import rpmfusion-free.asc \| awk -F: '$1 == "fpr" { print $10; exit }'` |
| RPM Fusion nonfree | `https://download1.rpmfusion.org/nonfree/fedora/RPM-GPG-KEY-rpmfusion-nonfree-fedora-2020` | `79BDB88F9BBF73910FD4095B6A2AF96194843C65` | `gpg --batch --with-colons --import-options show-only --import rpmfusion-nonfree.asc \| awk -F: '$1 == "fpr" { print $10; exit }'` |
| lionheartp/Hyprland COPR | `https://download.copr.fedorainfracloud.org/results/lionheartp/Hyprland/pubkey.gpg` | `97E23476C89635135407C7D5E9BA41342C4B2995` | `gpg --batch --with-colons --import-options show-only --import hyprland-copr.asc \| awk -F: '$1 == "fpr" { print $10; exit }'` |
| Flathub | `https://flathub.org/repo/flathub.flatpakrepo` | `6E5C05D979C76DAF93C081354184DD4D907A7CAE` | `awk -F= '/^GPGKey=/{print $2}' flathub.flatpakrepo \| base64 --decode \| gpg --batch --with-colons --import-options show-only --import \| awk -F: '$1 == "fpr" { print $10; exit }'` |
| Claude Desktop Extra | `https://patrickjaja.github.io/claude-desktop-extra/gpg-key.asc` | `825A7D15D78BABE45646D5DF382409F597908867` | `gpg --batch --with-colons --import-options show-only --import claude-desktop.asc \| awk -F: '$1 == "fpr" { print $10; exit }'` |
The retrieval command for every direct key was:
```bash
curl --fail --location --connect-timeout 10 --max-time 60 --output KEY.asc SOURCE_URL
```
## Reviewed publisher records and artifact locations
The key sources above are supported by these publisher-controlled records:
- `https://github.com/terrapkg/packages/blob/frawhide/README.md`
- `https://github.com/terrapkg/packages/discussions/7736`
- `https://code.claude.com/docs/en/setup`
- `https://github.com/oven-sh/bun/releases/tag/bun-v1.4.0`
- `https://github.com/oven-sh/bun/blob/main/dockerhub/distroless/Dockerfile`
- `https://github.com/nodejs/node/releases/tag/v24.20.0`
- `https://github.com/nodejs/node/blob/main/README.md`
- `https://github.com/openai/codex/releases/tag/rust-v0.150.1`
- `https://github.com/openai/codex/blob/main/.github/workflows/rust-release.yml`
- `https://github.com/rustdesk/rustdesk/releases/tag/1.4.9`
The reviewed immutable artifact and repository URLs are:
- `https://github.com/oven-sh/bun/releases/download/bun-v1.4.0/bun-linux-x64.zip`
- `https://github.com/oven-sh/bun/releases/download/bun-v1.4.0/bun-linux-aarch64.zip`
- `https://nodejs.org/dist/v24.20.0/node-v24.20.0-linux-x64.tar.xz`
- `https://nodejs.org/dist/v24.20.0/node-v24.20.0-linux-arm64.tar.xz`
- `https://github.com/openai/codex/releases/download/rust-v0.150.1/codex-package-x86_64-unknown-linux-musl.tar.gz`
- `https://github.com/openai/codex/releases/download/rust-v0.150.1/codex-package-aarch64-unknown-linux-musl.tar.gz`
- `https://github.com/rustdesk/rustdesk/releases/download/1.4.9/rustdesk-1.4.9-0.x86_64.rpm`
- `https://mirrors.rpmfusion.org/free/fedora/rpmfusion-free-release-44.noarch.rpm`
- `https://mirrors.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-44.noarch.rpm`
- `https://repos.fyralabs.com/terra44`
- `https://download.copr.fedorainfracloud.org/results/lionheartp/Hyprland/fedora-$releasever-$basearch/`
- `https://downloads.claude.ai/claude-code/rpm/stable`
- `https://patrickjaja.github.io/claude-desktop-extra/rpm/`
Artifact digests were checked with `sha256sum ARTIFACT` against the lowercase
64-hex values in `installers.conf`; all runtime downloads also enforce the
recorded byte limit before atomic replacement.
## Rotation policy
Do not replace a key on an automated update. A key rotation is a reviewed
repository change: obtain the new key from the publisher record, independently
confirm its complete primary fingerprint, update the vendored key and
`installers.conf` together, refresh this retrieval record, and add a focused
contract case if the verification behavior changes. Until that review lands,
verification fails closed and preserves any known-good destination.
+44
View File
@@ -0,0 +1,44 @@
BUN_VERSION=1.4.0
BUN_X86_64_URL=https://github.com/oven-sh/bun/releases/download/bun-v1.4.0/bun-linux-x64.zip
BUN_X86_64_SHA256=2d03fb5fb83ac8b567aca0a281b2ce1a1a19d488f56c2968d88c3f25e92fe452
BUN_X86_64_MAX_BYTES=67108864
BUN_AARCH64_URL=https://github.com/oven-sh/bun/releases/download/bun-v1.4.0/bun-linux-aarch64.zip
BUN_AARCH64_SHA256=4b1a332ee861983eb93bcfe6f770fff94e3e31b2c388bdaea3c8ed35e58eed0e
BUN_AARCH64_MAX_BYTES=67108864
NODE_VERSION=24.20.0
NODE_X86_64_URL=https://nodejs.org/dist/v24.20.0/node-v24.20.0-linux-x64.tar.xz
NODE_X86_64_SHA256=2f2c0da162318f0de47665410c7c8c2ed3d36c8f3105de4bbc61176c70a7cbf2
NODE_X86_64_MAX_BYTES=67108864
NODE_AARCH64_URL=https://nodejs.org/dist/v24.20.0/node-v24.20.0-linux-arm64.tar.xz
NODE_AARCH64_SHA256=5f4ddab610c1ab2016b3c227cebdbf6d9495161487e4739c7b90090595f465f7
NODE_AARCH64_MAX_BYTES=67108864
CODEX_VERSION=0.150.1
CODEX_X86_64_URL=https://github.com/openai/codex/releases/download/rust-v0.150.1/codex-package-x86_64-unknown-linux-musl.tar.gz
CODEX_X86_64_SHA256=00aba704f029f6dc0d948be407a756e0c97cc840132fd691353b2c6b0a505b17
CODEX_X86_64_MAX_BYTES=134217728
CODEX_AARCH64_URL=https://github.com/openai/codex/releases/download/rust-v0.150.1/codex-package-aarch64-unknown-linux-musl.tar.gz
CODEX_AARCH64_SHA256=1ecac3f87823efb98153233b076ea3d6e34a7a8cebe43c5285dc5f79e1514639
CODEX_AARCH64_MAX_BYTES=134217728
RUSTDESK_VERSION=1.4.9
RUSTDESK_X86_64_URL=https://github.com/rustdesk/rustdesk/releases/download/1.4.9/rustdesk-1.4.9-0.x86_64.rpm
RUSTDESK_X86_64_SHA256=eb1b053ac5b2f774f2271f7fbbfd2ea475899f7a55135c5e172bc54b9388f108
RUSTDESK_X86_64_MAX_BYTES=134217728
FEDORA_RELEASE=44
RPMFUSION_FREE_RELEASE_URL=https://mirrors.rpmfusion.org/free/fedora/rpmfusion-free-release-44.noarch.rpm
RPMFUSION_FREE_RELEASE_MAX_BYTES=4194304
RPMFUSION_NONFREE_RELEASE_URL=https://mirrors.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-44.noarch.rpm
RPMFUSION_NONFREE_RELEASE_MAX_BYTES=4194304
TERRA_BASEURL=https://repos.fyralabs.com/terra44
HYPRLAND_COPR_BASEURL=https://download.copr.fedorainfracloud.org/results/lionheartp/Hyprland/fedora-$releasever-$basearch/
FLATHUB_DESCRIPTOR_URL=https://flathub.org/repo/flathub.flatpakrepo
FLATHUB_DESCRIPTOR_MAX_BYTES=1048576
CLAUDE_CODE_BASEURL=https://downloads.claude.ai/claude-code/rpm/stable
CLAUDE_DESKTOP_BASEURL=https://patrickjaja.github.io/claude-desktop-extra/rpm/
TERRA_FINGERPRINT=AE09157A4DE88B497EA1D5D300CDAB43DE226D6F
CLAUDE_CODE_FINGERPRINT=31DDDE24DDFAB679F42D7BD2BAA929FF1A7ECACE
BUN_FINGERPRINT=F3DCC08A8572C0749B3E18888EAB4D40A7B22B59
RPMFUSION_FREE_FINGERPRINT=E9A491A3DE247814E7E067EAE06F8ECDD651FF2E
RPMFUSION_NONFREE_FINGERPRINT=79BDB88F9BBF73910FD4095B6A2AF96194843C65
HYPRLAND_COPR_FINGERPRINT=97E23476C89635135407C7D5E9BA41342C4B2995
FLATHUB_FINGERPRINT=6E5C05D979C76DAF93C081354184DD4D907A7CAE
CLAUDE_DESKTOP_FINGERPRINT=825A7D15D78BABE45646D5DF382409F597908867
+15
View File
@@ -0,0 +1,15 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
Comment: F3DC C08A 8572 C074 9B3E 1888 8EAB 4D40 A7B2 2B59
Comment: Robobun <[email protected]>
xjMEY9GQFhYJKwYBBAHaRw8BAQdAkppAqaXl0RkROz6NfdvlwYd2UuUVfHLk2NNY
IzEdnT/NGVJvYm9idW4gPHJvYm9idW5Ab3Zlbi5zaD7CkwQTFgoAOxYhBPPcwIqF
csB0mz4YiI6rTUCnsitZBQJj0ZAWAhsDBQsJCAcCAiICBhUKCQgLAgQWAgMBAh4H
AheAAAoJEI6rTUCnsitZ96UBAMvwCLD6Ud1RZkpvvnGUU+idHt2hcNmYU2d0XxDI
HQ0rAQCA9VFOtjZefQkfhDzgIgnEEdSFXaMiyY+D+LP8awNMCs44BGPRkBYSCisG
AQQBl1UBBQEBB0BpfePYSOEx8PihYkNXjlK5YT89CGHjEK5etleaB9i6OwMBCAfC
eAQYFgoAIBYhBPPcwIqFcsB0mz4YiI6rTUCnsitZBQJj0ZAWAhsMAAoJEI6rTUCn
sitZvhAA/j4SQxOCLheRG86A2181WAP4qLS1qxSw+fCf28DgiPfbAQCL0kcel+M9
qbRIlMnwn6TwlQgN9w1qqlSnA9CbKXT9Aw==
=zRMz
-----END PGP PUBLIC KEY BLOCK-----
+29
View File
@@ -0,0 +1,29 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBGnK73ABEACnbytJXkjweYrwIr0aLEFRlH+C0nF44KxFc7gQmJ6PjSPMGZAD
dxZcaixU7zZl8WxEpVO0wLmIH8cf2zGOdyuZg1Yaugk1vHb2b8WBhAGCQJdPgB8W
XquedepEYtk56uP/gCoTjJDUZluEGBHnlnuujSJ4orxEdhSykEoAUfJZGEILPpMd
bphFt/Sn+Eb/TxM5jpKPdwnv8AShNF/1mZU1fWTQq9tRKJUakZj04gdaDFElQXak
CtTij+GT6yoYCARSHwGO+PC/Pr6q4tc+D7LRjxSBvUWDoFSmlqb/PJ1hj9D/7I2O
e4XXniAPWMR56KvxHlzOzrNQdJujbJdSkCwh1ZijkSd3y8ayW5WYUTGdRab99NUw
agzlabe/VVF6kzJ0Scn5q3PihB2Y9Bwo0CKnkYk7a7KT77EWv0Kkq+VHmOtqX3a2
hhX+b6a6ve9rzJ1qZYGj+obv/C3Sx1LzUjAfqVy7RJDf2uAoP5t2g8u/TkSpUxhM
VEjZBkSxYZhMyzQM6t8IgkUfnSrIPTHixbDWARZ4beMOBjxyPZK1nP7OOrNR3TkK
JtwLMQAabURCDnL0PjS0iwBTU4jtumBD1XSULyWuoTvMljrpQr1nV1oDyOt0OLqa
KA2McWtd9PdXhC8y2EIg7TmrTlJLfHYbdmkiCYj4J49Q8HWkN/6WE+RTUwARAQAB
tD5BbnRocm9waWMgQ2xhdWRlIENvZGUgUmVsZWFzZSBTaWduaW5nIDxzZWN1cml0
eUBhbnRocm9waWMuY29tPokCUQQTAQoAOxYhBDHd3iTd+rZ59C170rqpKf8afsrO
BQJpyu9wAhsPBQsJCAcCAiICBhUKCQgLAgQWAgMBAh4HAheAAAoJELqpKf8afsrO
l5IP/2I8X1dFy5xYczWB/coIxGjuzS/V6ByZGZZEJsbr04pmuHiFUykJqPGWGQ6q
U0YF5iEwvEkaagS5m7DzhSEf3FM3Cgafax/6d70tar9Vr1D+w6uPfxetu7u/WYJp
aolIsdh5fTrBh9zSM1Njl8FM8wG8CwZQjS33Oa7d8cwRkgdUWbt6LXgz+cTQNuBn
BgW6Ks7oZFI25dfu0ojDR+aDFJg4+4wZoyDLPvJz1SIrJ5WFGs67zsx9SfS3yZnf
XKmBe+f0dUy+GJ2nFZrXFf99+c0dPEHYO8DCeAHZizjkFrdYtUHdDU0YDYEGkLJa
bE+pgcpkHf5EvsZzHsyDbl95W/eh7pcXMbwkN+W4CBYUE9X4uHhqzWaC5yAVRWUA
1BJ9V4LjZfHPLEJt0I3TxzXiEg9/BVeaTYq9RjaxIFo9Nfk158HqJY6SA5jslBlx
Gv/No8u+xVcze2UJyGVfEIUfm92+0UAIkny3+5cuVV0ICzJxXlXj0CnLM9Lt50wE
p3suVwuBEviCbZ08eAH1Ht8gbBdSsiOkIU8CX3v/scwHHx5q0+NBL6xLrQObg13a
tRXBlKObfElkPN3lTUbUnJOW4U8uSjH8VRP+AujKWMDFe7x0zCs+iYY1mTOvbrTS
9n3CmZUmbynZ+E/QWNENpW/pDNZdWFy43PASmML5FHu4m9Sn
=oqMI
-----END PGP PUBLIC KEY BLOCK-----
+56
View File
@@ -0,0 +1,56 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBGmVzwkBEAClNOGTBwWpfRynhbaMotnz7VFu1mJPG3zt2ntzbvLiaaJWSeRC
2/Ax86xndydREZVboelTaKGaLQZ+/kYdmT5GARXQ/C1D8ORwoGLxbfgwNSDWpqUa
yoE25ewXNQTnjiMJ79pr8HaRp/GHhKAkn0TLIlBCUn44hqDCH4Lr5ykJeiGoLKD7
TCOsjmnWWUvhKkdSiug4HARQ2z/7rAtDhmErGy+l4Ut5SBcvyHdoth5PPtVDyQXp
YVgxLoL4ExS6A7dL/WMfOeXPi2z6fM7p9jB2Hhwi3adejfhm73A4lwLs5N51dKud
uzBPS3PNsGo8GmrFXe5EMhPTAbFMhFyVRBRFPFrQFWqZ5FVJOo5S3ehoryIGvjgc
mur92WLJvpMvPFWWO/Qq00jkJf9ID14JPAaF44O8CV8+JsJVjVSfqKaTag5JxYJ0
NgGK/GREFXyZsbvs7V6C+qdEV1V4shBAPyn+h6MKpNDfjUUXnSIrR1ubU5k9g3mo
JFX51gsnAJnZ6ZSIKx9MdxFhtEOrNubaXgmmm6x/4OTIN3yOyl4YvVjg4F3a4jzI
hyYlh8L+1oZBYIXS6+i/ZQG6h0jBElLDYPvfBxSmpK3RBW0J7c6qhlPbS91TO6Td
kF9TIBoQdUB9V2qpfmmHVxmn4pf9Mro+MT4+kXFwMO1nV7nsJzmht6wTOQARAQAB
tFNDbGF1ZGUgRGVza3RvcCBMaW51eCAoY2xhdWRlLWRlc2t0b3AtYmluIHJlcG8g
c2lnbmluZyBrZXkpIDxwYXRyaWNramFqYWFAZ21haWwuY29tPokCUgQTAQoAPAMb
LwQFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AWIQSCWn0V14ur5FZG1d84JAn1l5CI
ZwUCamj6GwIZAQAKCRA4JAn1l5CIZ9dRD/kBQX6M7xBTU7GvVWfOxDY7sFKUP6YV
axJQNYVZ645UOJY895HuW/kreasHKlZO+0RlX4j0rb3PFey/NHakwmIN3Ru0d4dn
2UHTHXxAidfselMZ1avGpbyjLpKvtcjr+/8w59/+bvrA5/vpJpGDP2o8GT8415cv
827fd2fEoMYMrI538HNwTzXURoErJkiL6ZGOPJqxLkEY5JLk4bL7ChiSkOgCBZ6H
R/wciLK/flRkNivXxbTfDBjLEeJAPQkTyE/pK/itCX+dzcoOXmIXnz97J8gJPDyq
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
yD+bFESqa8u1U4uNNayal0aR+Hyb
=rBee
-----END PGP PUBLIC KEY BLOCK-----
+64
View File
@@ -0,0 +1,64 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
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
B6DGed86zJEa/RhS
=ez56
-----END PGP PUBLIC KEY BLOCK-----
+19
View File
@@ -0,0 +1,19 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQENBGkTU2cBCACrUmwefenkABmwEy6FURUcZBXs/TPc1270i0ogs1zz3EtLeHhX
mcOsEFSbPhS6ehDKtxie8/kKlPIEpgXPiL5LDA0cFuUjO5uIawfrGwajVlEeBRjn
4oMqInTgxX2fhj6oJpb0IrqspzfZWP7cJQbtefxUNkaANm9ZqIwsLWU0jKYA5sg1
xFyvDryg5gkrtrhGNCM+S9Mn5yB94Aly/aVWIKE+QSiZi8OiGbcYj8z5Hi08ZKvh
UmzvaOtbt8mI06DgCB/YyHzhwceLCpO0rT9PeYi5iCD438xyLbbrxhY55eFmw8gV
cid2uhifWUrc8Gh8bpiO8quMmfOjSAMBTpBnABEBAAG0Rmxpb25oZWFydHBfSHlw
cmxhbmQgKE5vbmUpIDxsaW9uaGVhcnRwI0h5cHJsYW5kQGNvcHIuZmVkb3JhaG9z
dGVkLm9yZz6JAVgEEwEIAEIWIQSX4jR2yJY1E1QHx9XpukE0LEsplQUCaRNTZwMb
LwQFCQlmAYAFCwkIBwICIgIGFQoJCAsCBBYCAwECHgcCF4AACgkQ6bpBNCxLKZXV
Mgf+O5fYThKr1CVNrPl1j+D7Qm5JtAq0C2KBklaN4IPt3kYeEGmrzH/yBs1O/Crq
pmctbZm92aITz2Z8m/14/lq4v43rG6j9Z/i5SyitQEVFJjR4GRbcheOwEBXRJ4YV
qMZkw/xJSztPoN180Zxew4CFlAUWs6URxFBroid9MyrNpnoob0ENhfFas5lHFFVp
uNleyuznhu7iqjP7K/jV86JvSyPyFDpwVyBr+bMZ1mkHc16KyDf/qSn4RhpjlCC9
qy8SeZsUZPqIURI5/VrFyb44LaBC1CA2RVcuY7NAyEMRZLTJfi+8cuHL8Kvcvz1l
JUpD4thuhsq2VkZtMptBrbxmPw==
=4uMv
-----END PGP PUBLIC KEY BLOCK-----
+29
View File
@@ -0,0 +1,29 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBF2tu8EBEADnI6bmlE7ebLuYSBKJavk7gwX8L2S0lDwtmAFmNcxQ/tAhh5Gx
2RKEneou12pSxav8MvbKOr4IpJLLmuoQMLYkbQRHovgVfDYdtvK9T8tZH51ACtnC
KKr9SucnKhWpDk3/n/djV0I2qSesE6QcJVrh66bT/8nbyIFbbiYLOgE88YAX5Wdj
TkgmYXJ54l1MP/3N64pFlmk6myYCrLh7cibFYLZOW2Xwfq6Go6HOpGn9Cazb+T6m
LALkVPERu2QkcUhMqy/slD5tFFb7DW1gkwnYiu5PKwThW7laZgmw2yAgDV+JccdK
D9ZHALmy9GyQ1ZjDptpa5BObE5vazbuAbSndoIqwaMxCrlqhIYdmqz4m/HJ9BaC0
mRSkT6N9SqytZXFhu5/Ld6+/Ol3b+q28bnV64qQrDH6hgnrRdqCQpm8g7tZFuk5X
JsB/A+EfI2kE6YXqWaGdEx0XcqOv97n6sRZNweOHX3vSM0eLwmM2dpgc7RvMfcqr
73ylZ9CnWVUD6cl+wE8SnGnVVqYau2spZFzKVAcfi/Zwvh6wM7/83XC2mkIHmoFR
OY5aDWFhoFZFgiHHnmDv6kACNmSHb/oYRkvwQ+JhAQu4I9CYw1sxaUDjwtt7a+4I
mBZM8WuvAVLkqnF+MJetiL15/W834HjCNITV03t9593T6Z1Dxpfv4hy7YwARAQAB
tFVSUE0gRnVzaW9uIGZyZWUgcmVwb3NpdG9yeSBmb3IgRmVkb3JhICgyMDIwKSA8
cnBtZnVzaW9uLWJ1aWxkc3lzQGxpc3RzLnJwbWZ1c2lvbi5vcmc+iQJFBBMBCAAv
FiEE6aSRo94keBTn4Gfq4G+OzdZR/y4FAl2tu8ECGwMECwkIBwMVCAoCHgECF4AA
CgkQ4G+OzdZR/y4ZQhAAmF5A4XC9ymd94BFwsbbpCnx2YlfmsZwT1QzBu9njjkH7
MC4THknYe2B/muE5dPu3NseZMzue1Ou4KbMz4wq82731prLRu+iHAxAxJ1qd8whA
QGuRJAg8+YEXKhpwpD/8P/xJo9IRmPxPM+6mQVTlASv34CEIGff1vJr40tNiU53P
PZq9SWD3/uG84PQRmGXetfF2K3NkXqzkvQSM68JZiYR2+wMkoO9f72B7LTBrfkwy
RcFPA7kj65pysB+l2wez03Dh/MyA3LTusd9M6FGiSOUVpQZ+NUFipIisS3vh/Bgp
zMsj1NSsMLjUDcX8stR8GfVgTxSgWwHTNl75XwTZpJOKMoj97kh9zzLwBhZ1W+xo
8s2W7YqVnOUl8rPm7ZbOefGkamNg8bhqcyNIEbHqR5QZVzDBT2AxVcB6jsxSHf5b
sb+KEJff4g6E4fWPA/IYdtJ7DItbVXnkAjqD7ADUh7Xq7pOgfC/4Cledf27x73m+
sdBvKsEBrroAsX/v4z46mQApszkfjTUAXwj2lUT+ujoktJHXqR71jbY0+8JX6Fyw
6ZW0emxR++bt9ksLcsNmjOQP9TmQpi2CW4Z+Ol2tlwtlnKAo6ecx4aacHKg+FYuQ
HTJRq6E6GpCPn1avf1v797RM+3zzw9TYkadfVLIQQ4HYbYzienOgGGporclrtrQ=
=oOVZ
-----END PGP PUBLIC KEY BLOCK-----
@@ -0,0 +1,30 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBF2tvGQBEAC5Q2ePLZZafOkFhYHpGZdRRBCcCd+aiLATofFV8+FjPuPLL/3R
7fx9RRukL+XKs6K9houj/oYVHmBY7II1mgeRzZHo6KygnM9ph3RKqQDse4TR9+VX
rctsBRikNc7GViSoiPHLRAJeTrlwYRjPHYfF64nFtcPYfPIlGZkEG8mrHbTjkh36
NAlqb3XC0cOSsKQV5f4Wn8fAUepYUkTxA74sVHLSDcBRj3fGfizkiHohy4OjNPij
1VVvfUQXIGYwEDnrd3JF5c2o6B4MfH7h1aN+xG7GJTRswgjQtYUayUOySD5mdZ9u
lUNfPrIAvwyTnc1IvoJUGlf8wSqz8NmjTHykUU+f6Dldb4JKNavnYaVlmDH4HfK+
FVdAD/1pG/6HL94clf/g8LR3sQ0KU/UZJKbDA81n1X04OREfqdjr81U84iyKyb8S
+5nwYuJvxoe+wHg+iHAK0CXYel6V1GR51yka8+sETXyEjGvXksPMQDVPGIDzDfPr
QVijtL3/1Pgkuz1ZvvXmuxD94uV2rBvjKl1NFSWNXId2J+vI5omllGHR3qskOHFa
My9IQkbV4sMoycW/fP5xbwGhVi5q5Gjo7h6J7TIzyMf4gl6PJTp0AFhOZAMA/dXY
nLDnw+qz+iq0B3I14JSLvgCH/uSUEMl5970+COK7wmPTU7I3Hq6PMbzvqQARAQAB
tFhSUE0gRnVzaW9uIG5vbmZyZWUgcmVwb3NpdG9yeSBmb3IgRmVkb3JhICgyMDIw
KSA8cnBtZnVzaW9uLWJ1aWxkc3lzQGxpc3RzLnJwbWZ1c2lvbi5vcmc+iQJFBBMB
CAAvFiEEeb24j5u/c5EP1Albair5YZSEPGUFAl2tvGQCGwMECwkIBwMVCAoCHgEC
F4AACgkQair5YZSEPGW0Ig/+NJf5+KzbRNuFvvGURQI7SYmYtFXkrW4n6rLPWeIV
UHvd/ko74aMVds7hTWeC0cLpjRMSPuwp9xjqb6NvQaqcUK4IwHzlXocait2HzSl+
h2jI3/wSQXqNkvNrgD3rkYZZZ/x7EBBTSTRUpFPq3yHA/BBXbZNEvFsXOmFAy5y+
E5iYnfyjYKHWd0ZwIliWWtK+V5TU54WqHqKF5J2iIDgANkLXiyqx6+LJ6Ng0YfCQ
fO7IMfwtgUt34AfrHWnq0S9BW0hmtPvcYjTtveQKCeGfdMcpRRJsOrvaDDKo1Wmr
IcvGO2VwiF9i19ppghXOSy7q51wTlEqtj3PWYhmJYcRq8Jr1SqjGx73QhUPtsF67
g3vjNEm8PE7pj7vg52BJlzkx6yU+hH5ZNBRM5ll4ZjiX+X7EzKa9so83uszuwoQA
mScTwyyQDNeflnUwiSgZc7PEv1i0BYIHVK7VjmamhOWZRHaaYFCc//gcmu10TJLn
ZCGF2ZDkAdUT6EoWBsT/QCgYSFggrjH9lgKqC5ON8+F5DO1RQe84irgz9jjE9+62
kgQgWZ6F2RZm5/R28DHdAetji50XbnmXgAk/u9u2Hw2bVVJfJ0WpEVcPvA1L86SE
8i8p1fmzljwRazZAksk5Zh2QfaM0jlMYHWbKpbXQcX19Uerm7D9IkciZvDAmgBYV
S6Y=
=rOqq
-----END PGP PUBLIC KEY BLOCK-----
+17
View File
@@ -0,0 +1,17 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GopenPGP 2.8.1
Comment: https://gopenpgp.org
xjMEaYpzVxYJKwYBBAHaRw8BAQdAb3DsTkfuyHxBUTJh9KY5K9Zmd3HHNlr3nr7j
DqIfJHbNIFRlcnJhIDQ0IDxzZWN1cml0eUBmeXJhbGFicy5jb20+wr8EExYIAHEF
gmmKc1cDCwkHCZAAzatD3iJtbzUUAAAAAAAcABBzYWx0QG5vdGF0aW9ucy5vcGVu
cGdwanMub3Jn6H9BnkxjSlvFTWI4j1lWagIVCAMWAAICGQECmwMCHgEWIQSuCRV6
TeiLSX6h1dMAzatD3iJtbwAAkxUA/AhjnPTnXX4U50jtWrE8/33CXkR/kMvp8y2m
jR9jrEzPAQCEA1Jx8eBbBo7RySbF1D8AoYGGvdy5Igmsz7/FCq4DAM44BGmKc1cS
CisGAQQBl1UBBQEBB0BKc0gRkEY9/IuABq32DNPxZN0AQo41geDGywcbV47JSQMB
CgnCrgQYFggAYAWCaYpzVwmQAM2rQ94ibW81FAAAAAAAHAAQc2FsdEBub3RhdGlv
bnMub3BlbnBncGpzLm9yZ8nm3oDFHJ/SnE3gwb0ZR04CmwwWIQSuCRV6TeiLSX6h
1dMAzatD3iJtbwAAjYoA/2P25j8wdGP/TdF4mhNiN/6cBNL08/wmqDTJooYy2GP+
AQCJp+Vj5nfTYUO7+6WvES4cFaaZJhY8CsjJwx6k8xhsCA==
=KXwo
-----END PGP PUBLIC KEY BLOCK-----
+2
View File
@@ -268,6 +268,8 @@ hermetic tests/setup/lid-contract
hermetic tests/setup/migrations-contract
hermetic tests/setup/nautilus-extensions-contract
hermetic tests/setup/package-lists-contract
# Provenance uses local signed fixtures and stubs every network/package operation.
hermetic tests/setup/package-provenance-contract
hermetic tests/setup/projects-contract
hermetic tests/setup/readme-contract
hermetic tests/setup/role-contract
@@ -0,0 +1 @@
291bd319ae85488101e908e37fc0fa1b0da1429ba27e10d2b391cb3f60dd44ea tiny-artifact
@@ -0,0 +1,11 @@
-----BEGIN PGP SIGNATURE-----
iQEzBAABCgAdFiEEYBb/GMrimM42SO4jJeAfdl4e+foFAmqQBJoACgkQJeAfdl4e
+foW9Qf/QLO0N5vVdG3Fi9ql6SE3dZItZtrJy4jFVPDEVEZJK4PoT9iRE/RQwqsU
7y86B1x0JmCoxVRigLD75gz8IYb8SzchbTrUQRB/l0FBjNZaeAX1O+E8GZIsK9Kf
KljmaIiG8vrwGilCxZnJPGv80mMpW9LETgF9be2L8bZff/UDwEZfOenYIgievUJW
cuNe41jzOd0kYuOggnxPsOqxfd+ludpwjOO/z2j2TV8J4H7JHzoRzG8100J+DYoY
ud9GyH1AtgGlQ3XALb4UotE3Btf8GiZ1Mg/igxZqvjCJhrfOiaeziKi4a80fhv9z
j1KFafXj9lc69vBgayepHF8BH6bocQ==
=nTYb
-----END PGP SIGNATURE-----
@@ -0,0 +1,18 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQENBGqQBJkBCADBKEbp0EaiCrTvnCmu6Ux1MyofeiS5plcZqHiRIBM9zy9Apxll
bKFD0tOG2i8GpjAIb2uO2tCfaLsANhi4H43D1XBNGS3DLQlc486c4BlCmtUb3JN1
FJiR1Tx+R7FxYHdlD9ceDdxGOIrVxMH3eDoHD1xOQFLstzMi/J49x5n0NcLIscVU
BpOwerm8a+tHOoigcRUgdud1E7YJOGMrkkXy4wMTZ+DkcqK5L6KlyEOfv+Ib2PkN
0VOLlD6p3Nb8Vbt54zJh/e/UvA0dBy4szFCR5PeBBvPuAwkMsBTErbrJ4S22O33M
eN7PAEAZ174/BO+u1jH2RSC7BOJbxCcjxmHBABEBAAG0MlBhbmFtYSBQcm92ZW5h
bmNlIEZpeHR1cmUgPGZpeHR1cmVAcGFuYW1hLmludmFsaWQ+iQFRBBMBCgA7FiEE
YBb/GMrimM42SO4jJeAfdl4e+foFAmqQBJkCGwMFCwkIBwICIgIGFQoJCAsCBBYC
AwECHgcCF4AACgkQJeAfdl4e+frEkwf/Si/D8yDAVaTIJPmuEr9nVtpmw9/vFQ0u
xxTXnPkEWMogLMLFCU4I2xHrAzJdvwuPKldZtE2aD2CX1lCB2JQDf1X+gt+jRiqC
o/eFUorCsaLm1lUylTG5NbGoCNN8xkC5V5q5WoXUga7inW0B6isRoIjGiFX0AKb4
5w8iZ3jibGomIAtfIvtEChM0orB5Y59o5JzwnE4LJ0OTiZRiKB7ncUbflJJHfX4v
Zd2HjuLGaPuYuneVBKlFDGuN39sh2vRfQNyQEqFM9zTCxj1pBcscX+wAQAn6r9xM
p6Sz8nRaNgkAUEnfb84MeLwYHgOeG0vD3V1Gv440TAxIp7VdeaCNhg==
=SCW3
-----END PGP PUBLIC KEY BLOCK-----
@@ -0,0 +1,118 @@
7avu2wMAAAAAAHBhbmFtYS1wcm92ZW5hbmNlLWZpeHR1cmUtMS0xAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAAAAAAAjq3oAQAAAAAAAAAIAAAQpAAA
AD4AAAAHAAAQlAAAABAAAAEMAAAABwAAAAAAAAE2AAABDQAAAAYAAAE2AAAAAQAAAREAAAAGAAAB
XwAAAAEAAAPoAAAABAAAAaAAAAABAAAD7AAAAAcAAAGkAAAAEAAAA+8AAAAEAAABtAAAAAEAAAPw
AAAABwAAAbgAAA7ciQEzBAABCgAdFiEEYBb/GMrimM42SO4jJeAfdl4e+foFAmqQBNEACgkQJeAf
dl4e+fq1FAgApbV7aLtafCECpXQRZfsg2dYdWcujtZB2JKQ4yK93sBoScSARSapoGXyuGj6Yiu5b
lzY/5hIQLY68WyzN5dCtutTIycEqdk5ZUU2n7wVmWsshyEp3zNG9LmYo7fZFX3ViJdHk4bgVg8t4
dgUtCPpixl43gQGb+KDTKNVN+8acmi1a2gkNGjJgWyvCjsFLU7Rac7R/pVhtgfUo+JA8goKYfIeJ
SMTFd0j0mPpbucn6IgkQDVu7x1/1UA88C5fOOUQRwfHxTMoxrDxD55g2P6YmN4vHMeouY/iNxFTM
mBeQ8CVUBvwL6wbZeakd3zKJdDwsOBkl8ymBSg0a3hetoWO11DM1NTg5MDBmNWUwM2YwNzFhNjM1
ZDg1ZjgxODI3NTA3YjdiMWQ1MDYAMjQ4ZTQ3YzFiNjhlYjM5NDgxMWFmNWJhOGZlNGNiZTEzYmUy
MGM5N2I0MzM2MzM1MGRhOGE2MDY0ZWQ4YTk4ZgAAAAiZ9bUc5Ib0/pUFYQ1fQtgpwwAAASQAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AAAAB////4AAAAAQAAAA
AI6t6AEAAAAAAAAAMwAABOEAAAA/AAAABwAABNEAAAAQAAAAZAAAAAgAAAAAAAAAAQAAA+gAAAAG
AAAAAgAAAAEAAAPpAAAABgAAABwAAAABAAAD6gAAAAYAAAAeAAAAAQAAA+wAAAAJAAAAIAAAAAEA
AAPtAAAACQAAAD8AAAABAAAD7gAAAAQAAABYAAAAAQAAA+8AAAAGAAAAXAAAAAEAAAPxAAAABAAA
AGgAAAABAAAD9gAAAAYAAABsAAAAAQAAA/gAAAAJAAAAcAAAAAEAAAP9AAAABgAAAHwAAAABAAAD
/gAAAAYAAACCAAAAAQAABAQAAAAEAAAAjAAAAAEAAAQGAAAAAwAAAJAAAAABAAAECQAAAAMAAACS
AAAAAQAABAoAAAAEAAAAlAAAAAEAAAQLAAAACAAAAJgAAAABAAAEDAAAAAgAAADZAAAAAQAABA0A
AAAEAAAA3AAAAAEAAAQPAAAACAAAAOAAAAABAAAEEAAAAAgAAADlAAAAAQAABBQAAAAGAAAA6gAA
AAEAAAQVAAAABAAAARAAAAABAAAEFwAAAAgAAAEUAAAAAQAABBgAAAAEAAABMAAAAAQAAAQZAAAA
CAAAAUAAAAAEAAAEGgAAAAgAAAGlAAAABAAABCgAAAAGAAABxAAAAAEAAARHAAAABAAAAcwAAAAB
AAAESAAAAAQAAAHQAAAAAQAABEkAAAAIAAAB1AAAAAEAAARYAAAABAAAAdgAAAABAAAEWQAAAAgA
AAHcAAAAAQAABFwAAAAEAAAB4AAAAAEAAARdAAAACAAAAeQAAAABAAAEXgAAAAgAAAHwAAAAAQAA
BGIAAAAGAAACFgAAAAEAAARkAAAABgAABAUAAAABAAAEZQAAAAYAAAQKAAAAAQAABGYAAAAGAAAE
DwAAAAEAAARsAAAABgAABBIAAAABAAAEdAAAAAQAAAQsAAAAAQAABHUAAAAEAAAEMAAAAAEAAAR2
AAAACAAABDQAAAABAAATkwAAAAQAAARAAAAAAQAAE8YAAAAGAAAERAAAAAEAABPkAAAACAAABEoA
AAABAAAT5QAAAAQAAASMAAAAAQAAE+kAAAAIAAAEkAAAAAFDAHBhbmFtYS1wcm92ZW5hbmNlLWZp
eHR1cmUAMQAxAFBhbmFtYSBwcm92ZW5hbmNlIHRlc3QgZml4dHVyZQBBIHRlc3Qtb25seSBSUE0g
Zml4dHVyZS4AapAEmmRlc2t0b3AtZ2liAAAAAAhNSVQAVW5zcGVjaWZpZWQAbGludXgAbm9hcmNo
AAAAAAAAAAiBpAAAapAEmmU4MGI3MWNkMTRkM2NiZDY1ZjQxNzNhYmNiZmNmMDFhNTQ1ZGJjYTMy
YTcyZDU3NTEwOGI1NTNhNjQ4Y2M5NmYAAAAAAAAAAHJvb3QAcm9vdABwYW5hbWEtcHJvdmVuYW5j
ZS1maXh0dXJlLTEtMS5zcmMucnBtAP////9wYW5hbWEtcHJvdmVuYW5jZS1maXh0dXJlAAAAAQAA
CgEAAAoBAAAKAQAACnJwbWxpYihDb21wcmVzc2VkRmlsZU5hbWVzKQBycG1saWIoRmlsZURpZ2Vz
dHMpAHJwbWxpYihQYXlsb2FkRmlsZXNIYXZlUHJlZml4KQBycG1saWIoUGF5bG9hZElzWnN0ZCkA
My4wLjQtMQA0LjYuMC0xADQuMC0xADUuNC4xOC0xADYuMC4yAAAAAAAAAQAAAAEAAAAAAAAACDEt
MQAAAAAAZml4dHVyZS50eHQAL3Vzci9zaGFyZS9wYW5hbWEtcHJvdmVuYW5jZS1maXh0dXJlLwAt
TzIgLWZsdG89YXV0byAtZmZhdC1sdG8tb2JqZWN0cyAtZmV4Y2VwdGlvbnMgLWcgLWdyZWNvcmQt
Z2NjLXN3aXRjaGVzIC1waXBlIC1XYWxsIC1Xbm8tY29tcGxhaW4td3JvbmctbGFuZyAtV2Vycm9y
PWZvcm1hdC1zZWN1cml0eSAtV3AsLVVfRk9SVElGWV9TT1VSQ0UsLURfRk9SVElGWV9TT1VSQ0U9
MyAtV3AsLURfR0xJQkNYWF9BU1NFUlRJT05TIC1zcGVjcz0vdXNyL2xpYi9ycG0vcmVkaGF0L3Jl
ZGhhdC1oYXJkZW5lZC1jYzEgLWZzdGFjay1wcm90ZWN0b3Itc3Ryb25nIC1zcGVjcz0vdXNyL2xp
Yi9ycG0vcmVkaGF0L3JlZGhhdC1hbm5vYmluLWNjMSAgLW02NCAtbWFyY2g9eDg2LTY0IC1tdHVu
ZT1nZW5lcmljIC1mYXN5bmNocm9ub3VzLXVud2luZC10YWJsZXMgLWZzdGFjay1jbGFzaC1wcm90
ZWN0aW9uIC1mY2YtcHJvdGVjdGlvbiAtbXRscy1kaWFsZWN0PWdudTIgLWZuby1vbWl0LWZyYW1l
LXBvaW50ZXIgLW1uby1vbWl0LWxlYWYtZnJhbWUtcG9pbnRlcgBjcGlvAHpzdGQAMTkAbm9hcmNo
LXJlZGhhdC1saW51eC1nbnUAAAAAAAAAAAAAAEFTQ0lJIHRleHQAAAAAAAh1dGYtOABiZjZkYzg1
Y2I3NjI5MzhhYjM1NDY2ZDYyNWUzZWI0MzIxMzk4MjAxZWY5NDM5NDRhZDk0NzU5YjExMTY1Yjk5
AAAAAAAINDQ4YWY1YjI2NTgyODFlZGFhYTNmMGVlNDU5ZTk2MWVhZGYzNTEzZmI5MDBiOTQ0NDVi
YWZjNDUwZmQxYWY2NwAAAAA/AAAAB////NAAAAAQKLUv/QBofQMAkgUUGHBvDmCIWNNxsOnme3c1
JmpNprTcf+8pMqqqrTUmWRSEae6cAZ3ZfAvlNTMJcvCJHSFGycr11LGrhbIja6V17Xsg3Hgfw380
wR+ajfOLFw8MIACTzAMyvJyYeLFKvjdrmx/Z4OEGZKVOuIQR
@@ -0,0 +1 @@
tiny artifact
@@ -0,0 +1 @@
tampered artifact
@@ -0,0 +1,118 @@
7avu2wMAAAAAAHBhbmFtYS1wcm92ZW5hbmNlLWZpeHR1cmUtMS0xAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAAAAAAAjq3oAQAAAAAAAAAHAAAQtAAA
AD4AAAAHAAAQpAAAABAAAAENAAAABgAAAAAAAAABAAABEQAAAAYAAAApAAAAAQAAA+gAAAAEAAAA
bAAAAAEAAAPsAAAABwAAAHAAAAAQAAAD7wAAAAQAAACAAAAAAQAAA/AAAAAHAAAAhAAAECAzNTU4
OTAwZjVlMDNmMDcxYTYzNWQ4NWY4MTgyNzUwN2I3YjFkNTA2ADI0OGU0N2MxYjY4ZWIzOTQ4MTFh
ZjViYThmZTRjYmUxM2JlMjBjOTdiNDMzNjMzNTBkYThhNjA2NGVkOGE5OGYAAAAAAAiZ9bUc5Ib0
/pUFYQ1fQtgpwwAAASQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AAAAB////5AAAAAQAAAA
AI6t6AEAAAAAAAAAMwAABOEAAAA/AAAABwAABNEAAAAQAAAAZAAAAAgAAAAAAAAAAQAAA+gAAAAG
AAAAAgAAAAEAAAPpAAAABgAAABwAAAABAAAD6gAAAAYAAAAeAAAAAQAAA+wAAAAJAAAAIAAAAAEA
AAPtAAAACQAAAD8AAAABAAAD7gAAAAQAAABYAAAAAQAAA+8AAAAGAAAAXAAAAAEAAAPxAAAABAAA
AGgAAAABAAAD9gAAAAYAAABsAAAAAQAAA/gAAAAJAAAAcAAAAAEAAAP9AAAABgAAAHwAAAABAAAD
/gAAAAYAAACCAAAAAQAABAQAAAAEAAAAjAAAAAEAAAQGAAAAAwAAAJAAAAABAAAECQAAAAMAAACS
AAAAAQAABAoAAAAEAAAAlAAAAAEAAAQLAAAACAAAAJgAAAABAAAEDAAAAAgAAADZAAAAAQAABA0A
AAAEAAAA3AAAAAEAAAQPAAAACAAAAOAAAAABAAAEEAAAAAgAAADlAAAAAQAABBQAAAAGAAAA6gAA
AAEAAAQVAAAABAAAARAAAAABAAAEFwAAAAgAAAEUAAAAAQAABBgAAAAEAAABMAAAAAQAAAQZAAAA
CAAAAUAAAAAEAAAEGgAAAAgAAAGlAAAABAAABCgAAAAGAAABxAAAAAEAAARHAAAABAAAAcwAAAAB
AAAESAAAAAQAAAHQAAAAAQAABEkAAAAIAAAB1AAAAAEAAARYAAAABAAAAdgAAAABAAAEWQAAAAgA
AAHcAAAAAQAABFwAAAAEAAAB4AAAAAEAAARdAAAACAAAAeQAAAABAAAEXgAAAAgAAAHwAAAAAQAA
BGIAAAAGAAACFgAAAAEAAARkAAAABgAABAUAAAABAAAEZQAAAAYAAAQKAAAAAQAABGYAAAAGAAAE
DwAAAAEAAARsAAAABgAABBIAAAABAAAEdAAAAAQAAAQsAAAAAQAABHUAAAAEAAAEMAAAAAEAAAR2
AAAACAAABDQAAAABAAATkwAAAAQAAARAAAAAAQAAE8YAAAAGAAAERAAAAAEAABPkAAAACAAABEoA
AAABAAAT5QAAAAQAAASMAAAAAQAAE+kAAAAIAAAEkAAAAAFDAHBhbmFtYS1wcm92ZW5hbmNlLWZp
eHR1cmUAMQAxAFBhbmFtYSBwcm92ZW5hbmNlIHRlc3QgZml4dHVyZQBBIHRlc3Qtb25seSBSUE0g
Zml4dHVyZS4AapAEmmRlc2t0b3AtZ2liAAAAAAhNSVQAVW5zcGVjaWZpZWQAbGludXgAbm9hcmNo
AAAAAAAAAAiBpAAAapAEmmU4MGI3MWNkMTRkM2NiZDY1ZjQxNzNhYmNiZmNmMDFhNTQ1ZGJjYTMy
YTcyZDU3NTEwOGI1NTNhNjQ4Y2M5NmYAAAAAAAAAAHJvb3QAcm9vdABwYW5hbWEtcHJvdmVuYW5j
ZS1maXh0dXJlLTEtMS5zcmMucnBtAP////9wYW5hbWEtcHJvdmVuYW5jZS1maXh0dXJlAAAAAQAA
CgEAAAoBAAAKAQAACnJwbWxpYihDb21wcmVzc2VkRmlsZU5hbWVzKQBycG1saWIoRmlsZURpZ2Vz
dHMpAHJwbWxpYihQYXlsb2FkRmlsZXNIYXZlUHJlZml4KQBycG1saWIoUGF5bG9hZElzWnN0ZCkA
My4wLjQtMQA0LjYuMC0xADQuMC0xADUuNC4xOC0xADYuMC4yAAAAAAAAAQAAAAEAAAAAAAAACDEt
MQAAAAAAZml4dHVyZS50eHQAL3Vzci9zaGFyZS9wYW5hbWEtcHJvdmVuYW5jZS1maXh0dXJlLwAt
TzIgLWZsdG89YXV0byAtZmZhdC1sdG8tb2JqZWN0cyAtZmV4Y2VwdGlvbnMgLWcgLWdyZWNvcmQt
Z2NjLXN3aXRjaGVzIC1waXBlIC1XYWxsIC1Xbm8tY29tcGxhaW4td3JvbmctbGFuZyAtV2Vycm9y
PWZvcm1hdC1zZWN1cml0eSAtV3AsLVVfRk9SVElGWV9TT1VSQ0UsLURfRk9SVElGWV9TT1VSQ0U9
MyAtV3AsLURfR0xJQkNYWF9BU1NFUlRJT05TIC1zcGVjcz0vdXNyL2xpYi9ycG0vcmVkaGF0L3Jl
ZGhhdC1oYXJkZW5lZC1jYzEgLWZzdGFjay1wcm90ZWN0b3Itc3Ryb25nIC1zcGVjcz0vdXNyL2xp
Yi9ycG0vcmVkaGF0L3JlZGhhdC1hbm5vYmluLWNjMSAgLW02NCAtbWFyY2g9eDg2LTY0IC1tdHVu
ZT1nZW5lcmljIC1mYXN5bmNocm9ub3VzLXVud2luZC10YWJsZXMgLWZzdGFjay1jbGFzaC1wcm90
ZWN0aW9uIC1mY2YtcHJvdGVjdGlvbiAtbXRscy1kaWFsZWN0PWdudTIgLWZuby1vbWl0LWZyYW1l
LXBvaW50ZXIgLW1uby1vbWl0LWxlYWYtZnJhbWUtcG9pbnRlcgBjcGlvAHpzdGQAMTkAbm9hcmNo
LXJlZGhhdC1saW51eC1nbnUAAAAAAAAAAAAAAEFTQ0lJIHRleHQAAAAAAAh1dGYtOABiZjZkYzg1
Y2I3NjI5MzhhYjM1NDY2ZDYyNWUzZWI0MzIxMzk4MjAxZWY5NDM5NDRhZDk0NzU5YjExMTY1Yjk5
AAAAAAAINDQ4YWY1YjI2NTgyODFlZGFhYTNmMGVlNDU5ZTk2MWVhZGYzNTEzZmI5MDBiOTQ0NDVi
YWZjNDUwZmQxYWY2NwAAAAA/AAAAB////NAAAAAQKLUv/QBofQMAkgUUGHBvDmCIWNNxsOnme3c1
JmpNprTcf+8pMqqqrTUmWRSEae6cAZ3ZfAvlNTMJcvCJHSFGycr11LGrhbIja6V17Xsg3Hgfw380
wR+ajfOLFw8MIACTzAMyvJyYeLFKvjdrmx/Z4OEGZKVOuIQR
+159
View File
@@ -0,0 +1,159 @@
#!/usr/bin/env bash
# The production change that breaks these cases is accepting an unverified
# download, a wrong signer, or executable/malformed provenance data.
set -euo pipefail
repo_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
fixtures="$repo_dir/tests/setup/fixtures/provenance"
config="$repo_dir/setup/provenance/installers.conf"
test_tmp="$(mktemp -d)"
host_gnupg="${GNUPGHOME:-$HOME/.gnupg}"
host_rpmdb="/usr/lib/sysimage/rpm/rpmdb.sqlite"
cleanup() {
rm -rf -- "$test_tmp"
}
trap cleanup EXIT
trap 'exit 130' INT
trap 'exit 143' TERM
fail() {
printf 'package provenance contract: %s\n' "$*" >&2
exit 1
}
expect_success() {
"$@" || fail "expected success: $*"
}
expect_failure() {
if "$@"; then
fail "expected failure: $*"
fi
}
assert_file_bytes() {
local path="$1" expected="$2"
[[ "$(<"$path")" == "$expected" ]] || fail "unexpected bytes in $path"
}
snapshot() {
local path="$1"
if [[ -e "$path" ]]; then
stat -c '%i:%s:%Y:%Z' "$path"
else
printf 'absent'
fi
}
# This must be the only production file sourced by the contract.
# shellcheck source=../../setup/lib/artifact-provenance
source "$repo_dir/setup/lib/artifact-provenance"
fixture_fingerprint='6016FF18CAE298CE3648EE2325E01F765E1EF9FA'
tiny_sha256='291bd319ae85488101e908e37fc0fa1b0da1429ba27e10d2b391cb3f60dd44ea'
base64 --decode "$fixtures/signed-fixture.rpm.base64" > "$test_tmp/signed-fixture.rpm"
base64 --decode "$fixtures/unsigned-fixture.rpm.base64" > "$test_tmp/unsigned-fixture.rpm"
expect_success key_fingerprint_matches "$fixtures/fixture-key.asc" "$fixture_fingerprint"
expect_failure key_fingerprint_matches "$fixtures/fixture-key.asc" '0000000000000000000000000000000000000000'
expect_success verify_detached_signature \
"$fixtures/fixture-key.asc" "$fixtures/SHASUMS256.txt.asc" "$fixtures/SHASUMS256.txt"
expect_failure verify_detached_signature \
"$fixtures/fixture-key.asc" "$fixtures/SHASUMS256.txt.asc" "$fixtures/tiny-artifact"
cp "$fixtures/SHASUMS256.txt.asc" "$test_tmp/bad-signature.asc"
sed -i 's/^=nTYb$/=nTYa/' "$test_tmp/bad-signature.asc"
expect_failure verify_detached_signature \
"$fixtures/fixture-key.asc" "$test_tmp/bad-signature.asc" "$fixtures/SHASUMS256.txt"
mkdir "$test_tmp/bin"
cat > "$test_tmp/bin/curl" <<'STUB'
#!/usr/bin/env bash
set -euo pipefail
output=''
while (($#)); do
case "$1" in
--output) output="$2"; shift 2 ;;
*) shift ;;
esac
done
case "${CURL_FIXTURE:?}" in
good) cp "$CURL_FIXTURE_ROOT/tiny-artifact" "$output" ;;
oversized) head -c 1025 /dev/zero > "$output" ;;
interrupted) printf 'partial' > "$output"; exit 42 ;;
*) exit 64 ;;
esac
STUB
chmod +x "$test_tmp/bin/curl"
PATH="$test_tmp/bin:$PATH"
export PATH CURL_FIXTURE_ROOT="$fixtures"
destination="$test_tmp/destination"
export CURL_FIXTURE=good
expect_success download_sha256 'https://fixture.invalid/good' "$tiny_sha256" 1024 "$destination"
cmp -s "$fixtures/tiny-artifact" "$destination" || fail 'verified download changed artifact bytes'
[[ ! -e "$destination.part" ]] || fail 'successful download left a part file'
export CURL_FIXTURE=good
expect_failure download_sha256 'https://fixture.invalid/uppercase-digest' \
'291BD319AE85488101E908E37FC0FA1B0DA1429BA27E10D2B391CB3F60DD44EA' 1024 \
"$test_tmp/uppercase-destination"
printf 'known-good\n' > "$destination"
export CURL_FIXTURE=good
expect_failure download_sha256 'https://fixture.invalid/bad-digest' \
'0000000000000000000000000000000000000000000000000000000000000000' 1024 "$destination"
assert_file_bytes "$destination" 'known-good'
[[ ! -e "$destination.part" ]] || fail 'bad digest left a part file'
export CURL_FIXTURE=oversized
expect_failure download_sha256 'https://fixture.invalid/oversized' "$tiny_sha256" 1024 "$destination"
assert_file_bytes "$destination" 'known-good'
[[ ! -e "$destination.part" ]] || fail 'oversized download left a part file'
export CURL_FIXTURE=interrupted
expect_failure download_sha256 'https://fixture.invalid/interrupted' "$tiny_sha256" 1024 "$destination"
assert_file_bytes "$destination" 'known-good'
[[ ! -e "$destination.part" ]] || fail 'interrupted download left a part file'
before_gnupg="$(snapshot "$host_gnupg")"
before_rpmdb="$(snapshot "$host_rpmdb")"
expect_success rpm_signature_matches \
"$test_tmp/signed-fixture.rpm" "$fixtures/fixture-key.asc" "$fixture_fingerprint"
expect_failure rpm_signature_matches \
"$test_tmp/unsigned-fixture.rpm" "$fixtures/fixture-key.asc" "$fixture_fingerprint"
expect_failure rpm_signature_matches \
"$test_tmp/signed-fixture.rpm" "$fixtures/fixture-key.asc" '0000000000000000000000000000000000000000'
[[ "$before_gnupg" == "$(snapshot "$host_gnupg")" ]] || fail 'host GPG state changed'
[[ "$before_rpmdb" == "$(snapshot "$host_rpmdb")" ]] || fail 'host RPM database changed'
expect_success load_installer_provenance "$config"
[[ "${INSTALLER_PROVENANCE[BUN_VERSION]:-}" == '1.4.0' ]] || fail 'valid provenance was not loaded'
parser_fixture="$test_tmp/installers.conf"
cp "$config" "$parser_fixture"
printf 'UNKNOWN_KEY=value\n' >> "$parser_fixture"
expect_failure load_installer_provenance "$parser_fixture"
cp "$config" "$parser_fixture"
printf 'BUN_VERSION=1.4.0\n' >> "$parser_fixture"
expect_failure load_installer_provenance "$parser_fixture"
grep -v '^NODE_VERSION=' "$config" > "$parser_fixture"
expect_failure load_installer_provenance "$parser_fixture"
cp "$config" "$parser_fixture"
sed -i 's/^BUN_VERSION=/ BUN_VERSION=/' "$parser_fixture"
expect_failure load_installer_provenance "$parser_fixture"
cp "$config" "$parser_fixture"
sed -i 's/^BUN_VERSION=.*/BUN_VERSION=$(id -u)/' "$parser_fixture"
expect_failure load_installer_provenance "$parser_fixture"
cp "$config" "$parser_fixture"
printf 'BUN_ARMV7_URL=https://fixture.invalid/bun\n' >> "$parser_fixture"
expect_failure load_installer_provenance "$parser_fixture"
printf 'package provenance contract: PASS\n'