diff --git a/.github/workflows/provenance-audit.yml b/.github/workflows/provenance-audit.yml new file mode 100644 index 0000000..2902fa1 --- /dev/null +++ b/.github/workflows/provenance-audit.yml @@ -0,0 +1,111 @@ +name: One-time bundled provenance audit + +on: + push: + branches: + - feature/client-tweaks + paths: + - .github/workflows/provenance-audit.yml + +permissions: + contents: read + +jobs: + audit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Identify bundled binaries + shell: bash + run: | + set -euo pipefail + + echo "=== LOCAL BINARIES ===" + for f in Payload/VanillaFixes.exe Payload/VfPatcher.dll Payload/transmogfix.dll Payload/WeirdUtils/bigcursor.dll Payload/WeirdUtils/customassets.dll Payload/WeirdUtils/logsessions.dll Payload/WeirdUtils/minimapicons.dll Payload/WeirdUtils/pngscreenshots.dll Payload/WeirdUtils/worldmarkers.dll + do + if [ -f "$f" ]; then + sha256sum "$f" + stat -c '%s bytes %n' "$f" + fi + done + + echo + echo "=== VANILLAFIXES 1.5.3 ===" + curl -fL --retry 3 -o /tmp/vf.zip https://github.com/hannesmann/vanillafixes/releases/download/v1.5.3/vanillafixes-1.5.3.zip + rm -rf /tmp/vf + mkdir -p /tmp/vf + unzip -q /tmp/vf.zip -d /tmp/vf + find /tmp/vf -maxdepth 3 -type f -printf '%P\n' + for local in Payload/VanillaFixes.exe Payload/VfPatcher.dll; do + name="$(basename "$local")" + remote="$(find /tmp/vf -type f -iname "$name" | head -n 1 || true)" + if [ -n "$remote" ]; then + echo "REMOTE $name" + sha256sum "$remote" + stat -c '%s bytes' "$remote" + cmp -s "$local" "$remote" && echo "MATCH $name VanillaFixes=v1.5.3" || echo "NO_MATCH $name VanillaFixes=v1.5.3" + else + echo "NOT_FOUND $name in VanillaFixes v1.5.3" + fi + done + + echo + echo "=== CODEBERG WEIRDUTILS RELEASES ===" + curl -fsSL --retry 3 'https://codeberg.org/api/v1/repos/MarcelineVQ/WeirdUtils/releases?limit=50' -o /tmp/weird-releases.json + + jq -r '.[] | "RELEASE tag=" + (.tag_name // "") + " name=" + (.name // "")' /tmp/weird-releases.json + + mkdir -p /tmp/weird-assets + python3 - <<'PY' + import json, os, urllib.request + + local_paths = { + "transmogfix.dll": "Payload/transmogfix.dll", + "bigcursor.dll": "Payload/WeirdUtils/bigcursor.dll", + "customassets.dll": "Payload/WeirdUtils/customassets.dll", + "logsessions.dll": "Payload/WeirdUtils/logsessions.dll", + "minimapicons.dll": "Payload/WeirdUtils/minimapicons.dll", + "pngscreenshots.dll": "Payload/WeirdUtils/pngscreenshots.dll", + "worldmarkers.dll": "Payload/WeirdUtils/worldmarkers.dll", + } + + with open("/tmp/weird-releases.json", "r", encoding="utf-8") as f: + releases = json.load(f) + + import hashlib + def sha256(path): + h = hashlib.sha256() + with open(path, "rb") as f: + for chunk in iter(lambda: f.read(1024 * 1024), b""): + h.update(chunk) + return h.hexdigest() + + for rel in releases: + tag = rel.get("tag_name") or rel.get("name") or "unknown" + for asset in rel.get("assets", []): + name = asset.get("name", "") + key = name.lower() + if key not in local_paths: + continue + url = asset.get("browser_download_url") + if not url: + continue + out = f"/tmp/weird-assets/{tag.replace('/', '_')}-{name}" + try: + req = urllib.request.Request(url, headers={"User-Agent":"Modernization-Tool provenance audit"}) + with urllib.request.urlopen(req, timeout=60) as r, open(out, "wb") as w: + w.write(r.read()) + local = local_paths[key] + same = ( + os.path.exists(local) + and os.path.getsize(local) == os.path.getsize(out) + and sha256(local) == sha256(out) + ) + print( + f"{'MATCH' if same else 'NO_MATCH'} {name} WeirdUtils={tag} " + f"remote_sha256={sha256(out)} remote_size={os.path.getsize(out)}" + ) + except Exception as exc: + print(f"DOWNLOAD_ERROR {name} WeirdUtils={tag}: {exc}") + PY