Files
ShadowsocksX-NG/ShadowsocksX-NG2/Scripts/lib-manifests.sh
T
Qiu Yuzhou a20df3001f feat(ng2): external binary supply chain and packaging gate (#24)
Pin sslocal v1.25.0 (aarch64-apple-darwin) and v2ray-plugin v1.3.2 via
committed manifests (tag + asset URL + archive SHA-256 + bundle location +
sign identifier):

- Scripts/fetch-external-binaries.sh downloads the pinned archive, verifies
  its SHA-256 byte-for-byte, extracts only the named member (arm64-only
  check) and stamps the local cache; archive hash mismatch fails hard, and
  any manifest/local-artifact drift forces a re-verified refetch. It re-runs
  as a pre-build phase so tampering fails the build itself.
- project.yml installs both binaries via Copy Files into
  Contents/Helpers[/Plugins]; generate requires the artifacts to exist
  (fetch before generate, else Copy Files phases are silently dropped).
- Scripts/sign-embedded-helpers.sh re-signs each helper Developer ID with
  --options runtime --timestamp and the pinned identifier
  (<bundle-id>[.plugin.]<name>) before Xcode seals the outer app signature.
- Scripts/packaging-gate.sh asserts strict nested signature verification,
  DevID + Hardened Runtime on the app with no App Sandbox entitlement, and
  exact per-binary manifest coverage under Contents/Helpers.
- Tests pin both manifests' schema and anchor hashes.

Verified: build + gate all green; byte-flip, foreign-binary and
missing-binary tampers each caught; 5 unit tests pass; no submodules or
in-repo builds; notarization stays out of scope (#39).
2026-09-20 14:27:21 +08:00

41 lines
1.4 KiB
Bash
Executable File

# Shared manifest reading for the Vendor supply chain scripts
# (fetch-external-binaries.sh / sign-embedded-helpers.sh / packaging-gate.sh).
# Sourced by those scripts; not runnable on its own.
#
# A manifest is Vendor/<name>/manifest.json with the fields fixed by
# spec #21 D6: project, release, target, asset, url, archiveSHA256,
# archiveMember, binary, bundleSubpath, signIdentifier. JSON is parsed with
# plutil + PlistBuddy so the scripts depend only on base macOS tooling.
PLIST_BUDDY=${PLIST_BUDDY:-/usr/libexec/PlistBuddy}
vendor_manifests() {
# Echo the path of every Vendor/*/manifest.json; fail if there are none.
local found=""
for manifest in "${VENDOR_DIR:?VENDOR_DIR not set}"/*/manifest.json; do
[ -f "$manifest" ] || continue
found=1
printf '%s\n' "$manifest"
done
[ -n "$found" ] || {
echo "error: no manifests found under $VENDOR_DIR" >&2
return 1
}
}
manifest_to_plist() {
# $1 = manifest.json path, $2 = destination .plist path
plutil -convert xml1 -o "$2" "$1" || {
echo "error: cannot parse manifest: $1" >&2
return 1
}
}
manifest_field() {
# $1 = converted .plist, $2 = key, $3 = original manifest path (for errors)
"$PLIST_BUDDY" -c "Print :$2" "$1" 2>/dev/null || {
echo "error: manifest $3: missing required field '$2'" >&2
return 1
}
}