From 8b95403a3f274eec184a5ed7c2bab8a5676b3d22 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Wed, 21 Jan 2026 01:17:03 +0000 Subject: [PATCH] Remove insecure fallback logic in URL matching to prevent content spoofing This change removes the fallback mechanism in `FindMatchingUrlIndex` (in both `ImageLoader.cs` and `VideoURLProvider.cs`) that would cyclically assign unknown URLs from external lists to existing `VRCUrl` slots. This behavior violated the "Fail Closed" principle and allowed external configurations to spoof captions for unrelated pre-approved images. Fixes a Critical security vulnerability where malicious actors could mislead users by associating trusted images with arbitrary, misleading captions. --- .jules/sentinel.md | 5 +++++ Scripts/ImageLoader.cs | 13 ------------- Scripts/VideoURLProvider.cs | 29 ----------------------------- 3 files changed, 5 insertions(+), 42 deletions(-) diff --git a/.jules/sentinel.md b/.jules/sentinel.md index fbdd504..98a0444 100644 --- a/.jules/sentinel.md +++ b/.jules/sentinel.md @@ -22,3 +22,8 @@ **Vulnerability:** The `ImageLoader` and `VideoURLProvider` scripts validated and upgraded URLs to HTTPS in their string cache for comparisons, but failed to update the actual `VRCUrl` objects used for the download/playback requests. This meant the code *looked* secure (validating strings) but *acted* insecurely (requesting HTTP), creating a false sense of security and leaving users vulnerable to MITM attacks. **Learning:** Validating a shadow copy (cache) of data does not secure the source data. When using object wrappers (like `VRCUrl`), modifying the extracted value does not modify the object itself. Security upgrades must be applied to the actual objects used for operations. **Prevention:** Explicitly replace or upgrade the source objects (e.g., `predefinedUrls[i] = new VRCUrl(secureUrl)`) when sanitizing inputs, rather than just sanitizing the local variable used for logic checks. + +## 2025-05-22 - Prevent Content Spoofing via Fallback Logic +**Vulnerability:** `FindMatchingUrlIndex` contained a fallback mechanism that blindly mapped unknown URLs from external lists to existing, unrelated `VRCUrl` slots when `useGeneratedUrlData` was enabled. This allowed external configuration to apply arbitrary captions to pre-approved images, creating a spoofing vulnerability. +**Learning:** Convenience features (like "auto-mapping" or "cyclic assignment" for unmatched items) often undermine strict allowlist enforcement. "Fail Closed" means if an exact match isn't found, the operation must fail, not guess. +**Prevention:** Remove fallback logic that bypasses exact matching. Ensure that lookups against an allowlist return an error or empty result if the specific item is not found. diff --git a/Scripts/ImageLoader.cs b/Scripts/ImageLoader.cs index 092627a..e39dd83 100644 --- a/Scripts/ImageLoader.cs +++ b/Scripts/ImageLoader.cs @@ -457,19 +457,6 @@ private int FindMatchingUrlIndex(string urlToFind, int additionalCount = 0) } } - // If using generated data, we can use the cyclical assignment - if (useGeneratedUrlData) - { - // Use the next available predefined URL slot (cyclical) - int index = (_activeUrlIndices.Length + additionalCount) % urlCount; - - // Ensure the predefined URL at this index exists - if (index < _predefinedUrlStrings.Length && _predefinedUrlStrings[index] != null) - { - return index; - } - } - // Last resort: find any available predefined URL // REMOVED for security: preventing content spoofing. // If the URL is not found in the predefined list, we should NOT display a random image. diff --git a/Scripts/VideoURLProvider.cs b/Scripts/VideoURLProvider.cs index 376a9a4..6bd39c3 100644 --- a/Scripts/VideoURLProvider.cs +++ b/Scripts/VideoURLProvider.cs @@ -1040,35 +1040,6 @@ private int FindMatchingUrlIndex(string urlToFind, int additionalCount = 0) } } - // If using generated data, we can use the cyclical assignment - if (useGeneratedUrlData) - { - // Use the next available predefined URL slot (cyclical) - // Include additionalCount to account for items currently being batched - int index = (_activeUrlIndices.Length + additionalCount) % urlCount; - - // Ensure the predefined URL at this index exists - if (index < _predefinedUrlStrings.Length && _predefinedUrlStrings[index] != null) - { - // Check if this URL is already used - string newUrl = _predefinedUrlStrings[index]; - for (int j = 0; j < _activeUrlIndices.Length; j++) - { - int existingIndex = _activeUrlIndices[j]; - if (existingIndex < _predefinedUrlStrings.Length && _predefinedUrlStrings[existingIndex] != null) - { - if (_predefinedUrlStrings[existingIndex] == newUrl) - { - Debug.Log($"[VideoURLProvider] URL already exists in playlist, skipping duplicate: {newUrl}"); - return -1; // Skip adding duplicate - } - } - } - - return index; - } - } - // Last resort: find any available predefined URL // REMOVED for security: preventing content spoofing. // If the URL is not found in the predefined list, we should NOT display a random video.