From 15c717072cdbe22d2d0396ec3548e6bf89798d17 Mon Sep 17 00:00:00 2001 From: Nick Pakhodnia Date: Thu, 21 May 2026 08:36:28 -0400 Subject: [PATCH 1/2] fix meta tag prototype pollution --- lib/plugins/system/meta/HTMLMetaHandler.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/plugins/system/meta/HTMLMetaHandler.js b/lib/plugins/system/meta/HTMLMetaHandler.js index fd467538b..e64f6fa1f 100644 --- a/lib/plugins/system/meta/HTMLMetaHandler.js +++ b/lib/plugins/system/meta/HTMLMetaHandler.js @@ -469,6 +469,12 @@ function merge(parentObj, props, value) { return; } + // Prototype pollution guard: never let attacker-controlled meta tag names + // (e.g. ) write into Object.prototype. + if (props.some(function(p) { return p === '__proto__' || p === 'constructor' || p === 'prototype'; })) { + return; + } + var currentNodeName = props[props.length - 1]; // Add 'url' to 'og:video'. And other same cases. From e208baa04ac265fd6167a867c7878477cf9bd7d4 Mon Sep 17 00:00:00 2001 From: Nick Pakhodnia Date: Thu, 21 May 2026 08:43:15 -0400 Subject: [PATCH 2/2] add guards to lowerCaseKeys --- lib/utils.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/utils.js b/lib/utils.js index fd6f36706..dd3d58741 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -1041,6 +1041,15 @@ export function unifyDate(date) { export function lowerCaseKeys(obj) { for (var k in obj) { + if (!Object.prototype.hasOwnProperty.call(obj, k)) { + // Skip inherited keys (e.g. from an already polluted prototype). + continue; + } + // Prototype pollution guard: never copy dangerous keys coming from + // attacker-controlled JSON (e.g. oembed `{"__proto__":{...}}`). + if (k === '__proto__' || k === 'constructor' || k === 'prototype') { + continue; + } var lowerCaseKey = k.toLowerCase(); if (lowerCaseKey != k) { obj[lowerCaseKey] = obj[k];