diff --git a/public/scripts/action-loader-slashcommands.js b/public/scripts/action-loader-slashcommands.js index ee0666778..278752c9a 100644 --- a/public/scripts/action-loader-slashcommands.js +++ b/public/scripts/action-loader-slashcommands.js @@ -7,6 +7,7 @@ import { commonEnumProviders, enumIcons } from './slash-commands/SlashCommandCom import { SlashCommandEnumValue, enumTypes } from './slash-commands/SlashCommandEnumValue.js'; import { SlashCommandParser } from './slash-commands/SlashCommandParser.js'; import { isFalseBoolean } from './utils.js'; +import { DOMPurify } from '../lib.js'; /** * Registers slash commands for the action loader module. @@ -275,8 +276,8 @@ export function registerActionLoaderSlashCommands() { slug: typeof args.slug === 'string' ? String(args.slug) : 'slash-show', blocking, toastMode, - message, - title, + message: DOMPurify.sanitize(message), + title: DOMPurify.sanitize(title), stopTooltip, onStop: createClosureHandler(args.onStop), onHide: createClosureHandler(args.onHide, { argName: 'onHide' }), diff --git a/public/scripts/extensions/regex/index.js b/public/scripts/extensions/regex/index.js index 33e6e2bc0..ca51b606c 100644 --- a/public/scripts/extensions/regex/index.js +++ b/public/scripts/extensions/regex/index.js @@ -1639,7 +1639,7 @@ async function checkCharEmbeddedRegexScripts() { function notifyReloadCurrentChat(presetName) { toastr.info( t`Reload the chat for regex to take effect` + '
' + t`Click here to reload immediately` + '', - t`Preset '${presetName}' contains enabled regex scripts`, + t`Preset '${escapeHtml(presetName)}' contains enabled regex scripts`, { timeOut: 5000, escapeHtml: false, diff --git a/public/scripts/personas.js b/public/scripts/personas.js index ca4702c96..1b70e0f74 100644 --- a/public/scripts/personas.js +++ b/public/scripts/personas.js @@ -49,6 +49,7 @@ import { uuidv4, resolveAvatarData, findPersona, + escapeHtml, } from './utils.js'; import { debounce_timeout } from './constants.js'; import { FILTER_TYPES, FilterHelper } from './filters.js'; @@ -946,8 +947,9 @@ async function selectCurrentPersona({ toastPersonaNameChange = true } = {}) { const temporary = getPersonaTemporaryLockInfo(); if (temporary.isTemporary) { toastr.info(t`This persona is only temporarily chosen. Click for more info.`, t`Temporary Persona`, { - preventDuplicates: true, onclick: () => { - toastr.info(temporary.info.replaceAll('\n', '
'), t`Temporary Persona`, { escapeHtml: false }); + preventDuplicates: true, + onclick: () => { + toastr.info(escapeHtml(temporary.info).replaceAll('\n', '
'), t`Temporary Persona`, { escapeHtml: false }); }, }); } @@ -1116,9 +1118,9 @@ async function lockPersona(type = 'chat') { if (power_user.persona_show_notifications) { let additional = ''; if (unlinkedCharacters.length) - additional += `

${t`Unlinked existing persona${unlinkedCharacters.length > 1 ? 's' : ''}: ${unlinkedCharacters.join(', ')}`}`; + additional += `

${t`Unlinked existing persona${unlinkedCharacters.length > 1 ? 's' : ''}: ${unlinkedCharacters.map(escapeHtml).join(', ')}`}`; if (additional || !isPersonaPanelOpen()) { - toastr.success(t`User persona ${name1} is locked to character ${name2}${additional}`, t`Persona Locked`, { escapeHtml: false }); + toastr.success(t`User persona ${escapeHtml(name1)} is locked to character ${escapeHtml(name2)}${additional}`, t`Persona Locked`, { escapeHtml: false }); } } } diff --git a/public/scripts/tags.js b/public/scripts/tags.js index 20086bccd..e2b144f00 100644 --- a/public/scripts/tags.js +++ b/public/scripts/tags.js @@ -16,7 +16,7 @@ import { import { FILTER_TYPES, FILTER_STATES, DEFAULT_FILTER_STATE, isFilterState, FilterHelper } from './filters.js'; import { groupCandidatesFilter, groupMembersFilter, groups, selected_group } from './group-chats.js'; -import { download, onlyUnique, parseJsonFile, uuidv4, getSortableDelay, flashHighlight, equalsIgnoreCaseAndAccents, includesIgnoreCaseAndAccents, removeFromArray, getFreeName, debounce, findChar } from './utils.js'; +import { download, onlyUnique, parseJsonFile, uuidv4, getSortableDelay, flashHighlight, equalsIgnoreCaseAndAccents, includesIgnoreCaseAndAccents, removeFromArray, getFreeName, debounce, findChar, escapeHtml } from './utils.js'; import { power_user } from './power-user.js'; import { SlashCommandParser } from './slash-commands/SlashCommandParser.js'; import { SlashCommand } from './slash-commands/SlashCommand.js'; @@ -977,11 +977,12 @@ async function importTags(character, { importSetting = null } = {}) { const tagsToImport = tagNamesToImport.map(tag => getTag(tag, { createNew: true })); const added = addTagsToEntity(tagsToImport, character.avatar); + const tagNames = tagsToImport.map(x => escapeHtml(x.name)).join(', '); if (added) { - toastr.success(t`Imported tags:` + `
${tagsToImport.map(x => x.name).join(', ')}`, t`Importing Tags`, { escapeHtml: false }); + toastr.success(t`Imported tags:` + `
${tagNames}`, t`Importing Tags`, { escapeHtml: false }); } else { - toastr.error(t`Couldn't import tags:` + `
${tagsToImport.map(x => x.name).join(', ')}`, t`Importing Tags`, { escapeHtml: false }); + toastr.error(t`Couldn't import tags:` + `
${tagNames}`, t`Importing Tags`, { escapeHtml: false }); } return added; @@ -1124,7 +1125,7 @@ function getTag(tagName, { createNew = false } = {}) { function createNewTag(tagName) { const existing = getTag(tagName); if (existing) { - toastr.warning(`Cannot create new tag. A tag with the name already exists:
${existing.name}`, 'Creating Tag', { escapeHtml: false }); + toastr.warning(`Cannot create new tag. A tag with the name already exists:
${escapeHtml(existing.name)}`, 'Creating Tag', { escapeHtml: false }); return existing; } diff --git a/public/scripts/utils.js b/public/scripts/utils.js index f58e28622..bfb3644a4 100644 --- a/public/scripts/utils.js +++ b/public/scripts/utils.js @@ -2487,13 +2487,13 @@ export async function checkOverwriteExistingData(type, existingNames, name, { in return true; } - const overwrite = interactive && await Popup.show.confirm(`${type} ${actionName}`, `

A ${type.toLowerCase()} with the same name already exists:
${existing}

Do you want to overwrite it?`); + const overwrite = interactive && await Popup.show.confirm(`${type} ${actionName}`, `

A ${type.toLowerCase()} with the same name already exists:
${escapeHtml(existing)}

Do you want to overwrite it?`); if (!overwrite) { - toastr.warning(`${type} ${actionName.toLowerCase()} cancelled. A ${type.toLowerCase()} with the same name already exists:
${existing}`, `${type} ${actionName}`, { escapeHtml: false }); + toastr.warning(`${type} ${actionName.toLowerCase()} cancelled. A ${type.toLowerCase()} with the same name already exists:
${escapeHtml(existing)}`, `${type} ${actionName}`, { escapeHtml: false }); return false; } - toastr.info(`Overwriting Existing ${type}:
${existing}`, `${type} ${actionName}`, { escapeHtml: false }); + toastr.info(`Overwriting Existing ${type}:
${escapeHtml(existing)}`, `${type} ${actionName}`, { escapeHtml: false }); // If there is an action to delete the existing data, do it, as the name might be slightly different so file name would not be the same if (deleteAction) {