test-release-manifest.sh

5.3 KB · raw

1#!/bin/sh2# Hermetic negative-path tests for the release-manifest inventory drift gate3# (PB-26-113). No Android SDK, Gradle project, or merged build output required.4set -eu56SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)7CHECK="$SCRIPT_DIR/check-release-manifest.py"89TEMP_ROOT=$(mktemp -d "${TMPDIR:-/tmp}/peach-release-manifest-tests.XXXXXX")10trap 'trash "$TEMP_ROOT"' EXIT HUP INT TERM1112MERGED="$TEMP_ROOT/AndroidManifest.xml"13INVENTORY="$TEMP_ROOT/inventory.txt"1415fail() {16    printf 'FAIL: %s\n' "$1" >&217    exit 118}1920write_manifest() {21    cat > "$MERGED" <<XML22<?xml version="1.0" encoding="utf-8"?>23<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.peachpasswords">24    <uses-permission android:name="android.permission.INTERNET"/>25    $126    <application android:name=".App">27        <activity android:name=".MainActivity" android:exported="true">28            <intent-filter>29                <action android:name="android.intent.action.MAIN"/>30                <category android:name="android.intent.category.LAUNCHER"/>31            </intent-filter>32        </activity>33    </application>34</manifest>35XML36}3738write_manifest ""39python3 "$CHECK" write "$MERGED" "$INVENTORY"40[ -s "$INVENTORY" ] || fail "write produced no inventory"41grep -q '^permission|android.permission.INTERNET|' "$INVENTORY" ||42    fail "inventory is missing the declared permission"4344python3 "$CHECK" check "$MERGED" "$INVENTORY"45python3 "$CHECK" write "$MERGED" "$INVENTORY"46python3 "$CHECK" check "$MERGED" "$INVENTORY"4748# A permission added to the merged manifest after the inventory was recorded49# must refuse, and must say so rather than crashing.50write_manifest '<uses-permission android:name="android.permission.CAMERA"/>'51if output=$(python3 "$CHECK" check "$MERGED" "$INVENTORY" 2>&1); then52    fail "drifted merged manifest was accepted"53fi54case "$output" in55    *"differs from checked-in inventory"*) ;;56    *) fail "drift refusal did not report drift: $output" ;;57esac5859# Missing inputs fail closed instead of reporting a clean comparison.60if python3 "$CHECK" check "$TEMP_ROOT/absent.xml" "$INVENTORY" >/dev/null 2>&1; then61    fail "a missing merged manifest was accepted"62fi63if python3 "$CHECK" check "$MERGED" "$TEMP_ROOT/absent.txt" >/dev/null 2>&1; then64    fail "a missing inventory was accepted"65fi6667# An exposure-bearing attribute changed without any name or exported flag68# changing must also refuse (PB-26-133): these three cases all passed the old69# inventory silently.70write_provider_manifest() {71    cat > "$MERGED" <<XML72<?xml version="1.0" encoding="utf-8"?>73<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.peachpasswords">74    <uses-permission android:name="android.permission.INTERNET"/>75    <queries><package android:name="com.example"/></queries>76    <application android:name=".App" android:allowBackup="false">77        <provider android:name=".Files" android:authorities="com.peachpasswords.files" android:exported="false" android:grantUriPermissions="$1"/>78    </application>79</manifest>80XML81}8283write_provider_manifest "false"84python3 "$CHECK" write "$MERGED" "$INVENTORY"85python3 "$CHECK" check "$MERGED" "$INVENTORY"86write_provider_manifest "true"87if python3 "$CHECK" check "$MERGED" "$INVENTORY" >/dev/null 2>&1; then88    fail "a granted URI permission was accepted as no drift"89fi9091# Nested intent-filter data attributes are security-relevant and must drift.92cat > "$MERGED" <<'XML'93<?xml version="1.0" encoding="utf-8"?>94<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.peachpasswords">95    <application android:name=".App">96        <activity android:name=".MainActivity" android:exported="true">97            <intent-filter>98                <action android:name="android.intent.action.VIEW"/>99                <data android:host="example.com" android:scheme="https"/>100            </intent-filter>101        </activity>102    </application>103</manifest>104XML105python3 "$CHECK" write "$MERGED" "$INVENTORY"106grep -q '^intent-filter-data|activity|.MainActivity|host=example.com;scheme=https$' "$INVENTORY" ||107    fail "inventory is missing nested intent-filter data"108python3 "$CHECK" check "$MERGED" "$INVENTORY"109sed 's/android:host="example.com"/android:host="evil.example.com"/' "$MERGED" > "$MERGED.changed"110mv "$MERGED.changed" "$MERGED"111if python3 "$CHECK" check "$MERGED" "$INVENTORY" >/dev/null 2>&1; then112    fail "nested intent data drift was accepted"113fi114115cat > "$MERGED" <<'XML'116<?xml version="1.0" encoding="utf-8"?>117<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.peachpasswords">118    <uses-permission android:name="android.permission.INTERNET" android:maxSdkVersion="32"/>119    <application android:name=".App"/>120</manifest>121XML122if python3 "$CHECK" check "$MERGED" "$INVENTORY" >/dev/null 2>&1; then123    fail "a new maxSdkVersion was accepted as no drift"124fi125126cat > "$MERGED" <<'XML'127<?xml version="1.0" encoding="utf-8"?>128<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.peachpasswords">129    <uses-permission android:name="android.permission.INTERNET"/>130    <application android:name=".App" android:debuggable="true"/>131</manifest>132XML133if python3 "$CHECK" check "$MERGED" "$INVENTORY" >/dev/null 2>&1; then134    fail "a debuggable application element was accepted as no drift"135fi136137printf 'PASS: release manifest inventory drift gate\n'