diff --git a/cocoscreator_projects/YouleNexus/assets/framework/config/remote-config.ts b/cocoscreator_projects/YouleNexus/assets/framework/config/remote-config.ts index 0e7e18f..8e7e5b7 100644 --- a/cocoscreator_projects/YouleNexus/assets/framework/config/remote-config.ts +++ b/cocoscreator_projects/YouleNexus/assets/framework/config/remote-config.ts @@ -69,7 +69,7 @@ function normalizeWebSocketUrl(value: string): string { } try { const parsed = new URL(url); - if (!value || /\s/.test(value) || !parsed.hostname || parsed.username || parsed.password + if (!value || /\s/.test(value) || url.includes('#') || !parsed.hostname || parsed.username || parsed.password || (parsed.protocol !== 'ws:' && parsed.protocol !== 'wss:')) throw new Error('invalid'); } catch { throw new ConfigParseError('Invalid remote server: malformed WebSocket URL'); diff --git a/cocoscreator_projects/framework-tests/config/remote-config.test.ts b/cocoscreator_projects/framework-tests/config/remote-config.test.ts index 2e998f4..29e977e 100644 --- a/cocoscreator_projects/framework-tests/config/remote-config.test.ts +++ b/cocoscreator_projects/framework-tests/config/remote-config.test.ts @@ -66,3 +66,11 @@ test('missing or invalid chosen servers never fall back to obsolete envelope or assert.throws(() => api.parseUrlServers(view(raw)), api.ConfigParseError); } }); + +test('WebSocket fragments including an empty trailing marker fail at the config boundary', () => { + for (const address of ['ws://127.0.0.1:3088/#invalid', 'wss://example.test/#', 'example.test:3088#']) { + assert.throws(() => api.parseUrlServers(view({ player_server_tcp: address })), api.ConfigParseError); + } + assert.deepEqual(api.parseUrlServers(view({ player_server_tcp: 'wss://example.test/path%23part' })), + ['wss://example.test/path%23part']); +});