From 51e3fe7027bba1bf15f245ab71ffebc8c8f57f1a Mon Sep 17 00:00:00 2001 From: NullSablex <244216261+NullSablex@users.noreply.github.com> Date: Sat, 20 Jun 2026 18:53:14 -0300 Subject: [PATCH] Potential fix for code scanning alert no. 23: Prototype-polluting function Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> --- src/core/config.ts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/core/config.ts b/src/core/config.ts index 4893e51..61efd0e 100644 --- a/src/core/config.ts +++ b/src/core/config.ts @@ -206,22 +206,30 @@ export class PawnProConfigManager { const current = readJsonFile(filePath) ?? {}; const parts = dotPath.split('.'); + if (parts.length === 0 || parts.some((p) => p.length === 0)) { + throw new Error('Invalid config key'); + } + + const isPollutionKey = (k: string): boolean => + k === '__proto__' || k === 'constructor' || k === 'prototype'; let cursor: Record = current; for (let i = 0; i < parts.length - 1; i++) { const key = parts[i]; // Validação no ponto de uso: a chave é checada imediatamente antes de // indexar o objeto, bloqueando __proto__/constructor/prototype. - if (!isSafeKey(key)) { + if (!isSafeKey(key) || isPollutionKey(key)) { throw new Error('Invalid config key: prototype pollution attempt'); } - if (!isPlainObject(cursor[key])) { + + const hasOwn = Object.prototype.hasOwnProperty.call(cursor, key); + if (!hasOwn || !isPlainObject(cursor[key])) { cursor[key] = {}; } cursor = cursor[key] as Record; } const leaf = parts[parts.length - 1]; - if (!isSafeKey(leaf)) { + if (!isSafeKey(leaf) || isPollutionKey(leaf)) { throw new Error('Invalid config key: prototype pollution attempt'); } cursor[leaf] = value;