Conversation
- Vanilla HTML/JS/CSS at domains/games/apps/1d4_web - Games browser (sortable table, motif badges, pagination) - Index form (POST api.1d4.net/index) and request status with auto-poll - ChessQL query view with example chips and syntax help - Cloudflare Worker + wrangler.toml, BUILD.bazel tar of static assets Fixes #1031
| view.id = `view-${route}`; | ||
| main.appendChild(view); | ||
| const fn = routes[route] || routes.games; | ||
| fn(view); |
Check failure
Code scanning / CodeQL
Unvalidated dynamic method call High
This autofix suggestion was applied.
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI about 2 months ago
In general, to fix unvalidated dynamic method calls, you should ensure that the user‑controlled key is checked against a whitelist (or at least verified as an own property) and that the resolved value is indeed a function before invoking it. This prevents dispatch to unexpected targets (including properties on Object.prototype) and avoids calling non‑function values.
For this specific case, the best low‑impact fix is to restrict route to a known set of route names and only then select the corresponding function, with a final fallback to routes.games. We can do this entirely within render() by introducing a small whitelist array and validating route against it. Then we safely compute fn as routes[safeRoute] || routes.games and call it. This preserves existing functionality (unknown hashes still render the games view) while making the dispatch explicit and safe.
Concretely, in domains/games/apps/1d4_web/src/app.js, modify lines 27–36 in render() so that:
- We define
const allowedRoutes = ['games', 'index', 'query']; - We compute
const safeRoute = allowedRoutes.includes(route) ? route : 'games'; - We use
safeRouteforsetActiveNav,view.id, and for selectingfn. - Optionally, add a
typeof fn === 'function'guard with a fallback toroutes.gamesto be extra defensive.
No new imports are needed; this uses only standard JavaScript.
| @@ -25,14 +25,19 @@ | ||
|
|
||
| function render() { | ||
| const route = getRoute(); | ||
| setActiveNav(route); | ||
| const allowedRoutes = ['games', 'index', 'query']; | ||
| const safeRoute = allowedRoutes.includes(route) ? route : 'games'; | ||
| setActiveNav(safeRoute); | ||
| const main = document.getElementById('app'); | ||
| main.innerHTML = ''; | ||
| const view = document.createElement('div'); | ||
| view.className = 'view active'; | ||
| view.id = `view-${route}`; | ||
| view.id = `view-${safeRoute}`; | ||
| main.appendChild(view); | ||
| const fn = routes[route] || routes.games; | ||
| let fn = routes[safeRoute] || routes.games; | ||
| if (typeof fn !== 'function') { | ||
| fn = routes.games; | ||
| } | ||
| fn(view); | ||
| } | ||
|
|
…od call Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Implements #1031.
domains/games/apps/1d4_webFixes #1031