Skip to content

Conversation

@mlmoravek
Copy link
Member

@mlmoravek mlmoravek commented Jan 15, 2026

Proposed Changes

  • Change js/ts file formatting from Prettier to eslint with ESLint Stylistic plugin.
  • Only format md, mdx, json, html with prettier.
  • Lint all files with the new config.

Main changes are in:

  • eslint.config.mjs
  • prettier.config.mjs
  • package.json

@mlmoravek mlmoravek added the dependencies Pull requests that update a dependency file label Jan 15, 2026
@netlify
Copy link

netlify bot commented Jan 15, 2026

Deploy Preview for oruga-documentation-preview ready!

Name Link
🔨 Latest commit b4c169c
🔍 Latest deploy log https://app.netlify.com/projects/oruga-documentation-preview/deploys/69713bc27ab07f00083e6982
😎 Deploy Preview https://deploy-preview-1515--oruga-documentation-preview.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

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

This assignment may alter Object.prototype if a malicious '__proto__' string is injected from
library input
.

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.

Suggested changeset 1
packages/oruga/src/utils/helpers.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/packages/oruga/src/utils/helpers.ts b/packages/oruga/src/utils/helpers.ts
--- a/packages/oruga/src/utils/helpers.ts
+++ b/packages/oruga/src/utils/helpers.ts
@@ -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 {
EOF
@@ -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 {
Copilot is powered by AI and may make mistakes. Always verify output.
return;
}
const field = p[0];
if (typeof obj[field] === "undefined") obj[field] = {};

Check warning

Code scanning / CodeQL

Prototype-polluting assignment Medium

This assignment may alter Object.prototype if a malicious '__proto__' string is injected from
library input
.

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(".");), if p.length === 0 or !p[0], return.
  • Before using p[0] as field, check if (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.
Suggested changeset 1
packages/oruga/src/utils/helpers.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/packages/oruga/src/utils/helpers.ts b/packages/oruga/src/utils/helpers.ts
--- a/packages/oruga/src/utils/helpers.ts
+++ b/packages/oruga/src/utils/helpers.ts
@@ -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 {
EOF
@@ -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 {
Copilot is powered by AI and may make mistakes. Always verify output.
@mlmoravek mlmoravek changed the title chore: change formatting from Prettier to ESLint Stylistic chore: change formatting from Prettier to ESLint Stylistic | v0.13 Jan 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant