From 6f8ba8fd69971dda6df99d24b5f7087fb78664e2 Mon Sep 17 00:00:00 2001 From: 10sa Date: Fri, 19 May 2023 21:39:48 +0900 Subject: [PATCH 1/5] Add security override config --- config.conf | 6 ++++++ server.js | 8 ++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/config.conf b/config.conf index 452636cca..b6f7dcb62 100644 --- a/config.conf +++ b/config.conf @@ -10,6 +10,11 @@ const enableExtensions = true; //Enables support for TavernAI-extras project const listen = true; // If true, Can be access from other device or PC. otherwise can be access only from hosting machine. const allowKeysExposure = false; // If true, private API keys could be fetched to the frontend. + +// If true, Allows insecure settings for listen, whitelist, and authentication. +// Change this setting only on "trusted networks". Do not change this value unless you are aware of the issues that can arise from changing this setting and configuring a insecure setting. +const securityOverride = false; + module.exports = { port, whitelist, @@ -21,4 +26,5 @@ module.exports = { listen, disableThumbnails, allowKeysExposure, + securityOverride, }; diff --git a/server.js b/server.js index f30b3714f..9f3f606dc 100644 --- a/server.js +++ b/server.js @@ -2715,8 +2715,12 @@ const setupTasks = async function () { } if (listen && !config.whitelistMode && !config.basicAuthMode) { - console.error('Your SillyTavern is currently unsecurely open to the public. Enable whitelisting or basic authentication.'); - process.exit(1); + if (config.securityOverride) + console.warn("Security has been override. If it's not a trusted network, change the settings."); + else { + console.error('Your SillyTavern is currently unsecurely open to the public. Enable whitelisting or basic authentication.'); + process.exit(1); + } } if (true === cliArguments.ssl) From 102a7eb6b7d5802052dcd308ddc05f15a4ca3dc7 Mon Sep 17 00:00:00 2001 From: 10sa Date: Fri, 19 May 2023 22:18:56 +0900 Subject: [PATCH 2/5] Refactoring character card scripts --- server.js | 58 ++--------------------------- src/character-card-parser.js | 72 ++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 55 deletions(-) create mode 100644 src/character-card-parser.js diff --git a/server.js b/server.js index 9f3f606dc..9505beda2 100644 --- a/server.js +++ b/server.js @@ -60,6 +60,8 @@ const utf8Encode = new TextEncoder(); const utf8Decode = new TextDecoder('utf-8', { ignoreBOM: true }); const commandExistsSync = require('command-exists').sync; +const characterCardParser = require('./src/character-card-parser.js'); + const config = require(path.join(__dirname, './config.conf')); const server_port = process.env.SILLY_TAVERN_PORT || config.port; @@ -892,61 +894,7 @@ async function charaWrite(img_url, data, target_img, response = undefined, mes = } async function charaRead(img_url, input_format) { - let format; - if (input_format === undefined) { - if (img_url.indexOf('.webp') !== -1) { - format = 'webp'; - } else { - format = 'png'; - } - } else { - format = input_format; - } - - switch (format) { - case 'webp': - try { - const exif_data = await ExifReader.load(fs.readFileSync(img_url)); - let char_data; - - if (exif_data['UserComment']['description']) { - let description = exif_data['UserComment']['description']; - if (description === 'Undefined' && exif_data['UserComment'].value && exif_data['UserComment'].value.length === 1) { - description = exif_data['UserComment'].value[0]; - } - try { - json5.parse(description); - char_data = description; - } catch { - const byteArr = description.split(",").map(Number); - const uint8Array = new Uint8Array(byteArr); - const char_data_string = utf8Decode.decode(uint8Array); - char_data = char_data_string; - } - } else { - console.log('No description found in EXIF data.'); - return false; - } - return char_data; - } - catch (err) { - console.log(err); - return false; - } - case 'png': - const buffer = fs.readFileSync(img_url); - const chunks = extract(buffer); - - const textChunks = chunks.filter(function (chunk) { - return chunk.name === 'tEXt'; - }).map(function (chunk) { - return PNGtext.decode(chunk.data); - }); - var base64DecodedData = Buffer.from(textChunks[0].text, 'base64').toString('utf8'); - return base64DecodedData;//textChunks[0].text; - default: - break; - } + return characterCardParser.parse(img_url, input_format); } app.post("/getcharacters", jsonParser, function (request, response) { diff --git a/src/character-card-parser.js b/src/character-card-parser.js new file mode 100644 index 000000000..9b66d9869 --- /dev/null +++ b/src/character-card-parser.js @@ -0,0 +1,72 @@ +const fs = require('fs'); +const json5 = require('json5'); +const ExifReader = require('exifreader'); + +const extract = require('png-chunks-extract'); +const PNGtext = require('png-chunk-text'); + +const utf8Decode = new TextDecoder('utf-8', { ignoreBOM: true }); + +const parse = async (cardUrl, format) => { + let fileFormat; + if (format === undefined) { + if (cardUrl.indexOf('.webp') !== -1) + fileFormat = 'webp'; + else + fileFormat = 'png'; + } + else + fileFormat = format; + + switch (fileFormat) { + case 'webp': + try { + const exif_data = await ExifReader.load(fs.readFileSync(cardUrl)); + let char_data; + + if (exif_data['UserComment']['description']) { + let description = exif_data['UserComment']['description']; + if (description === 'Undefined' && exif_data['UserComment'].value && exif_data['UserComment'].value.length === 1) { + description = exif_data['UserComment'].value[0]; + } + + try { + json5.parse(description); + char_data = description; + } catch { + const byteArr = description.split(",").map(Number); + const uint8Array = new Uint8Array(byteArr); + const char_data_string = utf8Decode.decode(uint8Array); + char_data = char_data_string; + } + } + else { + console.log('No description found in EXIF data.'); + return false; + } + + return char_data; + } + catch (err) { + console.log(err); + return false; + } + case 'png': + const buffer = fs.readFileSync(cardUrl); + const chunks = extract(buffer); + + const textChunks = chunks.filter(function (chunk) { + return chunk.name === 'tEXt'; + }).map(function (chunk) { + return PNGtext.decode(chunk.data); + }); + + return Buffer.from(textChunks[0].text, 'base64').toString('utf8'); + default: + break; + } +}; + +module.exports = { + parse: parse +}; \ No newline at end of file From 211649798aa6fc3f11a7c8b6683321e624931344 Mon Sep 17 00:00:00 2001 From: 10sa Date: Fri, 19 May 2023 22:30:49 +0900 Subject: [PATCH 3/5] Create .editorconfig --- .editorconfig | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..1e80dbbf5 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.{js, conf, json}] +charset = utf-8 +indent_style = tab +indent_size = 4 \ No newline at end of file From 30e931454a42966b84dd5c2f7d351cda57b93d49 Mon Sep 17 00:00:00 2001 From: 10sa Date: Fri, 19 May 2023 22:38:12 +0900 Subject: [PATCH 4/5] Change tab indent to space indent --- .editorconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.editorconfig b/.editorconfig index 1e80dbbf5..2a13caebf 100644 --- a/.editorconfig +++ b/.editorconfig @@ -7,5 +7,5 @@ trim_trailing_whitespace = true [*.{js, conf, json}] charset = utf-8 -indent_style = tab +indent_style = space indent_size = 4 \ No newline at end of file From 905db6a4e8f1d9584e17549f9271e6fd8babeb45 Mon Sep 17 00:00:00 2001 From: 10sa Date: Fri, 19 May 2023 22:48:48 +0900 Subject: [PATCH 5/5] Reformat codes --- src/character-card-parser.js | 116 +++++++++++++++++------------------ 1 file changed, 58 insertions(+), 58 deletions(-) diff --git a/src/character-card-parser.js b/src/character-card-parser.js index 9b66d9869..e97a66bf0 100644 --- a/src/character-card-parser.js +++ b/src/character-card-parser.js @@ -8,65 +8,65 @@ const PNGtext = require('png-chunk-text'); const utf8Decode = new TextDecoder('utf-8', { ignoreBOM: true }); const parse = async (cardUrl, format) => { - let fileFormat; - if (format === undefined) { - if (cardUrl.indexOf('.webp') !== -1) - fileFormat = 'webp'; - else - fileFormat = 'png'; - } - else - fileFormat = format; - - switch (fileFormat) { - case 'webp': - try { - const exif_data = await ExifReader.load(fs.readFileSync(cardUrl)); - let char_data; - - if (exif_data['UserComment']['description']) { - let description = exif_data['UserComment']['description']; - if (description === 'Undefined' && exif_data['UserComment'].value && exif_data['UserComment'].value.length === 1) { - description = exif_data['UserComment'].value[0]; - } - - try { - json5.parse(description); - char_data = description; - } catch { - const byteArr = description.split(",").map(Number); - const uint8Array = new Uint8Array(byteArr); - const char_data_string = utf8Decode.decode(uint8Array); - char_data = char_data_string; - } - } - else { - console.log('No description found in EXIF data.'); - return false; - } - - return char_data; - } - catch (err) { - console.log(err); - return false; - } - case 'png': - const buffer = fs.readFileSync(cardUrl); - const chunks = extract(buffer); - - const textChunks = chunks.filter(function (chunk) { - return chunk.name === 'tEXt'; - }).map(function (chunk) { - return PNGtext.decode(chunk.data); - }); - - return Buffer.from(textChunks[0].text, 'base64').toString('utf8'); - default: - break; + let fileFormat; + if (format === undefined) { + if (cardUrl.indexOf('.webp') !== -1) + fileFormat = 'webp'; + else + fileFormat = 'png'; + } + else + fileFormat = format; + + switch (fileFormat) { + case 'webp': + try { + const exif_data = await ExifReader.load(fs.readFileSync(cardUrl)); + let char_data; + + if (exif_data['UserComment']['description']) { + let description = exif_data['UserComment']['description']; + if (description === 'Undefined' && exif_data['UserComment'].value && exif_data['UserComment'].value.length === 1) { + description = exif_data['UserComment'].value[0]; + } + + try { + json5.parse(description); + char_data = description; + } catch { + const byteArr = description.split(",").map(Number); + const uint8Array = new Uint8Array(byteArr); + const char_data_string = utf8Decode.decode(uint8Array); + char_data = char_data_string; + } + } + else { + console.log('No description found in EXIF data.'); + return false; + } + + return char_data; + } + catch (err) { + console.log(err); + return false; + } + case 'png': + const buffer = fs.readFileSync(cardUrl); + const chunks = extract(buffer); + + const textChunks = chunks.filter(function (chunk) { + return chunk.name === 'tEXt'; + }).map(function (chunk) { + return PNGtext.decode(chunk.data); + }); + + return Buffer.from(textChunks[0].text, 'base64').toString('utf8'); + default: + break; } }; module.exports = { - parse: parse -}; \ No newline at end of file + parse: parse +};