Pastebin

Untitled

text 9 views Created: October 30, 2026 at 11:35:07 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
SCREECHVR V16: MODERATOR + CURRENCY SECURITY REVIEW
Date: 2026-10-30
Scope: Read-only review of supplied source bundle, local Unity source, V08 draft,
and official documentation. No code, revisions, dashboards, or production
services changed. V08 is explicitly a draft, not verified as deployed.

EXECUTIVE SUMMARY

The game derives moderator state from client-writable PlayFab UserData and then
uses that local state to gate moderator UI/actions. This is not a trusted
authorization boundary. In V08, ReportPlayer checks client-supplied ReporterId
against a hardcoded list and then invokes a privileged ban operation; if the
handler is callable by clients, this is critical authorization bypass. The
draft ServerGrantCurrency has no role check and grants to the authenticated
caller. Unity also has multiple direct client API currency grant paths. Their
actual exploitability depends partly on PlayFab API/title settings and live
backend configuration; source confirms the requests and trust assumptions, not
the production settings.

1. MODERATOR STATUS AND ACTIONS

Unity source reviewed:
- `! Screech VR/Screech VR/Assets/Scripts/Oculus_Login.cs`
  - `CreateKeyIfNot()` reads UserData key `Moderator`; if absent it writes
    `FALSE` using client `UpdateUserData`. A stored `TRUE` sets local
    `AccountPref = Moderator`.
  - No client source path found that legitimately assigns `TRUE`; this does not
    make the key secure. A player with client write access can attempt to set
    their own key.
  - `OnLoginSuccess()` also starts account-data reads; no server-verified role
    authorization is shown in this login path.
- `! Screech VR/Screech VR/Assets/Scripts/Check_Mod.cs`
  - `CheckModeratorCoroutine` reads local `Oculus_Login.Instance.AccountPref`
    and enables moderator-only objects. This is client-side UI/object gating.
- `! Screech VR/Screech VR/Assets/Scripts/Mod_Toggle.cs`
  - Toggle checks collider/finger and, in the Yes path, local Photon queue
    `MODDED`. It does not validate trusted moderator status.
- Related callers: `SmilerTouch.cs` and `TouchKick.cs` use local moderator checks;
  their Photon event 230 path asks the target client to quit. This is not a
  server-enforced kick/ban. `GDH Packages/LeaderBoard/Scripts/LeaderBoardManager.cs`
  invokes CloudScript `ReportPlayer` (see below).

CloudScript reviewed:
- `revisions/SCREECHVR_PLAYFAB_REVISION_V08_2026-10-29.js` (header says draft,
  not deployed). `isModServerSide` reads `IsMod` from player ReadOnlyData
  (lines 56-66); `VerifyModerator` uses `currentPlayerId` (508-513). These are
  safer patterns in the draft but do not protect every handler.
- V08 `ReportPlayer` (382-410) instead checks client `Args.ReporterId` against
  hardcoded moderator IDs (392-395), then uses client `Args.TargetId` for ban
  (and client-supplied report details). It does not call `isModServerSide` or
  bind reporter identity to `currentPlayerId`. This is a confirmed flaw in the
  draft source. Severity: Critical if client-callable/deployed; deployment and
  handler access are unknown. Do not describe as a live exploit without those
  facts.
- V08 `ServerGrantCurrency` (515-540) checks amount/reason presence and caps
  amount at 10,000, but has no moderator/operator authorization check. It grants
  to `currentPlayerId`. Severity: High if client-callable/deployed.
- `ReportPlayer` source uses hardcoded webhook URL; no server-owned permission
  check. The helper for server-side mod state does not help unless the specific
  action invokes it.

Confirmed vs configuration-dependent:
- Confirmed source flaw: moderator data is obtained from ordinary UserData and
  the client uses it for gating; no trusted server permission check is present
  in the cited Unity checks/actions.
- Confirmed source flaw: V08 ReportPlayer trusts caller-supplied reporter identity;
  V08 ServerGrantCurrency lacks a role check.
- PlayFab documents client UpdateUserData as readable/writable by the client;
  ReadOnlyData is server-modifiable and client-readable. A title policy may
  restrict API access, but no dashboard access was performed. The Moderator key
  is ordinary UserData in source, not ReadOnlyData.
- Unknown: whether V08 or any equivalent CloudScript revision is deployed,
  whether these handlers can be called by a regular client in the live title,
  and whether an external server/admin allowlist protects them.

Recommended trusted permission design (preserve moderator features):
1. Store roles in server-only InternalData or an authoritative role store; use
   ReadOnlyData only if the client must display the role. Provision/revoke roles
   through a restricted admin tool, never client UpdateUserData.
2. For every sensitive action, authorize on the backend using authenticated
   `currentPlayerId` and server-owned role data. Never accept ReporterId, role,
   target permission, or authority from client arguments. Validate target,
   allowed action, reason, and scope; rate-limit and audit.
3. Expose a read-only role query for UI convenience, but backend checks remain
   mandatory. Keep current moderator menus/features while migrating; hide UI on
   denied response, and route kick/ban/grant actions through backend. A local
   UI check is usability only.
4. Migrate existing moderators from the existing trusted roster/records after
   verifying them; do not blindly promote all accounts whose writable key says
   TRUE. Handle revocation and stale cache/session refresh.

2. CURRENCY CALLS AND REWARD PATHS

PlayFab distinction:
- Unity `PlayFabClientAPI.AddUserVirtualCurrency` is a client API call made with
  the player session. It changes the server-stored balance; it is not merely a
  local display change. If enabled for this title, a modified client can request
  a caller-chosen grant. A local amount check/UI does not prove eligibility.
- `PlayFabServerAPI.AddUserVirtualCurrency` / CloudScript server API requires
  server credentials and is appropriate only inside trusted backend logic.
  V08 ServerGrantCurrency uses this privileged operation, but the handler itself
  still needs caller authorization and validation. A privileged operation does
  not make an exposed handler admin-only.
- Exact client API policy and live CloudScript exposure are dashboard/deployment
  questions; neither is verified here.

Unity grant paths located in local source (Assets-relative paths):
- `Scripts/Oculus_Login.cs`: `AddCurrency(int)` calls client
  `AddUserVirtualCurrency` with supplied amount and optimistically changes the
  local balance; `RemoveCurrency` calls client `SubtractUserVirtualCurrency`.
- `Scripts/Atm_Manager.cs`: `BuyProductCallback` grants `currencyToGive` after
  local Meta IAP success/SKU handling. Client callback is not independently
  server receipt validation in the inspected caller.
- `Scripts/ShopKeeper.cs`: `SelectOre` grants 1/2/3 currency; `PickItem` checks
  cached local balance then spends through `RemoveCurrency`.
- `Scripts/RedeemAfter24.cs`: grants 5 currency via `AddCurrency`.
- `Scripts/SpokesSigmaIAP.cs`: `GrantAll` grants configured/computed currency
  and issues client `PurchaseItem`; `OWNED_IAP` dedupe is written via client
  `UpdateUserData` (`AppendOwnedSku`).
- `Assets/BundleIAP.cs`: grants 1 through `Oculus_Login.AddCurrency`.
- Spend/purchase callers include `Scripts/BuyCosmetic.cs`, `BuyOnCollide.cs`,
  `BuyBundleOnCollide.cs`, and `ShopKeeper.cs`. These are relevant compatibility
  paths, though not all directly grant currency.
- Other writers: `Oculus_Login.CreateKeyIfNot` writes Moderator through client
  `UpdateUserData`; `SavePlayerNameToUserData` writes USERNAME. Do not treat
  client UserData as trusted for roles, receipt claims, or reward dedupe.

CloudScript/revision findings:
- V08 `ServerGrantCurrency` (515-540): amount/reason checks and cap only; no
  role check or idempotency. Draft uses privileged server grant on caller.
- V08 `OnPurchaseItem` (302-380): accepts `args.Price`; catalog lookup is TODO;
  no robust duplicate transaction protection. Not itself a Unity AddCurrency
  call, but economy-critical.
- V08 `completedLevel` (179-199): accepts client level/kill values and writes
  progression; no reward grant observed in this handler. It can still falsify
  progression and must not become a trusted reward trigger without validation.
- V08 `unlockHighSkillContent` (254-265) relies on a PlayStream event; rule/
  trigger configuration was not available, so execution path is unknown.
- V08 `UpdateUserInternalData`/server APIs are privileged, but no general
  client-facing UpdateUserData handler was found in V08. CloudScript does not
  secure client Unity calls that bypass it.

Severity assessment:
- High, source-confirmed pattern: currency grant amount and eligibility originate
  from client callers (`AddCurrency`, IAP/reward callers). The balance is stored
  server-side, but caller authentication is not equivalent to reward validation.
- High, conditional: arbitrary client AddUserVirtualCurrency succeeds in
  production. Verify client API policy and PlayFab title settings before calling
  it a confirmed live vulnerability. Disable client grants where the title
  configuration permits; regardless, migrate every legitimate reward first.
- High, conditional: V08 ServerGrantCurrency callable by ordinary players and/or
  deployed. Handler lacks authorization, so any permitted caller can grant up
  to 10,000 HC per call. Rate limiting alone is insufficient.
- Medium/High: client-controlled IAP callback and UserData dedupe can allow
  forged/replayed grants if there is no independent receipt validation and
  idempotent server transaction. Live Meta/PlayFab receipt configuration unknown.
- Medium: local optimistic balance can be desynchronized and local shop decisions
  bypassed; authoritative server balance still determines outcomes where a
  server-priced purchase API is used.

3. SECURE REWARD AND MODERATOR-GRANT FLOWS

Player-earned rewards:
- Unity sends a minimal claim/event, not amount or balance. Backend authenticates
  PlayFab session, derives player ID from verified context, validates reward
  eligibility from server-owned state, caps per event/window, and writes a
  durable idempotency record keyed by player + event/transaction ID before
  granting. Handle retries atomically or through a transaction/outbox pattern.
- For gameplay rewards that cannot be proven by PUN Cloud, treat client reports
  as claims subject to conservative limits/review, or use authoritative server
  simulation. Do not promise secure anti-cheat from CloudScript alone.
- For daily/24-hour rewards, enforce cooldown and one-time claim server-side using
  server timestamps and atomic/serialized updates. Client timers are display only.
- IAP: validate provider receipt server-side, map receipt/transaction ID to
  product and configured currency amount, enforce unique transaction processing,
  then grant once. Never accept `currencyToGive` from the client as authority.
- Shops: client requests product ID; backend resolves price from catalog and
  performs purchase/deduction + grant with idempotency. Return authoritative
  inventory/balance; preserve item IDs and existing UX.

Moderator grants:
- Backend derives moderator from server-only role store and caller from session;
  checks operator permission, target, currency code, positive bounded amount,
  reason, and per-operator limits. Require an idempotency/request ID, audit
  caller/target/amount/reason/time/result, and return authoritative balance.
- Grant endpoints must not be directly callable without role authorization.
  Keep title secret keys only in backend secret storage; never in Unity.
- Role changes and currency grants should be separate permissions; provide
  revocation, review, and audit views. Do not expose broad admin grant powers to
  ordinary moderators unless explicitly required.

4. DASHBOARD / DEPLOYMENT CHECKS (NOT PERFORMED)

- PlayFab Title Settings/API Policies: whether Client AddUserVirtualCurrency and
  UpdateUserData are allowed/restricted. Do not infer from source or SDK presence.
- Player Data settings: verify client write behavior for Moderator and legacy
  OWNED_IAP keys. Ordinary UserData is documented client-writable unless
  restricted; ReadOnlyData/InternalData are distinct server-controlled stores.
- Automation > CloudScript: deployed revision and access to each handler; any
  Azure Function auth/function secrets; title API policies and caller access.
- PlayStream rules/events: confirm whether unlockHighSkillContent or other reward
  functions are triggered, and whether event fields are server-authenticated.
- Economy/catalog: currency codes, prices, products, purchase validation, and
  whether existing clients can call direct grant APIs.
- Meta IAP: app/product configuration and server receipt validation path.
- None of these settings or deployed services were inspected or changed.

5. COMPATIBILITY AND REGRESSION TESTS

Stage only; preserve existing features and data:
1. Ordinary account attempts Moderator=TRUE via UpdateUserData; server role
   response/actions remain denied. Legitimate moderator retains menus/actions.
2. Spoof ReporterId/TargetId in ReportPlayer; authorization uses authenticated
   caller and rejects non-moderator; valid report still records correctly.
3. Call ServerGrantCurrency as ordinary account, forged moderator, and valid
   operator; only authorized operation succeeds, with audit and authoritative
   balance. Test over-limit, negative, malformed, and repeated requests.
4. Call Unity direct AddUserVirtualCurrency with arbitrary amount in staging;
   verify intended API policy blocks it after migration. Verify legitimate ore,
   daily reward, bundle, and IAP rewards still work exactly once.
5. Replay/retry identical reward, IAP receipt, moderator grant, and purchase
   request; each transaction has one grant/deduction. Simulate timeout after
   backend commit and retry.
6. Forge IAP callback/product/amount and reuse receipt; reject or grant only the
   configured product once. Validate legitimate Meta purchase and restoration.
7. Check ShopKeeper balance/spend, cosmetics, bundle purchases, and currency UI
   against server-returned balance; verify no negative or duplicate balance.
8. Verify existing moderators, player names, owned items, balances, IAP
   entitlements, and migration/revocation behavior remain intact.
9. Confirm logs omit title secrets, receipts, and sensitive tokens; inspect audit
   record completeness and rollback procedure.

6. OFFICIAL DOCUMENTATION CONSULTED

- PlayFab Client UpdateUserData is documented as client-readable and writable:
  https://learn.microsoft.com/en-us/rest/api/playfab/client/player-data-management/update-user-data
- PlayFab player data modes (Client, Read Only, Internal):
  https://learn.microsoft.com/en-us/gaming/playfab/player-progression/player-data/
- PlayFab Server UpdateUserReadOnlyData requires title secret and is server
  written/client read-only:
  https://learn.microsoft.com/en-us/rest/api/playfab/server/player-data-management/update-user-read-only-data
- PlayFab CloudScript/Azure Functions quickstart and function authorization:
  https://learn.microsoft.com/en-us/gaming/playfab/live-service-management/service-gateway/automation/cloudscript-af/quickstart
- PlayFab legacy virtual currency documentation (Economy v1):
  https://learn.microsoft.com/en-us/gaming/playfab/economy-monetization/economy/tutorials/currencies
- PlayFab Economy v2 currency quickstart:
  https://learn.microsoft.com/en-us/gaming/playfab/economy-monetization/economy-v2/tutorials/currencies

SCOPE NOTE

V08 and bundle findings are draft/source observations, not proof of live
deployment. Source review does not establish dashboard access, PlayFab API
policy, or production behavior. No implementation or production changes were
made. This focused report supplements V14; it does not replace it.

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