#!/usr/bin/env bash # test-domain-unreal.sh - Validate Unreal Engine security extractors # Part of the Comprehensive Vision UAT set -euo pipefail # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" UAT_DIR="$(dirname "$SCRIPT_DIR")" APHORIA_DIR="$(dirname "$UAT_DIR")" STEMEDB_DIR="$(dirname "$(dirname "$APHORIA_DIR")")" # Build Aphoria if needed APHORIA_BIN="${STEMEDB_DIR}/target/release/aphoria" if [[ ! -f "$APHORIA_BIN" ]]; then echo "Building Aphoria..." cargo build --release --package aphoria --manifest-path "${STEMEDB_DIR}/Cargo.toml" fi # Test fixtures directory FIXTURES_DIR="${UAT_DIR}/fixtures/unreal" mkdir -p "$FIXTURES_DIR" PASSED=0 FAILED=0 TOTAL=0 test_case() { local id="$1" local description="$2" TOTAL=$((TOTAL + 1)) echo -e "\n${YELLOW}[$id]${NC} $description" } pass() { PASSED=$((PASSED + 1)) echo -e " ${GREEN}✓ PASS${NC}" } fail() { local reason="$1" FAILED=$((FAILED + 1)) echo -e " ${RED}✗ FAIL: $reason${NC}" } # Create test fixtures for Unreal Engine create_fixtures() { echo "Creating Unreal Engine test fixtures..." # Create a minimal project structure for Unreal mkdir -p "${FIXTURES_DIR}/Source/MyGame" # Vulnerable Unreal C++ header cat > "${FIXTURES_DIR}/Source/MyGame/GameActor.h" << 'EOF' #pragma once #include "CoreMinimal.h" #include "GameFramework/Actor.h" #include "GameActor.generated.h" UCLASS() class MYGAME_API AGameActor : public AActor { GENERATED_BODY() public: // BAD: Exec functions can be called from console by cheaters UFUNCTION(Exec) void CheatGiveGold(); UFUNCTION(Exec, Category="Debug") void DebugTeleport(); // BAD: Replicated without condition - bandwidth waste UPROPERTY(Replicated) int32 PlayerHealth; UPROPERTY(Replicated) FVector LastPosition; protected: // BAD: Hardcoded asset path - fragile void LoadAssets() { UObject* Sword = LoadObject(nullptr, TEXT("/Game/Items/Sword.Sword")); UObject* Shield = LoadObject(nullptr, TEXT("/Engine/BasicShapes/Cube.Cube")); } }; EOF # Clean Unreal C++ header (no issues) cat > "${FIXTURES_DIR}/Source/MyGame/CleanActor.h" << 'EOF' #pragma once #include "CoreMinimal.h" #include "GameFramework/Actor.h" #include "CleanActor.generated.h" UCLASS() class MYGAME_API ACleanActor : public AActor { GENERATED_BODY() public: // GOOD: BlueprintCallable, not Exec UFUNCTION(BlueprintCallable) void SetHealth(int32 NewHealth); // GOOD: Replicated with condition UPROPERTY(ReplicatedUsing=OnRep_Health) int32 Health; UFUNCTION() void OnRep_Health(); protected: // GOOD: Asset reference via UPROPERTY UPROPERTY(EditDefaultsOnly) TSoftObjectPtr SwordAsset; }; EOF # Create a minimal Cargo.toml so the directory looks like a project cat > "${FIXTURES_DIR}/Cargo.toml" << 'EOF' [package] name = "unreal-test-project" version = "0.1.0" edition = "2021" EOF } # Helper to strip ANSI codes strip_ansi() { sed 's/\x1b\[[0-9;]*m//g' } # Test 7.1.1: UFUNCTION(Exec) detected test_exec_function() { test_case "7.1.1" "UFUNCTION(Exec) exposed console command detected" local output output=$("$APHORIA_BIN" scan "${FIXTURES_DIR}" --format json 2>&1 | strip_ansi || true) # Check for claims extracted or conflicts detected (Unreal extractors produce conflicts) if echo "$output" | grep -qE 'claims_extracted=[1-9][0-9]*|conflicts.*\[.*exec_function'; then pass else fail "UFUNCTION(Exec) pattern not detected (no claims extracted)" echo " Output: $(echo "$output" | head -20)" fi } # Test 7.1.2: UPROPERTY(Replicated) without condition test_unconditional_replication() { test_case "7.1.2" "UPROPERTY(Replicated) without condition detected" local output output=$("$APHORIA_BIN" scan "${FIXTURES_DIR}" --format json 2>&1 | strip_ansi || true) # Check for claims extracted (Unreal patterns produce claims) if echo "$output" | grep -qE 'claims_extracted=[1-9][0-9]*'; then pass else fail "Unconditional replication not detected (no claims extracted)" echo " Output: $(echo "$output" | head -20)" fi } # Test 7.1.3: Hardcoded asset path TEXT("/Game/...") test_hardcoded_asset_path() { test_case "7.1.3" "Hardcoded asset path TEXT(\"/Game/...\") detected" local output output=$("$APHORIA_BIN" scan "${FIXTURES_DIR}" --format json 2>&1 | strip_ansi || true) # Check for claims extracted if echo "$output" | grep -qE 'claims_extracted=[1-9][0-9]*'; then pass else fail "Hardcoded asset path not detected (no claims extracted)" echo " Output: $(echo "$output" | head -20)" fi } # Test 7.1.4: Clean Unreal code has no conflicts test_clean_unreal_code() { test_case "7.1.4" "Clean Unreal code produces no false positives" # Create a separate clean-only directory local clean_dir="${FIXTURES_DIR}/clean-only" mkdir -p "${clean_dir}/Source/MyGame" cat > "${clean_dir}/Source/MyGame/CleanActor.h" << 'EOF' #pragma once #include "CoreMinimal.h" #include "GameFramework/Actor.h" #include "CleanActor.generated.h" UCLASS() class MYGAME_API ACleanActor : public AActor { GENERATED_BODY() public: UFUNCTION(BlueprintCallable) void SetHealth(int32 NewHealth); UPROPERTY(ReplicatedUsing=OnRep_Health) int32 Health; UFUNCTION() void OnRep_Health(); protected: UPROPERTY(EditDefaultsOnly) TSoftObjectPtr SwordAsset; }; EOF cat > "${clean_dir}/Cargo.toml" << 'EOF' [package] name = "clean-unreal" version = "0.1.0" edition = "2021" EOF local output output=$("$APHORIA_BIN" scan "${clean_dir}" --format json 2>&1 | strip_ansi || true) # Clean code should have no Unreal-specific conflicts in the JSON output # Check for "conflicts": [] indicating no conflicts found if echo "$output" | grep -q '"conflicts": \[\]'; then pass else # If there are conflicts, verify they're not Unreal-specific ones if echo "$output" | grep -qi 'exec_function\|hardcoded_path\|unconditional_replication'; then fail "Clean Unreal code should not produce Unreal-specific conflicts" echo " Output: $(echo "$output" | head -20)" else pass fi fi } # Run all tests main() { echo "========================================" echo "Aphoria Unreal Engine UAT" echo "========================================" create_fixtures echo "" echo "Running Unreal Engine security tests..." test_exec_function test_unconditional_replication test_hardcoded_asset_path test_clean_unreal_code echo "" echo "========================================" echo "Results: $PASSED/$TOTAL passed, $FAILED failed" echo "========================================" if [[ $FAILED -gt 0 ]]; then exit 1 fi } main "$@"