Skip to content

Conversation

@medmen
Copy link
Owner

@medmen medmen commented Jan 25, 2026

No description provided.

@medmen medmen self-assigned this Jan 25, 2026
@medmen medmen added the enhancement New feature or request label Jan 25, 2026
var last = lastRendered.length ? lastRendered[lastRendered.length - 1] : '';
if(redirectUrl && typeof last === 'string' && last.indexOf('[END OK]') === 0 && !redirected){
redirected = true;
setTimeout(function(){ window.location.assign(redirectUrl); }, 500);

Check failure

Code scanning / CodeQL

DOM text reinterpreted as HTML High

DOM text
is reinterpreted as HTML without escaping meta-characters.

Copilot Autofix

AI about 5 hours ago

In general, redirects or navigations should not use untrusted data directly. Either avoid using user-controlled values at all, or strictly validate and constrain them before use. For URLs, that typically means: (1) disallowing dangerous schemes (javascript:, data:, etc.), (2) preferably limiting to same-origin relative paths or a known-safe allowlist, and (3) falling back to a safe default if validation fails.

The best fix here without changing intended functionality is to validate and normalize redirectUrl before it is used. We can restrict data-redirect to same-origin URLs or relative paths only. To do so inside the provided snippet, we can (a) keep the raw string from getAttribute, (b) when we are about to redirect, attempt to construct a URL object with window.location.origin as base, (c) ensure that the resulting URL’s origin matches window.location.origin, and (d) only call window.location.assign if that check passes. Otherwise, we skip redirecting (or could choose a safe fallback, but we’ll preserve current behavior as much as possible by just not redirecting when the value is unsafe).

Concretely, in assets/protocol-status.js, around line 61–64, replace the direct use of window.location.assign(redirectUrl); with logic that (1) checks redirectUrl is a non-empty string, (2) constructs new URL(redirectUrl, window.location.origin), (3) compares safeUrl.origin to window.location.origin, and (4) calls window.location.assign(safeUrl.toString()) only if they match. This does not require any new imports and keeps the external behavior (redirecting to the configured path) while safely rejecting malicious schemes or cross-origin redirects.

Suggested changeset 1
assets/protocol-status.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/assets/protocol-status.js b/assets/protocol-status.js
--- a/assets/protocol-status.js
+++ b/assets/protocol-status.js
@@ -59,8 +59,15 @@
             try{
               var last = lastRendered.length ? lastRendered[lastRendered.length - 1] : '';
               if(redirectUrl && typeof last === 'string' && last.indexOf('[END OK]') === 0 && !redirected){
-                redirected = true;
-                setTimeout(function(){ window.location.assign(redirectUrl); }, 500);
+                try {
+                  var resolvedUrl = new URL(redirectUrl, window.location.origin);
+                  if (resolvedUrl.origin === window.location.origin) {
+                    redirected = true;
+                    setTimeout(function(){ window.location.assign(resolvedUrl.toString()); }, 500);
+                  }
+                } catch (e2) {
+                  // Ignore invalid redirectUrl values
+                }
               }
             } catch(e) {}
           }
EOF
@@ -59,8 +59,15 @@
try{
var last = lastRendered.length ? lastRendered[lastRendered.length - 1] : '';
if(redirectUrl && typeof last === 'string' && last.indexOf('[END OK]') === 0 && !redirected){
redirected = true;
setTimeout(function(){ window.location.assign(redirectUrl); }, 500);
try {
var resolvedUrl = new URL(redirectUrl, window.location.origin);
if (resolvedUrl.origin === window.location.origin) {
redirected = true;
setTimeout(function(){ window.location.assign(resolvedUrl.toString()); }, 500);
}
} catch (e2) {
// Ignore invalid redirectUrl values
}
}
} catch(e) {}
}
Copilot is powered by AI and may make mistakes. Always verify output.
@@ -0,0 +1 @@
(()=>{var e={495:function(e){var t;t=function(){var e=JSON.parse('{"$":"dollar","%":"percent","&":"and","<":"less",">":"greater","|":"or","¢":"cent","£":"pound","¤":"currency","¥":"yen","©":"(c)","ª":"a","®":"(r)","º":"o","À":"A","Á":"A","Â":"A","Ã":"A","Ä":"A","Å":"A","Æ":"AE","Ç":"C","È":"E","É":"E","Ê":"E","Ë":"E","Ì":"I","Í":"I","Î":"I","Ï":"I","Ð":"D","Ñ":"N","Ò":"O","Ó":"O","Ô":"O","Õ":"O","Ö":"O","Ø":"O","Ù":"U","Ú":"U","Û":"U","Ü":"U","Ý":"Y","Þ":"TH","ß":"ss","à":"a","á":"a","â":"a","ã":"a","ä":"a","å":"a","æ":"ae","ç":"c","è":"e","é":"e","ê":"e","ë":"e","ì":"i","í":"i","î":"i","ï":"i","ð":"d","ñ":"n","ò":"o","ó":"o","ô":"o","õ":"o","ö":"o","ø":"o","ù":"u","ú":"u","û":"u","ü":"u","ý":"y","þ":"th","ÿ":"y","Ā":"A","ā":"a","Ă":"A","ă":"a","Ą":"A","ą":"a","Ć":"C","ć":"c","Č":"C","č":"c","Ď":"D","ď":"d","Đ":"DJ","đ":"dj","Ē":"E","ē":"e","Ė":"E","ė":"e","Ę":"e","ę":"e","Ě":"E","ě":"e","Ğ":"G","ğ":"g","Ģ":"G","ģ":"g","Ĩ":"I","ĩ":"i","Ī":"i","ī":"i","Į":"I","į":"i","İ":"I","ı":"i","Ķ":"k","ķ":"k","Ļ":"L","ļ":"l","Ľ":"L","ľ":"l","Ł":"L","ł":"l","Ń":"N","ń":"n","Ņ":"N","ņ":"n","Ň":"N","ň":"n","Ō":"O","ō":"o","Ő":"O","ő":"o","Œ":"OE","œ":"oe","Ŕ":"R","ŕ":"r","Ř":"R","ř":"r","Ś":"S","ś":"s","Ş":"S","ş":"s","Š":"S","š":"s","Ţ":"T","ţ":"t","Ť":"T","ť":"t","Ũ":"U","ũ":"u","Ū":"u","ū":"u","Ů":"U","ů":"u","Ű":"U","ű":"u","Ų":"U","ų":"u","Ŵ":"W","ŵ":"w","Ŷ":"Y","ŷ":"y","Ÿ":"Y","Ź":"Z","ź":"z","Ż":"Z","ż":"z","Ž":"Z","ž":"z","Ə":"E","ƒ":"f","Ơ":"O","ơ":"o","Ư":"U","ư":"u","Lj":"LJ","lj":"lj","Nj":"NJ","nj":"nj","Ș":"S","ș":"s","Ț":"T","ț":"t","ə":"e","˚":"o","Ά":"A","Έ":"E","Ή":"H","Ί":"I","Ό":"O","Ύ":"Y","Ώ":"W","ΐ":"i","Α":"A","Β":"B","Γ":"G","Δ":"D","Ε":"E","Ζ":"Z","Η":"H","Θ":"8","Ι":"I","Κ":"K","Λ":"L","Μ":"M","Ν":"N","Ξ":"3","Ο":"O","Π":"P","Ρ":"R","Σ":"S","Τ":"T","Υ":"Y","Φ":"F","Χ":"X","Ψ":"PS","Ω":"W","Ϊ":"I","Ϋ":"Y","ά":"a","έ":"e","ή":"h","ί":"i","ΰ":"y","α":"a","β":"b","γ":"g","δ":"d","ε":"e","ζ":"z","η":"h","θ":"8","ι":"i","κ":"k","λ":"l","μ":"m","ν":"n","ξ":"3","ο":"o","π":"p","ρ":"r","ς":"s","σ":"s","τ":"t","υ":"y","φ":"f","χ":"x","ψ":"ps","ω":"w","ϊ":"i","ϋ":"y","ό":"o","ύ":"y","ώ":"w","Ё":"Yo","Ђ":"DJ","Є":"Ye","І":"I","Ї":"Yi","Ј":"J","Љ":"LJ","Њ":"NJ","Ћ":"C","Џ":"DZ","А":"A","Б":"B","В":"V","Г":"G","Д":"D","Е":"E","Ж":"Zh","З":"Z","И":"I","Й":"J","К":"K","Л":"L","М":"M","Н":"N","О":"O","П":"P","Р":"R","С":"S","Т":"T","У":"U","Ф":"F","Х":"H","Ц":"C","Ч":"Ch","Ш":"Sh","Щ":"Sh","Ъ":"U","Ы":"Y","Ь":"","Э":"E","Ю":"Yu","Я":"Ya","а":"a","б":"b","в":"v","г":"g","д":"d","е":"e","ж":"zh","з":"z","и":"i","й":"j","к":"k","л":"l","м":"m","н":"n","о":"o","п":"p","р":"r","с":"s","т":"t","у":"u","ф":"f","х":"h","ц":"c","ч":"ch","ш":"sh","щ":"sh","ъ":"u","ы":"y","ь":"","э":"e","ю":"yu","я":"ya","ё":"yo","ђ":"dj","є":"ye","і":"i","ї":"yi","ј":"j","љ":"lj","њ":"nj","ћ":"c","ѝ":"u","џ":"dz","Ґ":"G","ґ":"g","Ғ":"GH","ғ":"gh","Қ":"KH","қ":"kh","Ң":"NG","ң":"ng","Ү":"UE","ү":"ue","Ұ":"U","ұ":"u","Һ":"H","һ":"h","Ә":"AE","ә":"ae","Ө":"OE","ө":"oe","Ա":"A","Բ":"B","Գ":"G","Դ":"D","Ե":"E","Զ":"Z","Է":"E\'","Ը":"Y\'","Թ":"T\'","Ժ":"JH","Ի":"I","Լ":"L","Խ":"X","Ծ":"C\'","Կ":"K","Հ":"H","Ձ":"D\'","Ղ":"GH","Ճ":"TW","Մ":"M","Յ":"Y","Ն":"N","Շ":"SH","Չ":"CH","Պ":"P","Ջ":"J","Ռ":"R\'","Ս":"S","Վ":"V","Տ":"T","Ր":"R","Ց":"C","Փ":"P\'","Ք":"Q\'","Օ":"O\'\'","Ֆ":"F","և":"EV","ء":"a","آ":"aa","أ":"a","ؤ":"u","إ":"i","ئ":"e","ا":"a","ب":"b","ة":"h","ت":"t","ث":"th","ج":"j","ح":"h","خ":"kh","د":"d","ذ":"th","ر":"r","ز":"z","س":"s","ش":"sh","ص":"s","ض":"dh","ط":"t","ظ":"z","ع":"a","غ":"gh","ف":"f","ق":"q","ك":"k","ل":"l","م":"m","ن":"n","ه":"h","و":"w","ى":"a","ي":"y","ً":"an","ٌ":"on","ٍ":"en","َ":"a","ُ":"u","ِ":"e","ْ":"","٠":"0","١":"1","٢":"2","٣":"3","٤":"4","٥":"5","٦":"6","٧":"7","٨":"8","٩":"9","پ":"p","چ":"ch","ژ":"zh","ک":"k","گ":"g","ی":"y","۰":"0","۱":"1","۲":"2","۳":"3","۴":"4","۵":"5","۶":"6","۷":"7","۸":"8","۹":"9","฿":"baht","ა":"a","ბ":"b","გ":"g","დ":"d","ე":"e","ვ":"v","ზ":"z","თ":"t","ი":"i","კ":"k","ლ":"l","მ":"m","ნ":"n","ო":"o","პ":"p","ჟ":"zh","რ":"r","ს":"s","ტ":"t","უ":"u","ფ":"f","ქ":"k","ღ":"gh","ყ":"q","შ":"sh","ჩ":"ch","ც":"ts","ძ":"dz","წ":"ts","ჭ":"ch","ხ":"kh","ჯ":"j","ჰ":"h","Ṣ":"S","ṣ":"s","Ẁ":"W","ẁ":"w","Ẃ":"W","ẃ":"w","Ẅ":"W","ẅ":"w","ẞ":"SS","Ạ":"A","ạ":"a","Ả":"A","ả":"a","Ấ":"A","ấ":"a","Ầ":"A","ầ":"a","Ẩ":"A","ẩ":"a","Ẫ":"A","ẫ":"a","Ậ":"A","ậ":"a","Ắ":"A","ắ":"a","Ằ":"A","ằ":"a","Ẳ":"A","ẳ":"a","Ẵ":"A","ẵ":"a","Ặ":"A","ặ":"a","Ẹ":"E","ẹ":"e","Ẻ":"E","ẻ":"e","Ẽ":"E","ẽ":"e","Ế":"E","ế":"e","Ề":"E","ề":"e","Ể":"E","ể":"e","Ễ":"E","ễ":"e","Ệ":"E","ệ":"e","Ỉ":"I","ỉ":"i","Ị":"I","ị":"i","Ọ":"O","ọ":"o","Ỏ":"O","ỏ":"o","Ố":"O","ố":"o","Ồ":"O","ồ":"o","Ổ":"O","ổ":"o","Ỗ":"O","ỗ":"o","Ộ":"O","ộ":"o","Ớ":"O","ớ":"o","Ờ":"O","ờ":"o","Ở":"O","ở":"o","Ỡ":"O","ỡ":"o","Ợ":"O","ợ":"o","Ụ":"U","ụ":"u","Ủ":"U","ủ":"u","Ứ":"U","ứ":"u","Ừ":"U","ừ":"u","Ử":"U","ử":"u","Ữ":"U","ữ":"u","Ự":"U","ự":"u","Ỳ":"Y","ỳ":"y","Ỵ":"Y","ỵ":"y","Ỷ":"Y","ỷ":"y","Ỹ":"Y","ỹ":"y","–":"-","‘":"\'","’":"\'","“":"\\"","”":"\\"","„":"\\"","†":"+","•":"*","…":"...","₠":"ecu","₢":"cruzeiro","₣":"french franc","₤":"lira","₥":"mill","₦":"naira","₧":"peseta","₨":"rupee","₩":"won","₪":"new shequel","₫":"dong","€":"euro","₭":"kip","₮":"tugrik","₯":"drachma","₰":"penny","₱":"peso","₲":"guarani","₳":"austral","₴":"hryvnia","₵":"cedi","₸":"kazakhstani tenge","₹":"indian rupee","₺":"turkish lira","₽":"russian ruble","₿":"bitcoin","℠":"sm","™":"tm","∂":"d","∆":"delta","∑":"sum","∞":"infinity","♥":"love","元":"yuan","円":"yen","﷼":"rial","ﻵ":"laa","ﻷ":"laa","ﻹ":"lai","ﻻ":"la"}'),t=JSON.parse('{"bg":{"Й":"Y","Ц":"Ts","Щ":"Sht","Ъ":"A","Ь":"Y","й":"y","ц":"ts","щ":"sht","ъ":"a","ь":"y"},"de":{"Ä":"AE","ä":"ae","Ö":"OE","ö":"oe","Ü":"UE","ü":"ue","ß":"ss","%":"prozent","&":"und","|":"oder","∑":"summe","∞":"unendlich","♥":"liebe"},"es":{"%":"por ciento","&":"y","<":"menor que",">":"mayor que","|":"o","¢":"centavos","£":"libras","¤":"moneda","₣":"francos","∑":"suma","∞":"infinito","♥":"amor"},"fr":{"%":"pourcent","&":"et","<":"plus petit",">":"plus grand","|":"ou","¢":"centime","£":"livre","¤":"devise","₣":"franc","∑":"somme","∞":"infini","♥":"amour"},"pt":{"%":"porcento","&":"e","<":"menor",">":"maior","|":"ou","¢":"centavo","∑":"soma","£":"libra","∞":"infinito","♥":"amor"},"uk":{"И":"Y","и":"y","Й":"Y","й":"y","Ц":"Ts","ц":"ts","Х":"Kh","х":"kh","Щ":"Shch","щ":"shch","Г":"H","г":"h"},"vi":{"Đ":"D","đ":"d"},"da":{"Ø":"OE","ø":"oe","Å":"AA","å":"aa","%":"procent","&":"og","|":"eller","$":"dollar","<":"mindre end",">":"større end"},"nb":{"&":"og","Å":"AA","Æ":"AE","Ø":"OE","å":"aa","æ":"ae","ø":"oe"},"it":{"&":"e"},"nl":{"&":"en"},"sv":{"&":"och","Å":"AA","Ä":"AE","Ö":"OE","å":"aa","ä":"ae","ö":"oe"}}');function n(n,r){if("string"!=typeof n)throw new Error("slugify: string argument expected");var o=t[(r="string"==typeof r?{replacement:r}:r||{}).locale]||{},a=void 0===r.replacement?"-":r.replacement,i=void 0===r.trim||r.trim,u=n.normalize().split("").reduce((function(t,n){var i=o[n];return void 0===i&&(i=e[n]),void 0===i&&(i=n),i===a&&(i=" "),t+i.replace(r.remove||/[^\w\s$*_+~.()'"!\-:@]+/g,"")}),"");return r.strict&&(u=u.replace(/[^A-Za-z0-9\s]/g,"")),i&&(u=u.trim()),u=u.replace(/\s+/g,a),r.lower&&(u=u.toLowerCase()),u}return n.extend=function(t){Object.assign(e,t)},n},e.exports=t(),e.exports.default=t()}},t={};function n(e){return n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},n(e)}function r(e,t){var n="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(!n){if(Array.isArray(e)||(n=function(e,t){if(e){if("string"==typeof e)return o(e,t);var n={}.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?o(e,t):void 0}}(e))||t&&e&&"number"==typeof e.length){n&&(e=n);var r=0,a=function(){};return{s:a,n:function(){return r>=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(e){throw e},f:a}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,u=!0,l=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return u=e.done,e},e:function(e){l=!0,i=e},f:function(){try{u||null==n.return||n.return()}finally{if(l)throw i}}}}function o(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}function a(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,i(r.key),r)}}function i(e){var t=function(e,t){if("object"!=n(e)||!e)return e;var r=e[Symbol.toPrimitive];if(void 0!==r){var o=r.call(e,t||"default");if("object"!=n(o))return o;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string");return"symbol"==n(t)?t:t+""}var u=function n(r){var o=t[r];if(void 0!==o)return o.exports;var a=t[r]={exports:{}};return e[r].call(a.exports,a,a.exports,n),a.exports}(495);u.extend({$:"","%":"","&":"","<":"",">":"","|":"","¢":"","£":"","¤":"","¥":"","₠":"","₢":"","₣":"","₤":"","₥":"","₦":"","₧":"","₨":"","₩":"","₪":"","₫":"","€":"","₭":"","₮":"","₯":"","₰":"","₱":"","₲":"","₳":"","₴":"","₵":"","₸":"","₹":"","₽":"","₿":"","∂":"","∆":"","∑":"","∞":"","♥":"",元:"",円:"","﷼":""});var l=function(){"use strict";return e=function e(t){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.field=t,this.setTargetElement(),this.locked=!0,this.field.setAttribute("readonly","readonly"),""===this.field.value?(this.currentSlug="",this.updateValue(),this.listenTarget()):this.currentSlug=this.field.value,this.appendLockButton()},(t=[{key:"setTargetElement",value:function(){var e=JSON.parse(this.field.dataset.target);this.targets=[];var t,n=r(e);try{for(n.s();!(t=n.n()).done;){var o=t.value,a=document.getElementById(o);if(null===a)throw'Wrong target specified for slug widget ("'.concat(o,'").');this.targets.push(a)}}catch(e){n.e(e)}finally{n.f()}}},{key:"appendLockButton",value:function(){var e=this;this.lockButton=this.field.parentNode.querySelector("button"),this.lockButton.addEventListener("click",(function(){if(e.locked){var t=e.field.dataset.confirmText||null;if(null===t)e.unlock();else{var n=decodeURIComponent(JSON.parse('"'.concat(t.replace(/\"/g,'\\"'),'"')));!0===confirm(n)&&e.unlock()}}else e.lock()}))}},{key:"unlock",value:function(){this.locked=!1,this.lockButton.innerHTML=this.lockButton.getAttribute("data-icon-unlocked"),this.field.removeAttribute("readonly")}},{key:"lock",value:function(){this.locked=!0,this.lockButton.innerHTML=this.lockButton.getAttribute("data-icon-locked"),""!==this.currentSlug?this.field.value=this.currentSlug:this.updateValue(),this.field.setAttribute("readonly","readonly")}},{key:"updateValue",value:function(){this.field.value=u(this.targets.map((function(e){return e.value})).join("-"),{remove:/[^A-Za-z0-9\s-]/g,lower:!0,strict:!0})}},{key:"listenTarget",value:function(){var e,t=this,n=r(this.targets);try{for(n.s();!(e=n.n()).done;)e.value.addEventListener("input",(function(){"readonly"===t.field.getAttribute("readonly")&&t.updateValue()}))}catch(e){n.e(e)}finally{n.f()}}}])&&a(e.prototype,t),n&&a(e,n),Object.defineProperty(e,"prototype",{writable:!1}),e;var e,t,n}();document.addEventListener("DOMContentLoaded",(function(){document.querySelectorAll("[data-ea-slug-field]").forEach((function(e){new l(e)}))})),document.addEventListener("ea.collection.item-added",(function(e){e.detail.newElement.querySelectorAll("[data-ea-slug-field]").forEach((function(e){new l(e)}))}))})(); No newline at end of file

Check failure

Code scanning / CodeQL

Incomplete string escaping or encoding High

This does not escape backslash characters in the input.

Copilot Autofix

AI about 5 hours ago

Copilot could not generate an autofix suggestion

Copilot could not generate an autofix suggestion for this alert. Try pushing a new commit or if the problem persists contact support.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants