Pastebin

Untitled

text 12 views Created: October 29, 2026 at 10:07:51 EDT
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
================================================================================
SCREECHVR: V12 INDEPENDENT EVIDENCE AUDIT AND CORRECTION PASS
================================================================================

Research date: 2026-10-29
Purpose: Independent evidence audit and correction pass. Not a rewrite of V10.
Verifies claims against actual source code and official documentation.
Resolves contradictions. Produces corrected, evidence-backed report.

No implementation performed. No project files modified. No credentials reproduced.

================================================================================
1. EXECUTIVE SUMMARY
================================================================================

This V12 report is the result of an evidence-based audit of all prior research,
including V10 (50,483 bytes, 954 lines), V11 (25,877 bytes, 434 lines), and all
supporting reports. Every significant claim was rechecked against actual source
code and official documentation.

Key corrected findings:
- ServerGrantCurrency (V08 revision) has NO authorization check. Any authenticated
  player can grant up to 10,000 HC. Severity: HIGH (was labeled "secure").
- AddUserVirtualCurrency vulnerability is CONDITIONAL (depends on PlayFab title
  settings, not confirmed exploitable). Reclassified from "confirmed" to "conditional".
- Webhook URL is a hardcoded secret in ReportPlayer (preserved per user request,
  but should be moved to Title Internal Data).
- Meta User Verification proves account control, NOT device binding. "Hardware-bound"
  wording was incorrect.
- GetAccountInfo does NOT validate Photon tokens (only account existence).
- Custom Worker design for Photon token validation is UNRESOLVED.
- Heartbeat uses sequence validation, NOT cryptographic challenge-response.
  "challengeResponse" field is unused in the handler.
- "48 threat scenarios" claim is INCORRECT (actual matrix has 18 rows).
- €0 vs $1-2/mo domain cost CLARIFIED (domain already owned, €0 means no new
  paid services).
- All tests are PLANNED, not executed. No fabricated results.

10 confirmed vulnerabilities, 5 conditional, 12 unverified (dashboard-dependent).

================================================================================
2. SOURCE INVENTORY
================================================================================

Local project files inspected (read-only):
- Assets/Scripts/Oculus_Login.cs (auth, currency, ban, MOTD, title data, inventory)
- Assets/Scripts/ScreechApi.cs (worker HTTP client)
- Assets/Scripts/PhotonVRManager.cs (networking, rooms, cosmetics, gun)
- Assets/Scripts/PlayerSpawner.cs (spawn/despawn)
- Assets/Scripts/UsernameValidator.cs (content creator check)
- Assets/Scripts/AppEntitlementCheck.cs (Oculus entitlement, log only)
- Assets/Scripts/KickIfBanned.cs, Kick_Player.cs (ban/kick)
- Assets/Scripts/LevelSelect.cs, MapLoader.cs, sceneyessss.cs (scene loading)
- Assets/Scripts/Gamemode_System.cs, GamemodeManager.cs, Gamemode_.cs, DeployGamemode.cs
- Assets/Scripts/GetCosmetics.cs, SecondaryCosmetics.cs, BuyCosmetic.cs, Cosmetic_Yes.cs
- Assets/Scripts/TagManager.cs, TagPlayer.cs, TagLeaderboard.cs
- Assets/Scripts/BestJumpscare.cs (collider kill)
- Assets/Scripts/NewGorillaLocomotionScripts/Player.cs (locomotion)
- Assets/Scripts/Hand_Physic.cs (grab/physics)
- Packages/manifest.json (SDKs)
- Assets/Resources/GorillaPrefabs/Gorilla Rig.prefab

Research documents reviewed:
- research/ (27 reports + README + FINAL_RESEARCH_SUMMARY)
- research/FINAL_SECURITY_ARCHITECTURE/ (26 deliverables)
- docs/screechvr-technical-map-2026-10-28.md
- docs/voideration-screechvr-architecture.md
- docs/voideration-anticheat-research.md
- docs/voideration-anticheat-review.md
- research/QUEST_MODIFICATION_THREAT_CATALOG.md
- SHARED-MEMORY.md, AGENTS.md

Official documentation consulted:
- Meta Quest Attestation API: https://developers.meta.com/vr/documentation/native/ps-attestation-api/ (ACCESSIBLE)
- Photon pricing: https://www.photonengine.com/realtime/pricing (ACCESSIBLE)
- Photon custom authentication: https://doc.photonengine.com/pun/current/connection-and-authentication/authentication/overview-auth (ACCESSIBLE)
- PlayFab AddUserVirtualCurrency: https://learn.microsoft.com/en-us/rest/api/playfab/client/player-item-management/add-user-virtual-currency
- PlayFab PurchaseItem: https://learn.microsoft.com/en-us/rest/api/playfab/client/player-item-management/purchase-item
- PlayFab GetPhotonAuthenticationToken: https://learn.microsoft.com/en-us/rest/api/playfab/client/authentication/get-photon-authentication-token
- PlayFab Photon quickstart: https://learn.microsoft.com/en-us/xbox/playfab/live-service-management/service-gateway/add-ons/photon/quickstart
- OWASP API Security Top 10 2023: https://owasp.org/API-Security/editions/2023/en/0x11-t10/
- OWASP Cryptographic Storage Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html

================================================================================
3. ARCHITECTURE AND TRUST BOUNDARIES
================================================================================

Trust model (verified):
- Client (untrusted): all game logic, movement, currency display, moderator status, cosmetics, IAP grants, leaderboards.
- Photon Cloud (semi-trusted relay): room management, RPC routing, ownership. Master client is a player.
- PlayFab (trusted backend): auth, inventory, currency, bans, title data, leaderboards.
- Cloudflare worker (trusted): CCU, /link, /motd, /redeem, session validation, ban check.
- No dedicated authoritative server exists.

Trust boundaries:
1. Client -> Photon: untrusted input enters network.
2. Photon -> PlayFab: custom auth (server-to-server).
3. PlayFab -> Worker: session validation.
4. Worker -> Dashboard: admin API (backend-enforced).

================================================================================
4. CORRECTED CLAIM LEDGER
================================================================================

For every critical claim: exact source, code behavior, docs, dashboard dependency,
status, corrected conclusion, recommended action.

### 4.1 Currency grants (AddUserVirtualCurrency)

Claim: "Client can grant arbitrary currency via AddCurrency(amount)."
Source: Assets/Scripts/Oculus_Login.cs:269-302 (AddCurrency method)
Code behavior: AddCurrency calls PlayFab AddUserVirtualCurrency with client-specified
  amount. Updates local _currency before server call. Reverts on error.
Docs: PlayFab AddUserVirtualCurrency is a client API. PlayFab validates session
  ticket but NOT the amount. The amount is client-specified.
Dashboard dependency: Whether clients can call AddUserVirtualCurrency depends on
  PlayFab title settings (client access to economy APIs). This is a CONFIGURATION
  question, not a code question.
Status: CONDITIONAL (not confirmed exploitable). If client access is enabled in
  PlayFab title settings, it is a CRITICAL vulnerability. If disabled, only
  server-side calls work (and the vulnerability doesn't exist).
Corrected conclusion: The code allows client-specified amounts, but actual
  exploitability depends on PlayFab title configuration. Must verify in dashboard.
Recommended action: Move currency grants to server-side (CloudScript/worker) regardless.
  Verify PlayFab title settings for client access to AddUserVirtualCurrency.

### 4.2 Moderator authorization (ReportPlayer)

Claim: "Client can self-promote to moderator by setting PlayFab UserData
'Moderator'='TRUE'."
Source: Assets/Scripts/Oculus_Login.cs:392-428 (CreateKeyIfNot)
  Assets/Scripts/Check_Mod.cs (sets AccountPref based on UserData)
  Assets/Scripts/Mod_Toggle.cs (opens ModMenu if DefaultQueue == "MODDED")
Code behavior: CreateKeyIfNot reads PlayFab UserData "Moderator" key. If "TRUE",
  AccountPref = Moderator. Check_Mod sets AccountPref after 5s timeout.
Docs: PlayFab UserData is client-writable by default (PlayFab docs). Server/UpdateUserData
  requires server credentials. Client/UpdateUserData allows client writes.
Dashboard dependency: Whether UserData writes are restricted depends on PlayFab
  title settings (client access to UserData).
Status: CONDITIONAL (not confirmed exploitable). If UserData is client-writable,
  CRITICAL. If restricted to server-only, not exploitable.
Corrected conclusion: The code trusts client-writable UserData for moderator status.
  This is a vulnerability IF UserData is client-writable (likely, per PlayFab defaults).
  Must verify in PlayFab dashboard.
Recommended action: Move moderator status to server-side (ReadOnlyData or server claim).
  Verify PlayFab UserData write permissions.

### 4.3 Purchases (BuyCosmetic, OnPurchaseItem)

Claim: "Client can buy cosmetics at wrong price."
Source: Assets/Scripts/BuyCosmetic.cs:33 (checks local _currency >= Price)
  PlayFab CloudScript: OnPurchaseItem (accepts price from client)
Code behavior: BuyCosmetic checks local balance, calls PurchaseItem (PlayFab validates
  price server-side against catalog). OnPurchaseItem (CloudScript) accepts price from
  client args (should use server-side catalog price).
Docs: PlayFab PurchaseItem validates price server-side against catalog.
  PlayFab AddUserVirtualCurrency validates session but NOT amount.
Dashboard dependency: PlayFab catalog configuration (prices, items). Whether
  PurchaseItem validates price depends on catalog setup.
Status: PARTIALLY VERIFIED. PlayFab PurchaseItem validates price server-side (strong
  evidence from docs). But OnPurchaseItem (CloudScript) accepts client-supplied price
  (verified from source code). The client-side gate (BuyCosmetic) is cosmetic only.
Corrected conclusion: PlayFab PurchaseItem is server-validated. But OnPurchaseItem
  (CloudScript) accepts client price (vulnerability if called directly). Fix: remove
  price from client args, look up server-side.
Recommended action: Fix OnPurchaseItem to use server-side catalog price. Remove price
  from client args.

### 4.4 Ban enforcement (KickIfBanned, Kick_Player)

Claim: "Modified client can ignore bans."
Source: Assets/Scripts/KickIfBanned.cs (polls GetAccountInfo every 5s)
  Assets/Scripts/Kick_Player.cs (OnTriggerEnter -> Application.Quit)
Code behavior: KickIfBanned polls PlayFab GetAccountInfo. On AccountBanned error,
  calls Application.Quit + Disconnect + LoadScene. Kick_Player: on trigger enter on
  "Kick" layer, non-owner quits.
Docs: PlayFab bans are server-side (admin API). GetAccountInfo returns ban status.
  Photon custom auth can enforce bans on connect (server-side).
Status: VERIFIED (code confirms client-side enforcement only). No server-side
  kick enforcement exists.
Corrected conclusion: Bans are enforced client-side only. Modified client can
  ignore. Fix: Photon custom auth ban check on connect.
Recommended action: Implement Photon custom auth with ban check. Keep KickIfBanned
  as supplementary (5s delay).

### 4.5 Heartbeat replay protection

Claim: "Heartbeat has replay protection (sequence numbers, timestamp freshness)."
Source: PlayFab CloudScript: Heartbeat handler (in V08 revision)
Code behavior: Handler checks sequenceNumber > lastSeq, timestamp within 5 min,
  rate limit (max 1 per 4 min). Updates last_heartbeat_seq and last_heartbeat_time.
Docs: PlayFab CloudScript execution context. server.GetUserInternalData/UpdateUserInternalData.
Status: PROPOSED (not implemented). The handler exists in the V08 draft revision but
  has NOT been deployed. No tests executed.
  NOTE: The "challenge-response" is a sequence number + timestamp, not a cryptographic
  challenge-response. The "challengeResponse" field is unused in the handler.
Corrected conclusion: Heartbeat design uses sequence validation, not cryptographic
  challenge-response. The "challengeResponse" field is unused. Design is documented
  but not implemented or tested.
Recommended action: Implement actual challenge-response (server issues nonce, client
  returns hash) or rename to "sequence validation." Deploy and test.

### 4.6 Meta identity vs App Attestation

Claim: "Meta User Verification proves hardware-bound identity."
Source: research documents (prior). Corrected in V10.
Code behavior: Oculus_Login.cs uses Users.GetLoggedInUser() -> Oculus ID. No proof
  verification. LoginWithCustomID uses Oculus ID as CustomId.
Docs: Meta User Verification (getUserProof) proves account control, not device binding.
  Meta App Attestation (GetIntegrityToken) proves device/app integrity.
Status: CORRECTED (V10 fixed wording). Meta identity proves account control, NOT
  device binding. "Hardware-bound" was inaccurate.
Corrected conclusion: Meta User Verification proves user controls the Meta account.
  Does NOT prove device integrity or game integrity. Separate from App Attestation.
Recommended action: Implement Meta User Verification for identity proof. Add Meta
  App Attestation as optional device integrity signal.

### 4.7 Photon authentication

Claim: "Worker validates Photon token via GetAccountInfo."
Source: V08 revision and research docs (prior). Corrected in V10/V11.
Code behavior: Worker receives Photon token from Photon's servers (server-to-server).
  Worker cannot validate Photon token via GetAccountInfo (GetAccountInfo verifies
  account existence, not token validity).
Docs: PlayFab /photon/authenticate endpoint validates Photon tokens. Photon custom
  auth delegates to this endpoint.
Status: CORRECTED. Worker delegates to PlayFab's /photon/authenticate endpoint.
  Custom Worker design for token validation is UNRESOLVED (no documented
  independent verification mechanism).
Corrected conclusion: PlayFab's /photon/authenticate is the standard flow. Custom
  Worker must delegate to it. GetAccountInfo is for ban checks, not token validation.
Recommended action: Use PlayFab's standard /photon/authenticate endpoint. Add ban
  check via Server/GetUserAccountInfo after validation.

### 4.8 Worker route status

Claim: "Worker has /validate-session, /heartbeat, /report-flag, /ban-check endpoints."
Source: docs/voideration-screechvr-architecture.md (proposed). Verified against
  ScreechApi.cs (only /updateplayers, /redeem, /motd exist).
Status: PROPOSED (not implemented). Only 3 endpoints exist. The other 4 are proposed
  in architecture docs.
Corrected conclusion: Only 3 endpoints exist. The rest are proposed. No new
  endpoints have been implemented.
Recommended action: Implement proposed endpoints in Stage 1.

### 4.9 Webhook exposure

Claim: "Hardcoded webhook URL in ReportPlayer."
Source: PlayFab CloudScript (original revision A). Verified: webhook URL is
  hardcoded in ReportPlayer handler.
Status: VERIFIED (code confirms hardcoded webhook URL in ReportPlayer).
  Preserved per user request in V08 revision (kept original functionality).
Corrected conclusion: Webhook URL is a secret. Should be moved to Title Internal
  Data. Preserved per user request but documented as security concern.
Recommended action: Move webhook URL to Title Internal Data (getWebhookUrl pattern).

### 4.10 Pricing

Claim: "Photon free tier is 20 CCU (dev only). 100 CCU = $95/12mo."
Source: Photon pricing page (fetched 2026-10-29). VERIFIED.
Status: VERIFIED (from official pricing page).
Corrected conclusion: Photon free tier is 20 CCU (development only). Paid plans
  start at $95 one-time (100 CCU, 12-month term). PUN 2 is in maintenance/LTS mode.
Recommended action: Budget for Photon paid plan at launch. Consider Fusion for new projects.

### 4.11 Threat scenario count

Claim: "48 distinct threat scenarios in the threat matrix."
Source: V10 report section 28. Verified: the matrix references 18-row matrix in
  ANTI_CHEAT_PREVENTION_DETECTION_MATRIX.md. The "48 scenarios" claim is from the
  V10 prompt's requested list of 48 scenario types, not from actual analysis.
Status: INCORRECT. The actual matrix has 18 rows (threats), not 48. The 48-item
  list was a prompt requirement, not an analysis output.
Corrected conclusion: Threat matrix has 18 rows (confirmed threats). The 48-item
  list was a research prompt requirement, not an analysis result. No additional
  threats were identified beyond the 18 in the matrix.
Recommended action: Update V10 to reflect actual 18-row matrix. Do not claim 48 scenarios.

### 4.12 Cost contradiction (€0 vs $1-2/mo)

Claim: "€0 additional spend" but "Initial: $1-2/mo (domain only)."
Source: Multiple reports. The $1-2/mo is for domain registration (already owned).
  The €0 refers to additional services/subscriptions.
Status: CLARIFIED. €0 additional recurring spend means no new paid services. Domain
  is already owned ($10-15/yr, already paid). Cloudflare free tier covers everything else.
Corrected conclusion: €0 additional monthly spend for new services. Domain already
  owned and paid for. No new recurring costs for v1.
Recommended action: Clarify in all docs that €0 means no new paid services.

### 4.13 ServerGrantCurrency authorization

Claim: "ServerGrantCurrency is secure (but needs authorization check)."
Source: V08 revision. Verified: ServerGrantCurrency validates amount (1-10000) but
  no authorization check. Any authenticated player can call it.
Status: INCORRECT. ServerGrantCurrency has no authorization check. Any authenticated
  player can grant up to 10,000 HC.
Corrected conclusion: ServerGrantCurrency is NOT secure. It validates amount but
  not authorization. Fix: add server-side authorization (only admins/moderators).
Recommended action: Add authorization check before granting currency.

### 4.14 Heartbeat challenge-response

Claim: "Heartbeat has replay protection (sequence numbers, timestamp freshness)."
Source: V08 revision. Verified: Heartbeat handler checks sequenceNumber > lastSeq,
  timestamp within 5 min, rate limit (max 1 per 4 min). Updates last_heartbeat_seq
  and last_heartbeat_time.
Status: PROPOSED (not implemented). The handler exists in the V08 draft revision but
  has NOT been deployed. No tests executed. The "challenge-response" is a sequence
  number + timestamp, not a cryptographic challenge-response. The "challengeResponse"
  field is unused in the handler.
Corrected conclusion: Heartbeat design uses sequence validation, not cryptographic
  challenge-response. The "challengeResponse" field is unused. Design is documented
  but not implemented or tested.
Recommended action: Implement actual challenge-response (server issues nonce, client
  returns hash) or rename to "sequence validation." Deploy and test.

================================================================================
3. CONTRADICTION LEDGER
================================================================================

| # | Location | Conflicting statements | Evidence | Corrected conclusion |
|---|---|---|---|---|
| 1 | Section 4 vs Section 16 | "Worker cannot validate PlayFab session ticket" vs "Client MUST send session ticket" | Code: worker receives Photon token, not session ticket (ScreechApi.cs, Oculus_Login.cs) | Worker does NOT need session ticket. Validates Photon token via PlayFab /photon/authenticate. |
| 2 | Section 4 vs 16 | "GetAccountInfo validates Photon token" vs "GetAccountInfo verifies account existence, not token validity" | PlayFab docs: GetAccountInfo returns account info, not token validation | GetAccountInfo is for ban checks, not token validation. |
| 3 | Section 16 vs 20 | "Hardcoded webhook retained per user request" vs "no secrets reproduced" | Code: webhook URL is hardcoded in ReportPlayer | Webhook URL is a secret. Should be moved to Title Internal Data. Preserved per user request but documented as security concern. |
| 4 | Section 5 vs 13 | "Meta identity is hardware-bound" vs "Meta identity proves account control" | Meta docs: getUserProof proves account control, not device binding | "Hardware-bound" is inaccurate. Correct: account control proof. |
| 5 | Section 12 vs 16 | "Worker has /validate-session, /heartbeat, /report-flag, /ban-check" vs "only /updateplayers, /redeem, /motd exist" | ScreechApi.cs: only 3 endpoints exist | Only 3 endpoints exist. The rest are proposed. |
| 6 | Section 15b vs 12 | "Dashboard on Cloudflare Pages" vs "Dashboard is local-only" | User preference: local dashboard | Dashboard is local-only (http://127.0.0.1:<port>). No Cloudflare Pages. |
| 7 | Section 8 vs 12 | "30s heartbeat" vs "5-min heartbeat" | Cost analysis: 30s exceeds free tier | 5-min heartbeat (within free tier at 100 CCU). No KV writes. |
| 8 | Section 2 vs 12 | "€0 additional spend" vs "$1-2/mo domain" | Domain already owned ($10-15/yr). €0 means no new paid services. | €0 additional monthly spend for new services. Domain already paid. |
| 9 | Section 28 vs 13 | "48 threat scenarios" vs "18-row matrix" | ANTI_CHEAT_PREVENTION_DETECTION_MATRIX.md has 18 rows | Matrix has 18 rows. "48 scenarios" was a prompt requirement, not an analysis output. |
| 10 | Section 20 vs 15 | "ServerGrantCurrency is secure" vs "needs authorization check" | Code: ServerGrantCurrency validates amount (1-10000) but no authorization check | NOT secure. Any authenticated player can grant up to 10,000 HC. Fix: add server-side authorization. |
| 11 | Section 4 vs 16 | "Heartbeat has challenge-response" vs "challengeResponse field unused" | Code: Heartbeat handler checks sequenceNumber and timestamp, but never uses challengeResponse | Heartbeat uses sequence validation, not cryptographic challenge-response. Rename or implement actual challenge-response. |
| 12 | Section 12 vs 16 | "Dashboard on Cloudflare Pages" vs "Dashboard is local-only" | User preference: local dashboard | Dashboard is local-only (http://127.0.0.1:<port>). No Cloudflare Pages. |

================================================================================
4. OFFICIAL-SOURCE VERIFICATION
================================================================================

PlayFab AddUserVirtualCurrency:
- URL: https://learn.microsoft.com/en-us/rest/api/playfab/client/player-item-management/add-user-virtual-currency
- Finding: Client API. Accepts VirtualCurrency and Amount. Requires session ticket.
- Verification: PlayFab validates session ticket but NOT amount. Amount is client-specified.
- Status: VERIFIED (docs + code).

PlayFab PurchaseItem:
- URL: https://learn.microsoft.com/en-us/rest/api/playfab/client/player-item-management/purchase-item
- Finding: Client API. Accepts ItemId, VirtualCurrency, Price, CatalogVersion.
- Verification: PlayFab validates price against catalog server-side. Price must match catalog.
- Status: STRONG EVIDENCE (docs say server validates, verify catalog config).

PlayFab GetPhotonAuthenticationToken:
- URL: https://learn.microsoft.com/en-us/rest/api/playfab/client/authentication/get-photon-authentication-token
- Finding: Returns PhotonCustomAuthenticationToken. Used for Photon custom auth.
- Verification: Token is short-lived. Photon sends it to custom auth URL for validation.
- Status: VERIFIED (docs).

PlayFab /photon/authenticate:
- URL: https://<titleId>.playfabapi.com/photon/authenticate
- Finding: Photon's servers call this endpoint server-to-server. PlayFab validates the Photon token.
- Verification: This is the standard flow. Custom Worker must delegate to this endpoint.
- Status: VERIFIED (docs).

Meta User Verification:
- URL: https://developers.meta.com/vr/documentation/spatial-sdk/ps-ownership/
- Finding: getUserProof returns proof of account control. Server validates with Meta.
- Verification: Docs partially accessible (404 on some pages). Core concept verified.
- Status: STRONG EVIDENCE (docs partially accessible).

Meta App Attestation:
- URL: https://developers.meta.com/vr/documentation/native/ps-attestation-api/
- Finding: ovr_DeviceApplicationIntegrity_GetIntegrityToken returns attestation token. Server verifies with Meta.
- Verification: Full docs accessible. Token valid 24h, nonce one-time, timestamp freshness, rate limits.
- Status: VERIFIED (full docs accessible).

Photon Custom Authentication:
- URL: https://doc.photonengine.com/pun/current/connection-and-authentication/authentication/custom-authentication
- Finding: Photon's servers call custom auth URL. Backend validates credentials. Returns ResultCode 0/1/2/3.
- Verification: Docs accessible. Response codes verified.
- Status: VERIFIED (docs accessible).

Photon Pricing:
- URL: https://www.photonengine.com/realtime/pricing
- Finding: Free tier 20 CCU (dev only). 100 CCU $95/12mo. 500 CCU $95/mo. 1000 CCU $185/mo.
- Verification: Pricing page accessible. Prices verified.
- Status: VERIFIED (docs accessible).

Cloudflare Workers:
- URL: https://developers.cloudflare.com/workers/platform/pricing/
- Finding: Free 100k req/day. Paid $5/mo + $0.50/million.
- Verification: Pricing page accessible.
- Status: VERIFIED (docs accessible).

Cloudflare D1:
- URL: https://developers.cloudflare.com/d1/platform/limits/
- Finding: Free 5GB, 5M reads/day, 100k writes/day.
- Verification: Limits page accessible.
- Status: VERIFIED (docs accessible).

================================================================================
5. CONFIRMED VS CONDITIONAL VULNERABILITIES
================================================================================

Confirmed (verified against source code):
- V3: Client-side ban enforcement (KickIfBanned, Kick_Player). Confirmed.
- V5: No movement validation (Player.cs, all client-side). Confirmed.
- V6: Master client abuse (AutomaticallySyncScene, scene sync). Confirmed.
- V7: No anti-cheat scripts. Confirmed.
- V8: Photon RPCs lack ownership/param validation (ThusterController, Flash_Light). Confirmed.
- V9: Null crashes (PlayerSpawner, Hand_Physic, Monster_Track). Confirmed.
- V10: AppEntitlementCheck logs only (no quit). Confirmed.
- V11: Photon auth bypassable if anonymous enabled. Confirmed (code + docs).
- V12: Leaderboard faking (GDH client-submitted). Confirmed (code).
- V13: Tag/Infection RPC manipulation (TagPlayer, TagManager). Confirmed (code).

Conditional (depends on dashboard/config):
- V1: Client-trusted currency (AddUserVirtualCurrency). CONDITIONAL on PlayFab title settings (client access). If enabled, CRITICAL.
- V2: Client-trusted moderator status (UserData "Moderator"). CONDITIONAL on PlayFab UserData write permissions. If client-writable, CRITICAL.
- V4: IAP bypass (SpokesSigmaIAP). CONDITIONAL on receipt validation (not fully read).
- V14: ATM_TAB currency flow (not deeply read). CONDITIONAL.
- V15: GDH leaderboard anti-cheat (unknown). CONDITIONAL.

Unverified (requires access/testing):
- Meta attestation availability to ScreechVR.
- Meta User Verification SDK compatibility.
- PlayFab CloudScript deployment status.
- PlayFab PurchaseItem price validation.
- Photon custom auth configuration.
- D1 write throughput.
- Free tier limits at scale.

================================================================================
6. DASHBOARD-DEPENDENT UNKNOWNNS
================================================================================

The following require PlayFab/Photon dashboard access to verify:
1. PlayFab UserData "Moderator" key: client-writable? (CRITICAL if yes)
2. CloudScript/Azure Functions deployed? (none in repo)
3. PlayFab PurchaseItem validates price server-side? (assumed yes)
4. PlayFab bans enforced server-side? (assumed client-only)
5. Photon custom auth configured? (dashboard not inspected)
6. "Allow anonymous clients" disabled? (dashboard not inspected)
7. Dev/prod app IDs separate? (dashboard not inspected)
8. Meta attestation available to ScreechVR? (docs accessible, eligibility unverified)
9. Meta User Verification SDK compatibility? (requires testing)
10. SpokesSigmaIAP receipt validation (requires reading script + catalog)
11. GDH leaderboard anti-cheat (requires inspecting GDH package)
12. ATM_TAB currency flow (requires reading ATM_TAB.cs + Atm_Manager.cs)

================================================================================
7. PRIORITIZED NEXT ACTIONS
================================================================================

1. Verify PlayFab UserData "Moderator" writability (CRITICAL if true).
2. Verify CloudScript/Azure Functions deployment status.
3. Verify PlayFab PurchaseItem price validation.
4. Verify Photon custom auth configuration.
5. Move currency grants to server-side (CloudScript/worker).
6. Implement Photon custom auth for connect-time ban enforcement.
7. Add Meta User Verification (getUserProof) for identity proof.
8. Implement detection rules (S-001..S-012) with flag + review queue.
9. Fix null crashes (PlayerSpawner, Hand_Physic, Monster_Track).
10. Fix ThusterController/Flash_Light RPC floods.
11. Fix Tag/Infection RPC manipulation.
12. Move webhook URL to Title Internal Data.
13. Add AppEntitlementCheck quit on failure.
14. Implement heartbeat (5-min interval, sequence numbers, replay protection).
15. Build dashboard (local-only, http://127.0.0.1:<port>).

================================================================================
8. VERIFICATION RESULTS
================================================================================

Local file (V10): research/SCREECHVR_SECURITY_RESEARCH_V10_2026-10-29.txt
- Size: 50,483 bytes
- Characters: 50,483
- Lines: 954
- Sections: 36 (all present)
- Ends with: END OF REPORT (verified)
- Credentials: none reproduced (verified)

V11 report: research/SCREECHVR_SECURITY_RESEARCH_V11_2026-10-29.txt
- Size: 25,877 bytes
- Characters: 25,877
- Lines: 434
- Sections: 8 (focused correction, not 36)
- Ends with: END OF REPORT (verified)
- Credentials: none reproduced (verified)

No implementation performed. No project files modified. No services deployed.
No production data changed. No tests executed. No credentials reproduced.

================================================================================
END OF REPORT
================================================================================

Embed this paste

Install this app

  1. Tap the Share button
  2. Scroll down and tap "Add to Home Screen"
  3. Tap "Add" in the top right

Please confirm