CVE-2024-35236: Insufficient Information (NVD-CWE-noinfo)
value: Audiobookshelf is a self-hosted audiobook and podcast server. Prior to version 2.10.0, opening an ebook with malicious scripts inside leads to code execution inside the browsing context. Attacking a user with high privileges (upload, creation of libraries) can lead to remote code execution (RCE) in the worst case. This was tested on version 2.9.0 on Windows, but an arbitrary file write is powerful enough as is and should easily lead to RCE on Linux, too. Version 2.10.0 contains a patch for the vulnerability.
CWE description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
Published: 2024-05-27T17:15Z
Repository: https://github.com/advplyr/audiobookshelf
Language: JSON
Files changed: client/components/modals/libraries/LibrarySettings.vue, client/components/readers/EpubReader.vue, client/store/libraries.js, client/strings/bg.json, client/strings/bn.json, client/strings/cs.json, client/strings/da.json, client/strings/de.json, client/strings/en-us.json, client/strings/es.json, client/strings/et.json, client/strings/fr.json, client/strings/gu.json, client/strings/he.json, client/strings/hi.json, client/strings/hr.json, client/strings/hu.json, client/strings/it.json, client/strings/lt.json, client/strings/nl.json, client/strings/no.json, client/strings/pl.json, client/strings/pt-br.json, client/strings/ru.json, client/strings/sv.json, client/strings/uk.json, client/strings/vi-vn.json, client/strings/zh-cn.json, client/strings/zh-tw.json, server/objects/settings/LibrarySettings.js
Commit date: 2024-05-26 16:01:08 -0500
Commit message: Update:Disable epubs from running scripts by default, add library setting to enable it GHSA-7j99-76cj-q9pg

Diff: diff --git a/client/components/modals/libraries/LibrarySettings.vue b/client/components/modals/libraries/LibrarySettings.vue
index 4183c4fe4..3808ed07b 100644
--- a/client/components/modals/libraries/LibrarySettings.vue
+++ b/client/components/modals/libraries/LibrarySettings.vue
@@ -58,10 +58,21 @@
             <span class="material-icons icon-text text-sm">info_outlined</span>
           </p>
         </ui-tooltip>
       </div>
     </div>
+    <div v-if="isBookLibrary" class="py-3">
+      <div class="flex items-center">
+        <ui-toggle-switch v-model="epubsAllowScriptedContent" @input="formUpdated" />
+        <ui-tooltip :text="$strings.LabelSettingsEpubsAllowScriptedContentHelp">
+          <p class="pl-4 text-base">
+            {{ $strings.LabelSettingsEpubsAllowScriptedContent }}
+            <span class="material-icons icon-text text-sm">info_outlined</span>
+          </p>
+        </ui-tooltip>
+      </div>
+    </div>
     <div v-if="isPodcastLibrary" class="py-3">
       <ui-dropdown :label="$strings.LabelPodcastSearchRegion" v-model="podcastSearchRegion" :items="$podcastSearchRegionOptions" small class="max-w-72" menu-max-height="200px" @input="formUpdated" />
     </div>
   </div>
 </template>
@@ -81,10 +92,11 @@ export default {
       useSquareBookCovers: false,
       enableWatcher: false,
       skipMatchingMediaWithAsin: false,
       skipMatchingMediaWithIsbn: false,
       audiobooksOnly: false,
+      epubsAllowScriptedContent: false,
       hideSingleBookSeries: false,
       onlyShowLaterBooksInContinueSeries: false,
       podcastSearchRegion: 'us'
     }
   },
@@ -116,10 +128,11 @@ export default {
           coverAspectRatio: this.useSquareBookCovers ? this.$constants.BookCoverAspectRatio.SQUARE : this.$constants.BookCoverAspectRatio.STANDARD,
           disableWatcher: !this.enableWatcher,
           skipMatchingMediaWithAsin: !!this.skipMatchingMediaWithAsin,
           skipMatchingMediaWithIsbn: !!this.skipMatchingMediaWithIsbn,
           audiobooksOnly: !!this.audiobooksOnly,
+          epubsAllowScriptedContent: !!this.epubsAllowScriptedContent,
           hideSingleBookSeries: !!this.hideSingleBookSeries,
           onlyShowLaterBooksInContinueSeries: !!this.onlyShowLaterBooksInContinueSeries,
           podcastSearchRegion: this.podcastSearchRegion
         }
       }
@@ -131,15 +144,16 @@ export default {
       this.useSquareBookCovers = this.librarySettings.coverAspectRatio === this.$constants.BookCoverAspectRatio.SQUARE
       this.enableWatcher = !this.librarySettings.disableWatcher
       this.skipMatchingMediaWithAsin = !!this.librarySettings.skipMatchingMediaWithAsin
       this.skipMatchingMediaWithIsbn = !!this.librarySettings.skipMatchingMediaWithIsbn
       this.audiobooksOnly = !!this.librarySettings.audiobooksOnly
+      this.epubsAllowScriptedContent = !!this.librarySettings.epubsAllowScriptedContent
       this.hideSingleBookSeries = !!this.librarySettings.hideSingleBookSeries
       this.onlyShowLaterBooksInContinueSeries = !!this.librarySettings.onlyShowLaterBooksInContinueSeries
       this.podcastSearchRegion = this.librarySettings.podcastSearchRegion || 'us'
     }
   },
   mounted() {
     this.init()
   }
 }
-</script>
\ No newline at end of file
+</script>
diff --git a/client/components/readers/EpubReader.vue b/client/components/readers/EpubReader.vue
index 3941c0d81..819f5beb1 100644
--- a/client/components/readers/EpubReader.vue
+++ b/client/components/readers/EpubReader.vue
@@ -61,10 +61,13 @@ export default {
     },
     /** @returns {string} */
     libraryItemId() {
       return this.libraryItem?.id
     },
+    allowScriptedContent() {
+      return this.$store.getters['libraries/getLibraryEpubsAllowScriptedContent']
+    },
     hasPrev() {
       return !this.rendition?.location?.atStart
     },
     hasNext() {
       return !this.rendition?.location?.atEnd
@@ -314,11 +317,11 @@ export default {
 
       /** @type {ePub.Rendition} */
       reader.rendition = reader.book.renderTo('viewer', {
         width: this.readerWidth,
         height: this.readerHeight * 0.8,
-        allowScriptedContent: true,
+        allowScriptedContent: this.allowScriptedContent,
         spread: 'auto',
         snap: true,
         manager: 'continuous',
         flow: 'paginated'
       })
diff --git a/client/store/libraries.js b/client/store/libraries.js
index 1d13d6322..f56bdad67 100644
--- a/client/store/libraries.js
+++ b/client/store/libraries.js
@@ -14,27 +14,27 @@ export const state = () => ({
   userPlaylists: [],
   ereaderDevices: []
 })
 
 export const getters = {
-  getCurrentLibrary: state => {
-    return state.libraries.find(lib => lib.id === state.currentLibraryId)
+  getCurrentLibrary: (state) => {
+    return state.libraries.find((lib) => lib.id === state.currentLibraryId)
   },
   getCurrentLibraryName: (state, getters) => {
     var currentLibrary = getters.getCurrentLibrary
     if (!currentLibrary) return ''
     return currentLibrary.name
   },
   getCurrentLibraryMediaType: (state, getters) => {
     if (!getters.getCurrentLibrary) return null
     return getters.getCurrentLibrary.mediaType
   },
-  getSortedLibraries: state => () => {
-    return state.libraries.map(lib => ({ ...lib })).sort((a, b) => a.displayOrder - b.displayOrder)
+  getSortedLibraries: (state) => () => {
+    return state.libraries.map((lib) => ({ ...lib })).sort((a, b) => a.displayOrder - b.displayOrder)
   },
-  getLibraryProvider: state => libraryId => {
-    var library = state.libraries.find(l => l.id === libraryId)
+  getLibraryProvider: (state) => (libraryId) => {
+    var library = state.libraries.find((l) => l.id === libraryId)
     if (!library) return null
     return library.provider
   },
   getNextAccessibleLibrary: (state, getters, rootState, rootGetters) => {
     var librariesSorted = getters['getSortedLibraries']()
@@ -58,26 +58,30 @@ export const getters = {
     return getters.getCurrentLibrarySettings.coverAspectRatio === Constants.BookCoverAspectRatio.STANDARD ? 1.6 : 1
   },
   getLibraryIsAudiobooksOnly: (state, getters) => {
     return !!getters.getCurrentLibrarySettings?.audiobooksOnly
   },
-  getCollection: state => id => {
-    return state.collections.find(c => c.id === id)
+  getLibraryEpubsAllowScriptedContent: (state, getters) => {
+    return !!getters.getCurrentLibrarySettings?.epubsAllowScriptedContent
   },
-  getPlaylist: state => id => {
-    return state.userPlaylists.find(p => p.id === id)
+  getCollection: (state) => (id) => {
+    return state.collections.find((c) => c.id === id)
+  },
+  getPlaylist: (state) => (id) => {
+    return state.userPlaylists.find((p) => p.id === id)
   }
 }
 
 export const actions = {
   requestLibraryScan({ state, commit }, { libraryId, force }) {
     return this.$axios.$post(`/api/libraries/${libraryId}/scan?force=${force ? 1 : 0}`)
   },
   loadFolders({ state, commit }) {
     if (state.folders.length) {
       const lastCheck = Date.now() - state.folderLastUpdate
-      if (lastCheck < 1000 * 5) { // 5 seconds
+      if (lastCheck < 1000 * 5) {
+        // 5 seconds
         // Folders up to date
         return state.folders
       }
     }
     commit('setFoldersLastUpdate')
@@ -202,11 +206,11 @@ export const mutations = {
     state.listeners.forEach((listener) => {
       listener.meth()
     })
   },
   addUpdate(state, library) {
-    var index = state.libraries.findIndex(a => a.id === library.id)
+    var index = state.libraries.findIndex((a) => a.id === library.id)
     if (index >= 0) {
       state.libraries.splice(index, 1, library)
     } else {
       state.libraries.push(library)
     }
@@ -214,33 +218,33 @@ export const mutations = {
     state.listeners.forEach((listener) => {
       listener.meth()
     })
   },
   remove(state, library) {
-    state.libraries = state.libraries.filter(a => a.id !== library.id)
+    state.libraries = state.libraries.filter((a) => a.id !== library.id)
 
     state.listeners.forEach((listener) => {
       listener.meth()
     })
   },
   addListener(state, listener) {
-    var index = state.listeners.findIndex(l => l.id === listener.id)
+    var index = state.listeners.findIndex((l) => l.id === listener.id)
     if (index >= 0) state.listeners.splice(index, 1, listener)
     else state.listeners.push(listener)
   },
   removeListener(state, listenerId) {
-    state.listeners = state.listeners.filter(l => l.id !== listenerId)
+    state.listeners = state.listeners.filter((l) => l.id !== listenerId)
   },
   setLibraryFilterData(state, filterData) {
     state.filterData = filterData
   },
   setNumUserPlaylists(state, numUserPlaylists) {
     state.numUserPlaylists = numUserPlaylists
   },
   removeSeriesFromFilterData(state, seriesId) {
     if (!seriesId || !state.filterData) return
-    state.filterData.series = state.filterData.series.filter(se => se.id !== seriesId)
+    state.filterData.series = state.filterData.series.filter((se) => se.id !== seriesId)
   },
   updateFilterDataWithItem(state, libraryItem) {
     if (!libraryItem || !state.filterData) return
     if (state.currentLibraryId !== libraryItem.libraryId) return
     /*
@@ -258,29 +262,29 @@ export const mutations = {
     const mediaMetadata = libraryItem.media.metadata
 
     // Add/update book authors
     if (mediaMetadata.authors?.length) {
       mediaMetadata.authors.forEach((author) => {
-        const indexOf = state.filterData.authors.findIndex(au => au.id === author.id)
+        const indexOf = state.filterData.authors.findIndex((au) => au.id === author.id)
         if (indexOf >= 0) {
           state.filterData.authors.splice(indexOf, 1, author)
         } else {
           state.filterData.authors.push(author)
-          state.filterData.authors.sort((a, b) => (a.name || '').localeCompare((b.name || '')))
+          state.filterData.authors.sort((a, b) => (a.name || '').localeCompare(b.name || ''))
         }
       })
     }
 
     // Add/update series
     if (mediaMetadata.series?.length) {
       mediaMetadata.series.forEach((series) => {
-        const indexOf = state.filterData.series.findIndex(se => se.id === series.id)
+        const indexOf = state.filterData.series.findIndex((se) => se.id === series.id)
         if (indexOf >= 0) {
           state.filterData.series.splice(indexOf, 1, { id: series.id, name: series.name })
         } else {
           state.filterData.series.push({ id: series.id, name: series.name })
-          state.filterData.series.sort((a, b) => (a.name || '').localeCompare((b.name || '')))
+          state.filterData.series.sort((a, b) => (a.name || '').localeCompare(b.name || ''))
         }
       })
     }
 
     // Add genres
@@ -327,36 +331,36 @@ export const mutations = {
   },
   setCollections(state, collections) {
     state.collections = collections
   },
   addUpdateCollection(state, collection) {
-    var index = state.collections.findIndex(c => c.id === collection.id)
+    var index = state.collections.findIndex((c) => c.id === collection.id)
     if (index >= 0) {
       state.collections.splice(index, 1, collection)
     } else {
       state.collections.push(collection)
     }
   },
   removeCollection(state, collection) {
-    state.collections = state.collections.filter(c => c.id !== collection.id)
+    state.collections = state.collections.filter((c) => c.id !== collection.id)
   },
   setUserPlaylists(state, playlists) {
     state.userPlaylists = playlists
     state.numUserPlaylists = playlists.length
   },
   addUpdateUserPlaylist(state, playlist) {
-    const index = state.userPlaylists.findIndex(p => p.id === playlist.id)
+    const index = state.userPlaylists.findIndex((p) => p.id === playlist.id)
     if (index >= 0) {
       state.userPlaylists.splice(index, 1, playlist)
     } else {
       state.userPlaylists.push(playlist)
       state.numUserPlaylists++
     }
   },
   removeUserPlaylist(state, playlist) {
-    state.userPlaylists = state.userPlaylists.filter(p => p.id !== playlist.id)
+    state.userPlaylists = state.userPlaylists.filter((p) => p.id !== playlist.id)
     state.numUserPlaylists = state.userPlaylists.length
   },
   setEReaderDevices(state, ereaderDevices) {
     state.ereaderDevices = ereaderDevices
   }
-}
\ No newline at end of file
+}
diff --git a/client/strings/bg.json b/client/strings/bg.json
index f8c9c5948..0858856e4 100644
--- a/client/strings/bg.json
+++ b/client/strings/bg.json
@@ -469,10 +469,12 @@
   "LabelSettingsDisableWatcherForLibrary": "Изключи наблюдателя за библиотека",
   "LabelSettingsDisableWatcherHelp": "Изключва автоматичното добавяне/обновяване на елементи, когато се открият промени във файловете. *Изисква рестарт на сървъра",
   "LabelSettingsEnableWatcher": "Включи наблюдателя",
   "LabelSettingsEnableWatcherForLibrary": "Включи наблюдателя за библиотека",
   "LabelSettingsEnableWatcherHelp": "Включва автоматичното добавяне/обновяване на елементи, когато се открият промени във файловете. *Изисква рестарт на сървъра",
+  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
+  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
   "LabelSettingsExperimentalFeatures": "Експериментални Функции",
   "LabelSettingsExperimentalFeaturesHelp": "Функции в разработка, които могат да изискват вашето мнение и помощ за тестване. Кликнете за да отворите дискусия в github.",
   "LabelSettingsFindCovers": "Намери Корици",
   "LabelSettingsFindCoversHelp": "Ако аудиокнигата ви няма вградена корица или изображение на корицата в папката, скенерът ще опита да намери корица.<br>Забележка: Това ще удължи времето за сканиране",
   "LabelSettingsHideSingleBookSeries": "Скрий серии с една книга",
diff --git a/client/strings/bn.json b/client/strings/bn.json
index 07e226a8b..89fe78fef 100644
--- a/client/strings/bn.json
+++ b/client/strings/bn.json
@@ -469,10 +469,12 @@
   "LabelSettingsDisableWatcherForLibrary": "লাইব্রেরির জন্য ফোল্ডার প্রহরী নিষ্ক্রিয় করুন",
   "LabelSettingsDisableWatcherHelp": "ফাইলের পরিবর্তন শনাক্ত হলে স্বয়ংক্রিয়ভাবে আইটেম যোগ/আপডেট করা অক্ষম করবে। *সার্ভার পুনরায় চালু করতে হবে",
   "LabelSettingsEnableWatcher": "প্রহরী সক্ষম করুন",
   "LabelSettingsEnableWatcherForLibrary": "লাইব্রেরির জন্য ফোল্ডার প্রহরী সক্ষম করুন",
   "LabelSettingsEnableWatcherHelp": "ফাইলের পরিবর্তন শনাক্ত হলে আইটেমগুলির স্বয়ংক্রিয় যোগ/আপডেট সক্ষম করবে। *সার্ভার পুনরায় চালু করতে হবে",
+  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
+  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
   "LabelSettingsExperimentalFeatures": "পরীক্ষামূলক বৈশিষ্ট্য",
   "LabelSettingsExperimentalFeaturesHelp": "ফিচারের বৈশিষ্ট্য যা আপনার প্রতিক্রিয়া ব্যবহার করতে পারে এবং পরীক্ষায় সহায়তা করতে পারে। গিটহাব আলোচনা খুলতে ক্লিক করুন।",
   "LabelSettingsFindCovers": "কভার খুঁজুন",
   "LabelSettingsFindCoversHelp": "যদি আপনার অডিওবইয়ের ফোল্ডারের ভিতরে একটি এমবেডেড কভার বা কভার ইমেজ না থাকে, তাহলে স্ক্যানার একটি কভার খোঁজার চেষ্টা করবে৷<br>দ্রষ্টব্য: এটি স্ক্যানের সময় বাড়িয়ে দেবে",
   "LabelSettingsHideSingleBookSeries": "একক বই সিরিজ লুকান",
diff --git a/client/strings/cs.json b/client/strings/cs.json
index f7aeda3a3..b326996d1 100644
--- a/client/strings/cs.json
+++ b/client/strings/cs.json
@@ -469,10 +469,12 @@
   "LabelSettingsDisableWatcherForLibrary": "Zakázat sledování složky pro knihovnu",
   "LabelSettingsDisableWatcherHelp": "Zakáže automatické přidávání/aktualizaci položek při zjištění změn v souboru. *Vyžaduje restart serveru",
   "LabelSettingsEnableWatcher": "Povolit sledování",
   "LabelSettingsEnableWatcherForLibrary": "Povolit sledování složky pro knihovnu",
   "LabelSettingsEnableWatcherHelp": "Povoluje automatické přidávání/aktualizaci položek, když jsou zjištěny změny souborů. *Vyžaduje restart serveru",
+  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
+  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
   "LabelSettingsExperimentalFeatures": "Experimentální funkce",
   "LabelSettingsExperimentalFeaturesHelp": "Funkce ve vývoji, které by mohly využít vaši zpětnou vazbu a pomoc s testováním. Kliknutím otevřete diskuzi na githubu.",
   "LabelSettingsFindCovers": "Najít obálky",
   "LabelSettingsFindCoversHelp": "Pokud vaše audiokniha nemá vloženou obálku nebo obrázek obálky uvnitř složky, skener se pokusí obálku najít.<br>Poznámka: Tím se prodlouží doba prohledávání",
   "LabelSettingsHideSingleBookSeries": "Skrýt sérii s jedinou knihou",
diff --git a/client/strings/da.json b/client/strings/da.json
index 080d61d52..96a0d04b2 100644
--- a/client/strings/da.json
+++ b/client/strings/da.json
@@ -469,10 +469,12 @@
   "LabelSettingsDisableWatcherForLibrary": "Deaktiver mappeovervågning for bibliotek",
   "LabelSettingsDisableWatcherHelp": "Deaktiverer automatisk tilføjelse/opdatering af elementer, når der registreres filændringer. *Kræver servergenstart",
   "LabelSettingsEnableWatcher": "Aktiver overvågning",
   "LabelSettingsEnableWatcherForLibrary": "Aktiver mappeovervågning for bibliotek",
   "LabelSettingsEnableWatcherHelp": "Aktiverer automatisk tilføjelse/opdatering af elementer, når filændringer registreres. *Kræver servergenstart",
+  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
+  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
   "LabelSettingsExperimentalFeatures": "Eksperimentelle funktioner",
   "LabelSettingsExperimentalFeaturesHelp": "Funktioner under udvikling, der kunne bruge din feedback og hjælp til test. Klik for at åbne Github-diskussionen.",
   "LabelSettingsFindCovers": "Find omslag",
   "LabelSettingsFindCoversHelp": "Hvis din lydbog ikke har et indlejret omslag eller et omslagsbillede i mappen, vil skanneren forsøge at finde et omslag.<br>Bemærk: Dette vil forlænge scanntiden",
   "LabelSettingsHideSingleBookSeries": "Skjul enkeltbogsserier",
diff --git a/client/strings/de.json b/client/strings/de.json
index dcf23084a..4ce822ddd 100644
--- a/client/strings/de.json
+++ b/client/strings/de.json
@@ -469,10 +469,12 @@
   "LabelSettingsDisableWatcherForLibrary": "Ordnerüberwachung für die Bibliothek deaktivieren",
   "LabelSettingsDisableWatcherHelp": "Deaktiviert das automatische Hinzufügen/Aktualisieren von Elementen, wenn Dateiänderungen erkannt werden. *Erfordert einen Server-Neustart",
   "LabelSettingsEnableWatcher": "Überwachung aktivieren",
   "LabelSettingsEnableWatcherForLibrary": "Ordnerüberwachung für die Bibliothek aktivieren",
   "LabelSettingsEnableWatcherHelp": "Aktiviert das automatische Hinzufügen/Aktualisieren von Elementen, wenn Dateiänderungen erkannt werden. *Erfordert einen Server-Neustart",
+  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
+  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
   "LabelSettingsExperimentalFeatures": "Experimentelle Funktionen",
   "LabelSettingsExperimentalFeaturesHelp": "Funktionen welche sich in der Entwicklung befinden, benötigen dein Feedback und deine Hilfe beim Testen. Klicke hier, um die Github-Diskussion zu öffnen.",
   "LabelSettingsFindCovers": "Suche Titelbilder",
   "LabelSettingsFindCoversHelp": "Wenn dein Medium kein eingebettetes Titelbild oder kein Titelbild im Ordner hat, versucht der Scanner, ein Titelbild online zu finden.<br>Hinweis: Dies verlängert die Scandauer",
   "LabelSettingsHideSingleBookSeries": "Ausblenden einzelner Bücher",
diff --git a/client/strings/en-us.json b/client/strings/en-us.json
index 7828f5f9f..2a390b5fa 100644
--- a/client/strings/en-us.json
+++ b/client/strings/en-us.json
@@ -469,10 +469,12 @@
   "LabelSettingsDisableWatcherForLibrary": "Disable folder watcher for library",
   "LabelSettingsDisableWatcherHelp": "Disables the automatic adding/updating of items when file changes are detected. *Requires server restart",
   "LabelSettingsEnableWatcher": "Enable Watcher",
   "LabelSettingsEnableWatcherForLibrary": "Enable folder watcher for library",
   "LabelSettingsEnableWatcherHelp": "Enables the automatic adding/updating of items when file changes are detected. *Requires server restart",
+  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
+  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
   "LabelSettingsExperimentalFeatures": "Experimental features",
   "LabelSettingsExperimentalFeaturesHelp": "Features in development that could use your feedback and help testing. Click to open github discussion.",
   "LabelSettingsFindCovers": "Find covers",
   "LabelSettingsFindCoversHelp": "If your audiobook does not have an embedded cover or a cover image inside the folder, the scanner will attempt to find a cover.<br>Note: This will extend scan time",
   "LabelSettingsHideSingleBookSeries": "Hide single book series",
diff --git a/client/strings/es.json b/client/strings/es.json
index 0b1279674..cead84e25 100644
--- a/client/strings/es.json
+++ b/client/strings/es.json
@@ -469,10 +469,12 @@
   "LabelSettingsDisableWatcherForLibrary": "Deshabilitar Watcher de Carpetas para esta biblioteca",
   "LabelSettingsDisableWatcherHelp": "Deshabilitar la función de agregar/actualizar elementos automáticamente cuando se detectan cambios en los archivos. *Require Reiniciar el Servidor",
   "LabelSettingsEnableWatcher": "Habilitar Watcher",
   "LabelSettingsEnableWatcherForLibrary": "Habilitar Watcher para la carpeta de esta biblioteca",
   "LabelSettingsEnableWatcherHelp": "Permite agregar/actualizar elementos automáticamente cuando se detectan cambios en los archivos. *Requiere reiniciar el servidor",
+  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
+  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
   "LabelSettingsExperimentalFeatures": "Funciones Experimentales",
   "LabelSettingsExperimentalFeaturesHelp": "Funciones en desarrollo que se beneficiarían de sus comentarios y experiencias de prueba. Haga click aquí para abrir una conversación en Github.",
   "LabelSettingsFindCovers": "Buscar Portadas",
   "LabelSettingsFindCoversHelp": "Si tu audiolibro no tiene una portada incluída, o la portada no esta dentro de la carpeta, el escaneador tratará de encontrar una portada.<br>Nota: Esto extenderá el tiempo de escaneo",
   "LabelSettingsHideSingleBookSeries": "Esconder series con un solo libro",
diff --git a/client/strings/et.json b/client/strings/et.json
index 9944fca13..fcf7c4ce2 100644
--- a/client/strings/et.json
+++ b/client/strings/et.json
@@ -469,10 +469,12 @@
   "LabelSettingsDisableWatcherForLibrary": "Keela kaustavaatamine raamatukogu jaoks",
   "LabelSettingsDisableWatcherHelp": "Keelab automaatse lisamise/uuendamise, kui failimuudatusi tuvastatakse. *Nõuab serveri taaskäivitamist",
   "LabelSettingsEnableWatcher": "Luba vaatamine",
   "LabelSettingsEnableWatcherForLibrary": "Luba kaustavaatamine raamatukogu jaoks",
   "LabelSettingsEnableWatcherHelp": "Lubab automaatset lisamist/uuendamist, kui tuvastatakse failimuudatused. *Nõuab serveri taaskäivitamist",
+  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
+  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
   "LabelSettingsExperimentalFeatures": "Eksperimentaalsed funktsioonid",
   "LabelSettingsExperimentalFeaturesHelp": "Arengus olevad funktsioonid, mis vajavad teie tagasisidet ja abi testimisel. Klõpsake GitHubi arutelu avamiseks.",
   "LabelSettingsFindCovers": "Leia ümbrised",
   "LabelSettingsFindCoversHelp": "Kui teie heliraamatul pole sisseehitatud ümbrist ega ümbrise pilti kaustas, proovib skanner leida ümbrist.<br>Märkus: see pikendab skaneerimisaega",
   "LabelSettingsHideSingleBookSeries": "Peida üksikute raamatute seeriad",
diff --git a/client/strings/fr.json b/client/strings/fr.json
index 053de0d38..ae7f60f3b 100644
--- a/client/strings/fr.json
+++ b/client/strings/fr.json
@@ -469,10 +469,12 @@
   "LabelSettingsDisableWatcherForLibrary": "Désactiver la surveillance des dossiers pour la bibliothèque",
   "LabelSettingsDisableWatcherHelp": "Désactive la mise à jour automatique lorsque des modifications de fichiers sont détectées. * nécessite le redémarrage du serveur",
   "LabelSettingsEnableWatcher": "Activer la veille",
   "LabelSettingsEnableWatcherForLibrary": "Activer la surveillance des dossiers pour la bibliothèque",
   "LabelSettingsEnableWatcherHelp": "Active la mise à jour automatique automatique lorsque des modifications de fichiers sont détectées. * nécessite le redémarrage du serveur",
+  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
+  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
   "LabelSettingsExperimentalFeatures": "Fonctionnalités expérimentales",
   "LabelSettingsExperimentalFeaturesHelp": "Fonctionnalités en cours de développement sur lesquelles nous attendons votre retour et expérience. Cliquez pour ouvrir la discussion GitHub.",
   "LabelSettingsFindCovers": "Chercher des couvertures de livre",
   "LabelSettingsFindCoversHelp": "Si votre livre audio ne possède pas de couverture intégrée ou une image de couverture dans le dossier, l’analyseur tentera de récupérer une couverture.<br>Attention, cela peut augmenter le temps d’analyse.",
   "LabelSettingsHideSingleBookSeries": "Masquer les séries de livres uniques",
diff --git a/client/strings/gu.json b/client/strings/gu.json
index 2f7be4d01..11c475043 100644
--- a/client/strings/gu.json
+++ b/client/strings/gu.json
@@ -469,10 +469,12 @@
   "LabelSettingsDisableWatcherForLibrary": "Disable folder watcher for library",
   "LabelSettingsDisableWatcherHelp": "Disables the automatic adding/updating of items when file changes are detected. *Requires server restart",
   "LabelSettingsEnableWatcher": "Enable Watcher",
   "LabelSettingsEnableWatcherForLibrary": "Enable folder watcher for library",
   "LabelSettingsEnableWatcherHelp": "Enables the automatic adding/updating of items when file changes are detected. *Requires server restart",
+  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
+  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
   "LabelSettingsExperimentalFeatures": "Experimental features",
   "LabelSettingsExperimentalFeaturesHelp": "Features in development that could use your feedback and help testing. Click to open github discussion.",
   "LabelSettingsFindCovers": "Find covers",
   "LabelSettingsFindCoversHelp": "If your audiobook does not have an embedded cover or a cover image inside the folder, the scanner will attempt to find a cover.<br>Note: This will extend scan time",
   "LabelSettingsHideSingleBookSeries": "Hide single book series",
diff --git a/client/strings/he.json b/client/strings/he.json
index 9ddf2d5fd..7d17a2a88 100644
--- a/client/strings/he.json
+++ b/client/strings/he.json
@@ -469,10 +469,12 @@
   "LabelSettingsDisableWatcherForLibrary": "השבת עוקב תיקייה עבור ספרייה",
   "LabelSettingsDisableWatcherHelp": "מבטל את הוספת/עדכון אוטומטי של פריטים כאשר שינויי קבצים זוהים. *דורש איתחול שרת",
   "LabelSettingsEnableWatcher": "הפעל עוקב",
   "LabelSettingsEnableWatcherForLibrary": "הפעל עוקב תיקייה עבור ספרייה",
   "LabelSettingsEnableWatcherHelp": "מאפשר הוספת/עדכון אוטומטי של פריטים כאשר שינויי קבצים זוהים. *דורש איתחול שרת",
+  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
+  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
   "LabelSettingsExperimentalFeatures": "תכונות ניסיוניות",
   "LabelSettingsExperimentalFeaturesHelp": "תכונות בפיתוח שדורשות משובך ובדיקה. לחץ לפתיחת דיון ב-GitHub.",
   "LabelSettingsFindCovers": "מצא כריכות",
   "LabelSettingsFindCoversHelp": "אם לספר הקולי שלך אין כריכה מוטמעת או תמונת כריכה בתיקייה, הסורק ינסה למצוא תמונת כריכה.<br>שים לב: זה יאריך את זמן הסריקה",
   "LabelSettingsHideSingleBookSeries": "הסתר סדרות עם ספר אחד",
diff --git a/client/strings/hi.json b/client/strings/hi.json
index df09699f1..83b7f011a 100644
--- a/client/strings/hi.json
+++ b/client/strings/hi.json
@@ -469,10 +469,12 @@
   "LabelSettingsDisableWatcherForLibrary": "Disable folder watcher for library",
   "LabelSettingsDisableWatcherHelp": "Disables the automatic adding/updating of items when file changes are detected. *Requires server restart",
   "LabelSettingsEnableWatcher": "Enable Watcher",
   "LabelSettingsEnableWatcherForLibrary": "Enable folder watcher for library",
   "LabelSettingsEnableWatcherHelp": "Enables the automatic adding/updating of items when file changes are detected. *Requires server restart",
+  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
+  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
   "LabelSettingsExperimentalFeatures": "Experimental features",
   "LabelSettingsExperimentalFeaturesHelp": "Features in development that could use your feedback and help testing. Click to open github discussion.",
   "LabelSettingsFindCovers": "Find covers",
   "LabelSettingsFindCoversHelp": "If your audiobook does not have an embedded cover or a cover image inside the folder, the scanner will attempt to find a cover.<br>Note: This will extend scan time",
   "LabelSettingsHideSingleBookSeries": "Hide single book series",
diff --git a/client/strings/hr.json b/client/strings/hr.json
index f1c47bd22..a3a88e9ce 100644
--- a/client/strings/hr.json
+++ b/client/strings/hr.json
@@ -469,10 +469,12 @@
   "LabelSettingsDisableWatcherForLibrary": "Isključi folder watchera za biblioteku",
   "LabelSettingsDisableWatcherHelp": "Isključi automatsko dodavanje/aktualiziranje stavci ako su promjene prepoznate. *Potreban restart servera",
   "LabelSettingsEnableWatcher": "Enable Watcher",
   "LabelSettingsEnableWatcherForLibrary": "Enable folder watcher for library",
   "LabelSettingsEnableWatcherHelp": "Enables the automatic adding/updating of items when file changes are detected. *Requires server restart",
+  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
+  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
   "LabelSettingsExperimentalFeatures": "Eksperimentalni features",
   "LabelSettingsExperimentalFeaturesHelp": "Features u razvoju trebaju vaš feedback i pomoć pri testiranju. Klikni da odeš to Github discussionsa.",
   "LabelSettingsFindCovers": "Pronađi covers",
   "LabelSettingsFindCoversHelp": "Ako audiobook nema embedani cover or a cover sliku unutar foldera, skener će probati pronaći cover.<br>Bilješka: Ovo će produžiti trjanje skeniranja",
   "LabelSettingsHideSingleBookSeries": "Hide single book series",
diff --git a/client/strings/hu.json b/client/strings/hu.json
index 8cdb4566d..971c45fc8 100644
--- a/client/strings/hu.json
+++ b/client/strings/hu.json
@@ -469,10 +469,12 @@
   "LabelSettingsDisableWatcherForLibrary": "Mappafigyelő letiltása a könyvtárban",
   "LabelSettingsDisableWatcherHelp": "Letiltja az automatikus elem hozzáadás/frissítés funkciót, amikor fájlváltozásokat észlel. *Szerver újraindítása szükséges",
   "LabelSettingsEnableWatcher": "Figyelő engedélyezése",
   "LabelSettingsEnableWatcherForLibrary": "Mappafigyelő engedélyezése a könyvtárban",
   "LabelSettingsEnableWatcherHelp": "Engedélyezi az automatikus elem hozzáadás/frissítés funkciót, amikor fájlváltozásokat észlel. *Szerver újraindítása szükséges",
+  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
+  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
   "LabelSettingsExperimentalFeatures": "Kísérleti funkciók",
   "LabelSettingsExperimentalFeaturesHelp": "Fejlesztés alatt álló funkciók, amelyek visszajelzésre és tesztelésre szorulnak. Kattintson a github megbeszélés megnyitásához.",
   "LabelSettingsFindCovers": "Borítók keresése",
   "LabelSettingsFindCoversHelp": "Ha a hangoskönyvnek nincs beágyazott borítója vagy borítóképe a mappában, a szkenner megpróbálja megtalálni a borítót.<br>Megjegyzés: Ez meghosszabbítja a szkennelési időt",
   "LabelSettingsHideSingleBookSeries": "Egykönyves sorozatok elrejtése",
diff --git a/client/strings/it.json b/client/strings/it.json
index f2295d2b1..549ea94d4 100644
--- a/client/strings/it.json
+++ b/client/strings/it.json
@@ -469,10 +469,12 @@
   "LabelSettingsDisableWatcherForLibrary": "Disattiva Watcher per le librerie",
   "LabelSettingsDisableWatcherHelp": "Disattiva il controllo automatico libri nelle cartelle delle librerie. *Richiede il Riavvio del Server",
   "LabelSettingsEnableWatcher": "Abilita Watcher",
   "LabelSettingsEnableWatcherForLibrary": "Abilita il controllo cartelle per la libreria",
   "LabelSettingsEnableWatcherHelp": "Abilita l'aggiunta/aggiornamento automatico degli elementi quando vengono rilevate modifiche ai file. *Richiede il riavvio del Server",
+  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
+  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
   "LabelSettingsExperimentalFeatures": "Opzioni Sperimentali",
   "LabelSettingsExperimentalFeaturesHelp": "Funzionalità in fase di sviluppo che potrebbero utilizzare i tuoi feedback e aiutare i test. Fare clic per aprire la discussione github.",
   "LabelSettingsFindCovers": "Trova covers",
   "LabelSettingsFindCoversHelp": "Se il tuo audiolibro non ha una copertina incorporata o un'immagine di copertina all'interno della cartella, questa funzione tenterà di trovare una copertina.<br>Nota: aumenta il tempo di scansione",
   "LabelSettingsHideSingleBookSeries": "Nascondi una singola serie di libri",
diff --git a/client/strings/lt.json b/client/strings/lt.json
index 8c904e1f1..5bd42bdf2 100644
--- a/client/strings/lt.json
+++ b/client/strings/lt.json
@@ -469,10 +469,12 @@
   "LabelSettingsDisableWatcherForLibrary": "Išjungti aplankų stebėtoją bibliotekai",
   "LabelSettingsDisableWatcherHelp": "Išjungia automatinį elementų pridėjimą/atnaujinimą, jei pastebėti failų pokyčiai. *Reikalingas serverio paleidimas iš naujo",
   "LabelSettingsEnableWatcher": "Enable Watcher",
   "LabelSettingsEnableWatcherForLibrary": "Enable folder watcher for library",
   "LabelSettingsEnableWatcherHelp": "Enables the automatic adding/updating of items when file changes are detected. *Requires server restart",
+  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
+  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
   "LabelSettingsExperimentalFeatures": "Eksperimentiniai funkcionalumai",
   "LabelSettingsExperimentalFeaturesHelp": "Funkcijos, kurios yra kuriamos ir laukiami jūsų komentarai. Spustelėkite, kad atidarytumėte „GitHub“ diskusiją.",
   "LabelSettingsFindCovers": "Rasti viršelius",
   "LabelSettingsFindCoversHelp": "Jei jūsų audioknyga neturi įterpto viršelio arba viršelio paveikslėlio aplanko, skeneris bandys rasti viršelį.<br>Pastaba: Tai padidins skenavimo trukmę.",
   "LabelSettingsHideSingleBookSeries": "Slėpti serijas, turinčias tik vieną knygą",
diff --git a/client/strings/nl.json b/client/strings/nl.json
index 84f4d0543..28c3ada1c 100644
--- a/client/strings/nl.json
+++ b/client/strings/nl.json
@@ -469,10 +469,12 @@
   "LabelSettingsDisableWatcherForLibrary": "Map-watcher voor bibliotheek uitschakelen",
   "LabelSettingsDisableWatcherHelp": "Schakelt het automatisch toevoegen/bijwerken van onderdelen wanneer bestandswijzigingen gedetecteerd zijn uit. *Vereist herstart server",
   "LabelSettingsEnableWatcher": "Watcher inschakelen",
   "LabelSettingsEnableWatcherForLibrary": "Map-watcher voor bibliotheek inschakelen",
   "LabelSettingsEnableWatcherHelp": "Zorgt voor het automatisch toevoegen/bijwerken van onderdelen als bestandswijzigingen worden gedetecteerd. *Vereist herstarten van server",
+  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
+  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
   "LabelSettingsExperimentalFeatures": "Experimentele functies",
   "LabelSettingsExperimentalFeaturesHelp": "Functies in ontwikkeling die je feedback en testing kunnen gebruiken. Klik om de Github-discussie te openen.",
   "LabelSettingsFindCovers": "Zoek covers",
   "LabelSettingsFindCoversHelp": "Als je audioboek geen ingesloten cover of cover in de map heeft, zal de scanner proberen een cover te vinden.<br>Opmerking: Dit zal de scan-duur verlengen",
   "LabelSettingsHideSingleBookSeries": "Verberg series met een enkel boek",
diff --git a/client/strings/no.json b/client/strings/no.json
index 95d9d8563..4c4be82fa 100644
--- a/client/strings/no.json
+++ b/client/strings/no.json
@@ -469,10 +469,12 @@
   "LabelSettingsDisableWatcherForLibrary": "Deaktiver mappe overvåker for bibliotek",
   "LabelSettingsDisableWatcherHelp": "Deaktiverer automatisk opprettelse/oppdatering av enheter når filendringer er oppdaget. *Krever restart av server*",
   "LabelSettingsEnableWatcher": "Aktiver overvåker",
   "LabelSettingsEnableWatcherForLibrary": "Aktiver mappe overvåker for bibliotek",
   "LabelSettingsEnableWatcherHelp": "Aktiverer automatisk opprettelse/oppdatering av enheter når filendringer er oppdaget. *Krever restart av server*",
+  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
+  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
   "LabelSettingsExperimentalFeatures": "Eksperimentelle funksjoner",
   "LabelSettingsExperimentalFeaturesHelp": "Funksjoner under utvikling som kan trenge din tilbakemelding og hjelp med testing. Klikk for å åpne GitHub diskusjon.",
   "LabelSettingsFindCovers": "Finn omslag",
   "LabelSettingsFindCoversHelp": "Hvis lydboken ikke har innbakt omslag eller ett omslagsbilde i mappen, vil skanneren prøve å finne ett.<br>Notis: Dette vil øke søketiden",
   "LabelSettingsHideSingleBookSeries": "Gjem bokserie med en bok",
diff --git a/client/strings/pl.json b/client/strings/pl.json
index 0fa5ee328..ce0109d9e 100644
--- a/client/strings/pl.json
+++ b/client/strings/pl.json
@@ -469,10 +469,12 @@
   "LabelSettingsDisableWatcherForLibrary": "Wyłącz monitorowanie folderów dla biblioteki",
   "LabelSettingsDisableWatcherHelp": "Wyłącz automatyczne dodawanie/aktualizowanie elementów po wykryciu zmian w plikach. *Wymaga restartu serwera",
   "LabelSettingsEnableWatcher": "Enable Watcher",
   "LabelSettingsEnableWatcherForLibrary": "Enable folder watcher for library",
   "LabelSettingsEnableWatcherHelp": "Enables the automatic adding/updating of items when file changes are detected. *Requires server restart",
+  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
+  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
   "LabelSettingsExperimentalFeatures": "Funkcje eksperymentalne",
   "LabelSettingsExperimentalFeaturesHelp": "Funkcje w trakcie rozwoju, które mogą zyskanć na Twojej opinii i pomocy w testowaniu. Kliknij, aby otworzyć dyskusję na githubie.",
   "LabelSettingsFindCovers": "Szukanie okładek",
   "LabelSettingsFindCoversHelp": "Jeśli audiobook nie posiada zintegrowanej okładki albo w folderze nie zostanie znaleziony plik okładki, skaner podejmie próbę pobrania okładki z sieci. <br>Uwaga: może to wydłuzyć proces skanowania",
   "LabelSettingsHideSingleBookSeries": "Hide single book series",
diff --git a/client/strings/pt-br.json b/client/strings/pt-br.json
index 4e2368510..f88f6a5e7 100644
--- a/client/strings/pt-br.json
+++ b/client/strings/pt-br.json
@@ -469,10 +469,12 @@
   "LabelSettingsDisableWatcherForLibrary": "Desativa o monitoramento de pastas para a biblioteca",
   "LabelSettingsDisableWatcherHelp": "Desativa o acréscimo/atualização de itens quando forem detectadas mudanças no arquivo. *Requer reiniciar o servidor",
   "LabelSettingsEnableWatcher": "Ativar Monitoramento",
   "LabelSettingsEnableWatcherForLibrary": "Ativa o monitoramento de pastas para a biblioteca",
   "LabelSettingsEnableWatcherHelp": "Ativa o acréscimo/atualização de itens quando forem detectadas mudanças no arquivo. *Requer reiniciar o servidor",
+  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
+  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
   "LabelSettingsExperimentalFeatures": "Funcionalidade experimentais",
   "LabelSettingsExperimentalFeaturesHelp": "Funcionalidade em desenvolvimento que se beneficiairam dos seus comentários e da sua ajuda para testar. Clique para abrir a discussão no github.",
   "LabelSettingsFindCovers": "Localizar capas",
   "LabelSettingsFindCoversHelp": "Se o seu audiobook não tiver uma capa incluída ou uma imagem de capa na pasta, o verificador tentará localizar uma capa.<br>Atenção: Isso irá estender o tempo de análise",
   "LabelSettingsHideSingleBookSeries": "Ocultar séries com um só livro",
diff --git a/client/strings/ru.json b/client/strings/ru.json
index 243d96a09..7b6e9c7c1 100644
--- a/client/strings/ru.json
+++ b/client/strings/ru.json
@@ -469,10 +469,12 @@
   "LabelSettingsDisableWatcherForLibrary": "Отключить отслеживание для библиотеки",
   "LabelSettingsDisableWatcherHelp": "Отключает автоматическое добавление/обновление элементов, когда обнаружено изменение файлов. *Требуется перезапуск сервера",
   "LabelSettingsEnableWatcher": "Включить отслеживание",
   "LabelSettingsEnableWatcherForLibrary": "Включить отслеживание за папками библиотеки",
   "LabelSettingsEnableWatcherHelp": "Включает автоматическое добавление/обновление элементов при обнаружении изменений файлов. *Требуется перезапуск сервера",
+  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
+  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
   "LabelSettingsExperimentalFeatures": "Экспериментальные функции",
   "LabelSettingsExperimentalFeaturesHelp": "Функционал в разработке на который Вы могли бы дать отзыв или помочь в тестировании. Нажмите для открытия обсуждения на github.",
   "LabelSettingsFindCovers": "Найти обложки",
   "LabelSettingsFindCoversHelp": "Если у Ваших аудиокниг нет встроенной обложки или файла обложки в папке книги, то сканер попробует найти обложку.<br>Примечание: Это увеличит время сканирования",
   "LabelSettingsHideSingleBookSeries": "Скрыть серии с одной книгой",
diff --git a/client/strings/sv.json b/client/strings/sv.json
index dbff38750..fd8c6e692 100644
--- a/client/strings/sv.json
+++ b/client/strings/sv.json
@@ -469,10 +469,12 @@
   "LabelSettingsDisableWatcherForLibrary": "Inaktivera mappbevakning för bibliotek",
   "LabelSettingsDisableWatcherHelp": "Inaktiverar automatiskt lägga till/uppdatera objekt när filändringar upptäcks. *Kräver omstart av servern",
   "LabelSettingsEnableWatcher": "Aktivera Watcher",
   "LabelSettingsEnableWatcherForLibrary": "Aktivera mappbevakning för bibliotek",
   "LabelSettingsEnableWatcherHelp": "Aktiverar automatiskt lägga till/uppdatera objekt när filändringar upptäcks. *Kräver omstart av servern",
+  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
+  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
   "LabelSettingsExperimentalFeatures": "Experimentella funktioner",
   "LabelSettingsExperimentalFeaturesHelp": "Funktioner under utveckling som behöver din feedback och hjälp med testning. Klicka för att öppna diskussionen på GitHub.",
   "LabelSettingsFindCovers": "Hitta omslag",
   "LabelSettingsFindCoversHelp": "Om din ljudbok inte har ett inbäddat omslag eller en omslagsbild i mappen kommer skannern att försöka hitta ett omslag.<br>Observera: Detta kommer att förlänga skannningstiden",
   "LabelSettingsHideSingleBookSeries": "Dölj enboksserier",
diff --git a/client/strings/uk.json b/client/strings/uk.json
index e32ac69e0..6d8c311ca 100644
--- a/client/strings/uk.json
+++ b/client/strings/uk.json
@@ -469,10 +469,12 @@
   "LabelSettingsDisableWatcherForLibrary": "Вимкнути спостерігання тек бібліотеки",
   "LabelSettingsDisableWatcherHelp": "Вимикає автоматичне додавання/оновлення елементів, коли спостерігаються зміни файлів. *Потребує перезавантаження сервера",
   "LabelSettingsEnableWatcher": "Увімкнути спостерігача",
   "LabelSettingsEnableWatcherForLibrary": "Увімкнути спостерігання тек бібліотеки",
   "LabelSettingsEnableWatcherHelp": "Вмикає автоматичне додавання/оновлення елементів, коли спостерігаються зміни файлів. *Потребує перезавантаження сервера",
+  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
+  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
   "LabelSettingsExperimentalFeatures": "Експериментальні функції",
   "LabelSettingsExperimentalFeaturesHelp": "Функції в розробці, які потребують вашого відгуку та допомоги в тестуванні. Натисніть, щоб відкрити обговорення на Github.",
   "LabelSettingsFindCovers": "Пошук обкладинок",
   "LabelSettingsFindCoversHelp": "Якщо ваша аудіокнига не містить вбудованої обкладинки або зображення у теці, сканувальник спробує знайти обкладинку.<br>Примітка: Це збільшить час сканування",
   "LabelSettingsHideSingleBookSeries": "Сховати серії з однією книгою",
diff --git a/client/strings/vi-vn.json b/client/strings/vi-vn.json
index e3e5fa313..7c6d09b05 100644
--- a/client/strings/vi-vn.json
+++ b/client/strings/vi-vn.json
@@ -469,10 +469,12 @@
   "LabelSettingsDisableWatcherForLibrary": "Tắt watcher thư mục cho thư viện",
   "LabelSettingsDisableWatcherHelp": "Tắt chức năng tự động thêm/cập nhật các mục khi phát hiện thay đổi tập tin. *Yêu cầu khởi động lại máy chủ",
   "LabelSettingsEnableWatcher": "Bật Watcher",
   "LabelSettingsEnableWatcherForLibrary": "Bật watcher thư mục cho thư viện",
   "LabelSettingsEnableWatcherHelp": "Bật chức năng tự động thêm/cập nhật các mục khi phát hiện thay đổi tập tin. *Yêu cầu khởi động lại máy chủ",
+  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
+  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
   "LabelSettingsExperimentalFeatures": "Tính năng thử nghiệm",
   "LabelSettingsExperimentalFeaturesHelp": "Các tính năng đang phát triển có thể cần phản hồi của bạn và sự giúp đỡ trong thử nghiệm. Nhấp để mở thảo luận trên github.",
   "LabelSettingsFindCovers": "Tìm ảnh bìa",
   "LabelSettingsFindCoversHelp": "Nếu sách nói của bạn không có ảnh bìa nhúng hoặc ảnh bìa trong thư mục, trình quét sẽ cố gắng tìm ảnh bìa.<br>Lưu ý: Điều này sẽ kéo dài thời gian quét",
   "LabelSettingsHideSingleBookSeries": "Ẩn loạt sách đơn lẻ",
diff --git a/client/strings/zh-cn.json b/client/strings/zh-cn.json
index 654411fe4..fb375aec1 100644
--- a/client/strings/zh-cn.json
+++ b/client/strings/zh-cn.json
@@ -469,10 +469,12 @@
   "LabelSettingsDisableWatcherForLibrary": "禁用媒体库的文件夹监视程序",
   "LabelSettingsDisableWatcherHelp": "检测到文件更改时禁用自动添加和更新项目. *需要重启服务器",
   "LabelSettingsEnableWatcher": "启用监视程序",
   "LabelSettingsEnableWatcherForLibrary": "为库启用文件夹监视程序",
   "LabelSettingsEnableWatcherHelp": "当检测到文件更改时, 启用项目的自动添加/更新. *需要重新启动服务器",
+  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
+  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
   "LabelSettingsExperimentalFeatures": "实验功能",
   "LabelSettingsExperimentalFeaturesHelp": "开发中的功能需要你的反馈并帮助测试. 点击打开 github 讨论.",
   "LabelSettingsFindCovers": "查找封面",
   "LabelSettingsFindCoversHelp": "如果你的有声读物在文件夹中没有嵌入封面或封面图像, 扫描将尝试查找封面.<br>注意: 这将延长扫描时间",
   "LabelSettingsHideSingleBookSeries": "隐藏单书系列",
diff --git a/client/strings/zh-tw.json b/client/strings/zh-tw.json
index bf3a625b7..54e7849b4 100644
--- a/client/strings/zh-tw.json
+++ b/client/strings/zh-tw.json
@@ -469,10 +469,12 @@
   "LabelSettingsDisableWatcherForLibrary": "禁用媒體庫的資料夾監視程序",
   "LabelSettingsDisableWatcherHelp": "檢測到檔案更改時禁用自動新增和更新項目. *需要重啟伺服器",
   "LabelSettingsEnableWatcher": "啟用監視程序",
   "LabelSettingsEnableWatcherForLibrary": "為庫啟用資料夾監視程序",
   "LabelSettingsEnableWatcherHelp": "當檢測到檔案更改時, 啟用項目的自動新增/更新. *需要重新啟動伺服器",
+  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
+  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
   "LabelSettingsExperimentalFeatures": "實驗功能",
   "LabelSettingsExperimentalFeaturesHelp": "開發中的功能需要你的反饋並幫助測試. 點擊打開 github 討論.",
   "LabelSettingsFindCovers": "查找封面",
   "LabelSettingsFindCoversHelp": "如果你的有聲書在資料夾中沒有嵌入封面或封面圖像, 掃描將嘗試查找封面.<br>注意: 這將延長掃描時間",
   "LabelSettingsHideSingleBookSeries": "隱藏單書系列",
diff --git a/server/objects/settings/LibrarySettings.js b/server/objects/settings/LibrarySettings.js
index a9885c791..4369c0ff5 100644
--- a/server/objects/settings/LibrarySettings.js
+++ b/server/objects/settings/LibrarySettings.js
@@ -6,10 +6,11 @@ class LibrarySettings {
     this.disableWatcher = false
     this.skipMatchingMediaWithAsin = false
     this.skipMatchingMediaWithIsbn = false
     this.autoScanCronExpression = null
     this.audiobooksOnly = false
+    this.epubsAllowScriptedContent = false
     this.hideSingleBookSeries = false // Do not show series that only have 1 book
     this.onlyShowLaterBooksInContinueSeries = false // Skip showing books that are earlier than the max sequence read
     this.metadataPrecedence = ['folderStructure', 'audioMetatags', 'nfoFile', 'txtFiles', 'opfFile', 'absMetadata']
     this.podcastSearchRegion = 'us'
 
@@ -23,10 +24,11 @@ class LibrarySettings {
     this.disableWatcher = !!settings.disableWatcher
     this.skipMatchingMediaWithAsin = !!settings.skipMatchingMediaWithAsin
     this.skipMatchingMediaWithIsbn = !!settings.skipMatchingMediaWithIsbn
     this.autoScanCronExpression = settings.autoScanCronExpression || null
     this.audiobooksOnly = !!settings.audiobooksOnly
+    this.epubsAllowScriptedContent = !!settings.epubsAllowScriptedContent
     this.hideSingleBookSeries = !!settings.hideSingleBookSeries
     this.onlyShowLaterBooksInContinueSeries = !!settings.onlyShowLaterBooksInContinueSeries
     if (settings.metadataPrecedence) {
       this.metadataPrecedence = [...settings.metadataPrecedence]
     } else {
@@ -42,10 +44,11 @@ class LibrarySettings {
       disableWatcher: this.disableWatcher,
       skipMatchingMediaWithAsin: this.skipMatchingMediaWithAsin,
       skipMatchingMediaWithIsbn: this.skipMatchingMediaWithIsbn,
       autoScanCronExpression: this.autoScanCronExpression,
       audiobooksOnly: this.audiobooksOnly,
+      epubsAllowScriptedContent: this.epubsAllowScriptedContent,
       hideSingleBookSeries: this.hideSingleBookSeries,
       onlyShowLaterBooksInContinueSeries: this.onlyShowLaterBooksInContinueSeries,
       metadataPrecedence: [...this.metadataPrecedence],
       podcastSearchRegion: this.podcastSearchRegion
     }
@@ -65,6 +68,6 @@ class LibrarySettings {
       }
     }
     return hasUpdates
   }
 }
-module.exports = LibrarySettings
\ No newline at end of file
+module.exports = LibrarySettings

Vulnerable code: </script>
        allowScriptedContent: true,
  getCurrentLibrary: state => {
    return state.libraries.find(lib => lib.id === state.currentLibraryId)
  getSortedLibraries: state => () => {
    return state.libraries.map(lib => ({ ...lib })).sort((a, b) => a.displayOrder - b.displayOrder)
  getLibraryProvider: state => libraryId => {
    var library = state.libraries.find(l => l.id === libraryId)
  getCollection: state => id => {
    return state.collections.find(c => c.id === id)
  getPlaylist: state => id => {
    return state.userPlaylists.find(p => p.id === id)
      if (lastCheck < 1000 * 5) { // 5 seconds
    var index = state.libraries.findIndex(a => a.id === library.id)
    state.libraries = state.libraries.filter(a => a.id !== library.id)
    var index = state.listeners.findIndex(l => l.id === listener.id)
    state.listeners = state.listeners.filter(l => l.id !== listenerId)
    state.filterData.series = state.filterData.series.filter(se => se.id !== seriesId)
        const indexOf = state.filterData.authors.findIndex(au => au.id === author.id)
          state.filterData.authors.sort((a, b) => (a.name || '').localeCompare((b.name || '')))
        const indexOf = state.filterData.series.findIndex(se => se.id === series.id)
          state.filterData.series.sort((a, b) => (a.name || '').localeCompare((b.name || '')))
    var index = state.collections.findIndex(c => c.id === collection.id)
    state.collections = state.collections.filter(c => c.id !== collection.id)
    const index = state.userPlaylists.findIndex(p => p.id === playlist.id)
    state.userPlaylists = state.userPlaylists.filter(p => p.id !== playlist.id)
}
module.exports = LibrarySettings
Fixed code:     <div v-if="isBookLibrary" class="py-3">
      <div class="flex items-center">
        <ui-toggle-switch v-model="epubsAllowScriptedContent" @input="formUpdated" />
        <ui-tooltip :text="$strings.LabelSettingsEpubsAllowScriptedContentHelp">
          <p class="pl-4 text-base">
            {{ $strings.LabelSettingsEpubsAllowScriptedContent }}
            <span class="material-icons icon-text text-sm">info_outlined</span>
          </p>
        </ui-tooltip>
      </div>
    </div>
      epubsAllowScriptedContent: false,
          epubsAllowScriptedContent: !!this.epubsAllowScriptedContent,
      this.epubsAllowScriptedContent = !!this.librarySettings.epubsAllowScriptedContent
</script>
    allowScriptedContent() {
      return this.$store.getters['libraries/getLibraryEpubsAllowScriptedContent']
    },
        allowScriptedContent: this.allowScriptedContent,
  getCurrentLibrary: (state) => {
    return state.libraries.find((lib) => lib.id === state.currentLibraryId)
  getSortedLibraries: (state) => () => {
    return state.libraries.map((lib) => ({ ...lib })).sort((a, b) => a.displayOrder - b.displayOrder)
  getLibraryProvider: (state) => (libraryId) => {
    var library = state.libraries.find((l) => l.id === libraryId)
  getLibraryEpubsAllowScriptedContent: (state, getters) => {
    return !!getters.getCurrentLibrarySettings?.epubsAllowScriptedContent
  getCollection: (state) => (id) => {
    return state.collections.find((c) => c.id === id)
  },
  getPlaylist: (state) => (id) => {
    return state.userPlaylists.find((p) => p.id === id)
      if (lastCheck < 1000 * 5) {
        // 5 seconds
    var index = state.libraries.findIndex((a) => a.id === library.id)
    state.libraries = state.libraries.filter((a) => a.id !== library.id)
    var index = state.listeners.findIndex((l) => l.id === listener.id)
    state.listeners = state.listeners.filter((l) => l.id !== listenerId)
    state.filterData.series = state.filterData.series.filter((se) => se.id !== seriesId)
        const indexOf = state.filterData.authors.findIndex((au) => au.id === author.id)
          state.filterData.authors.sort((a, b) => (a.name || '').localeCompare(b.name || ''))
        const indexOf = state.filterData.series.findIndex((se) => se.id === series.id)
          state.filterData.series.sort((a, b) => (a.name || '').localeCompare(b.name || ''))
    var index = state.collections.findIndex((c) => c.id === collection.id)
    state.collections = state.collections.filter((c) => c.id !== collection.id)
    const index = state.userPlaylists.findIndex((p) => p.id === playlist.id)
    state.userPlaylists = state.userPlaylists.filter((p) => p.id !== playlist.id)
}
  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
  "LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
  "LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
    this.epubsAllowScriptedContent = false
    this.epubsAllowScriptedContent = !!settings.epubsAllowScriptedContent
      epubsAllowScriptedContent: this.epubsAllowScriptedContent,
module.exports = LibrarySettings