-
-
Notifications
You must be signed in to change notification settings - Fork 169
chore: change formatting from Prettier to ESLint Stylistic | v0.13 #1515
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Conversation
✅ Deploy Preview for oruga-documentation-preview ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
|
||
| const p = path.split("."); | ||
| if (p.length === 1) { | ||
| obj[p[0]] = value; |
Check warning
Code scanning / CodeQL
Prototype-polluting assignment Medium
library input
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 29 days ago
In general, to prevent prototype pollution in functions that write to object properties based on untrusted strings, you either (1) use a safe data structure (like Map or a prototype-less object from Object.create(null)), or (2) reject or transform dangerous keys such as __proto__, constructor, and prototype before using them to access or assign object properties.
Here, the least invasive and most compatible fix is to validate each path segment before using it as a property name. Specifically for setValueByPath, we can add a guard that stops if any path segment equals one of the dangerous names. That prevents writes such as obj["__proto__"] = ... or recursing into obj["__proto__"], avoiding pollution while leaving all normal behavior intact. Concretely: after splitting path into p, we check p[0]. If it equals "__proto__", "constructor", or "prototype", we immediately return without doing anything. We should perform this check in every call, including recursive calls, so we place it near where we derive field = p[0]. No extra imports or new dependencies are needed; we only add simple string comparisons in packages/oruga/src/utils/helpers.ts inside setValueByPath.
-
Copy modified lines R335-R339 -
Copy modified line R341 -
Copy modified lines R344-R346
| @@ -332,13 +332,18 @@ | ||
| if (typeof path !== "string") return; | ||
|
|
||
| const p = path.split("."); | ||
| const key = p[0]; | ||
| // Prevent prototype pollution through dangerous keys | ||
| if (key === "__proto__" || key === "constructor" || key === "prototype") { | ||
| return; | ||
| } | ||
| if (p.length === 1) { | ||
| obj[p[0]] = value; | ||
| obj[key] = value; | ||
| return; | ||
| } | ||
| const field = p[0]; | ||
| if (typeof obj[field] === "undefined") obj[field] = {}; | ||
| return setValueByPath(obj[field], p.slice(1).join("."), value); | ||
| const field = key; | ||
| if (typeof (obj as any)[field] === "undefined") (obj as any)[field] = {}; | ||
| return setValueByPath((obj as any)[field], p.slice(1).join(".") as K, value as any); | ||
| } | ||
|
|
||
| export function removeElement(el: Element): void { |
| return; | ||
| } | ||
| const field = p[0]; | ||
| if (typeof obj[field] === "undefined") obj[field] = {}; |
Check warning
Code scanning / CodeQL
Prototype-polluting assignment Medium
library input
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 29 days ago
In general, to fix prototype-polluting assignments in “set by path” helpers, you must ensure that untrusted keys cannot become special properties that affect the prototype chain (__proto__, constructor, prototype) or other built-in object internals. This can be done by either: (1) validating and rejecting such keys, (2) transforming keys so they cannot collide with built-ins (e.g., prefixing them), or (3) using data structures that are not affected by Object.prototype, like Map or objects created with Object.create(null).
For this specific function, the minimal change that preserves existing behavior is to validate each path segment and bail out early if any dangerous key is encountered. The main risk is in field = p[0]; if (typeof obj[field] === "undefined") obj[field] = {}; and in the recursive call setValueByPath(obj[field], p.slice(1).join("."), value);. We should add a small predicate isUnsafeKey (local helper) that returns true for "__proto__", "constructor", and "prototype", and call it before using a path segment as a key. If field is unsafe, we simply stop and do nothing; this avoids modifying the prototype while not changing normal behavior for legitimate keys. Additionally, we should ensure that the top-level path is a non-empty string and that all segments pass the same check as we recurse (the recursion will re-run the same logic, so checking field in each invocation is sufficient).
Concretely, in packages/oruga/src/utils/helpers.ts, inside setValueByPath, we will:
- Introduce a small local utility
const isUnsafeKey = (key: string): boolean => key === "__proto__" || key === "constructor" || key === "prototype";just above or inside the function. - After splitting the path (
const p = path.split(".");), ifp.length === 0or!p[0], return. - Before using
p[0]asfield, checkif (isUnsafeKey(field)) return;so we never assign to or traverse via these dangerous keys.
No new external dependencies are needed; this is pure TypeScript code.
-
Copy modified lines R335-R348 -
Copy modified line R350 -
Copy modified lines R353-R355
| @@ -332,13 +332,27 @@ | ||
| if (typeof path !== "string") return; | ||
|
|
||
| const p = path.split("."); | ||
| if (p.length === 0 || !p[0]) return; | ||
|
|
||
| const unsafeKey = "__proto__"; | ||
| const unsafeConstructor = "constructor"; | ||
| const unsafePrototype = "prototype"; | ||
| const field = p[0]; | ||
| if ( | ||
| field === unsafeKey || | ||
| field === unsafeConstructor || | ||
| field === unsafePrototype | ||
| ) { | ||
| return; | ||
| } | ||
|
|
||
| if (p.length === 1) { | ||
| obj[p[0]] = value; | ||
| (obj as any)[field] = value; | ||
| return; | ||
| } | ||
| const field = p[0]; | ||
| if (typeof obj[field] === "undefined") obj[field] = {}; | ||
| return setValueByPath(obj[field], p.slice(1).join("."), value); | ||
|
|
||
| if (typeof (obj as any)[field] === "undefined") (obj as any)[field] = {}; | ||
| return setValueByPath((obj as any)[field], p.slice(1).join("."), value as any); | ||
| } | ||
|
|
||
| export function removeElement(el: Element): void { |
b2ba879 to
c0e4ad9
Compare
Proposed Changes
Main changes are in: