diff --git a/.changelogs/achievements-hash-validation.yml b/.changelogs/achievements-hash-validation.yml new file mode 100644 index 0000000000..6dec13ee31 --- /dev/null +++ b/.changelogs/achievements-hash-validation.yml @@ -0,0 +1,5 @@ +significance: patch +type: security +links: + - gocodebox/private-issues#61 +entry: Fixed a data sanitization issue related to achievement permalinks. diff --git a/assets/js/app/llms-achievements.js b/assets/js/app/llms-achievements.js index e70ea6f920..14b79f3979 100644 --- a/assets/js/app/llms-achievements.js +++ b/assets/js/app/llms-achievements.js @@ -4,7 +4,7 @@ * @package LifterLMS/Scripts * * @since 3.14.0 - * @version 4.5.1 + * @version [version] */ LLMS.Achievements = { @@ -15,7 +15,7 @@ LLMS.Achievements = { * @since 3.14.0 * @since 4.5.1 Fix conditional loading check. * - * @return void + * @return {void} */ init: function() { @@ -36,7 +36,7 @@ LLMS.Achievements = { * * @since 3.14.0 * - * @return void + * @return {void} */ bind: function() { @@ -70,7 +70,7 @@ LLMS.Achievements = { * @since 3.14.0 * * @param obj $el The jQuery selector for the modal card. - * @return void + * @return {void} */ create_modal: function( $el ) { @@ -111,16 +111,29 @@ LLMS.Achievements = { * On page load, opens a modal if the URL contains an achievement in the location hash * * @since 3.14.0 + * @since [version] Sanitize achievement IDs before using window.location.hash to trigger the modal open. * - * @return void + * @return {void} */ maybe_open: function() { - var hash = window.location.hash; - if ( hash && -1 !== hash.indexOf( 'achievement-' ) ) { - $( 'a[href="' + hash + '"]' ).first().trigger( 'click' ); + let hash = window.location.hash.split( '-' ); + if ( 2 !== hash.length ) { + return; } + hash[1] = parseInt( hash[1] ); + if ( '#achievement-' !== hash[0] || ! Number.isInteger( hash[1] ) ) { + return; + } + + const a = document.querySelector( `a[href="${ hash.join( '-' ) }"]` ) + if ( ! a ) { + return; + } + + a.click(); + } };