From fb5dbfc52a2fcc5ebee3da39d43f13f4533e220a Mon Sep 17 00:00:00 2001 From: Kasen IO Date: Sun, 5 Jan 2020 23:32:28 -0500 Subject: [PATCH 1/7] Disable whitelist on entity_server scripts. --- libraries/script-engine/src/ScriptEngine.cpp | 24 ++++++++++++-------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 482bde9fd4..6a6b1e8417 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -2377,15 +2377,21 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co // END PULL SAFEURLS FROM INTERFACE.JSON Settings bool isInWhitelist = false; // assume unsafe - for (const auto& str : safeURLS) { - qCDebug(scriptengine) << whitelistPrefix << "Script URL: " << scriptOrURL << "TESTING AGAINST" << str << "RESULTS IN" - << scriptOrURL.startsWith(str); - if (!str.isEmpty() && scriptOrURL.startsWith(str)) { - isInWhitelist = true; - qCDebug(scriptengine) << whitelistPrefix << "Script approved."; - break; // bail early since we found a match - } - } + + if(ScriptEngine::getContext() == "entity_server") { + isInWhitelist = true; + } else { + for (const auto& str : safeURLS) { + qCDebug(scriptengine) << whitelistPrefix << "Script URL: " << scriptOrURL << "TESTING AGAINST" << str << "RESULTS IN" + << scriptOrURL.startsWith(str); + if (!str.isEmpty() && scriptOrURL.startsWith(str)) { + isInWhitelist = true; + qCDebug(scriptengine) << whitelistPrefix << "Script approved."; + break; // bail early since we found a match + } + } + } + if (!isInWhitelist) { qCDebug(scriptengine) << whitelistPrefix << "(disabled entity script)" << entityID.toString() << scriptOrURL; exception = makeError("UNSAFE_ENTITY_SCRIPTS == 0"); From 8124b7d4a14055b89fbb39ab8ac14b925bbcbce2 Mon Sep 17 00:00:00 2001 From: Kasen IO Date: Mon, 6 Jan 2020 08:29:01 -0500 Subject: [PATCH 2/7] Fixed tabs and spaces. --- libraries/script-engine/src/ScriptEngine.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 6a6b1e8417..589e88c394 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -2363,7 +2363,7 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co } } else { - // ENTITY SCRIPT WHITELIST STARTS HERE + // ENTITY SCRIPT WHITELIST STARTS HERE QString whitelistPrefix = "[WHITELIST ENTITY SCRIPTS]"; QList safeURLS = { "" }; safeURLS += qEnvironmentVariable("EXTRA_WHITELIST").trimmed().split(QRegExp("\\s*,\\s*"), QString::SkipEmptyParts); @@ -2378,16 +2378,16 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co bool isInWhitelist = false; // assume unsafe - if(ScriptEngine::getContext() == "entity_server") { + if (ScriptEngine::getContext() == "entity_server") { isInWhitelist = true; } else { for (const auto& str : safeURLS) { qCDebug(scriptengine) << whitelistPrefix << "Script URL: " << scriptOrURL << "TESTING AGAINST" << str << "RESULTS IN" - << scriptOrURL.startsWith(str); + << scriptOrURL.startsWith(str); if (!str.isEmpty() && scriptOrURL.startsWith(str)) { isInWhitelist = true; qCDebug(scriptengine) << whitelistPrefix << "Script approved."; - break; // bail early since we found a match + break; // bail early since we found a match } } } From 20f5439fa89dfe14a381283de3005fd1743c3b99 Mon Sep 17 00:00:00 2001 From: Kasen IO Date: Mon, 6 Jan 2020 08:58:09 -0500 Subject: [PATCH 3/7] Hard tabs converted to 4 length soft tabs. --- libraries/script-engine/src/ScriptEngine.cpp | 28 ++++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 589e88c394..1e46e55eff 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -2377,20 +2377,20 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co // END PULL SAFEURLS FROM INTERFACE.JSON Settings bool isInWhitelist = false; // assume unsafe - - if (ScriptEngine::getContext() == "entity_server") { - isInWhitelist = true; - } else { - for (const auto& str : safeURLS) { - qCDebug(scriptengine) << whitelistPrefix << "Script URL: " << scriptOrURL << "TESTING AGAINST" << str << "RESULTS IN" - << scriptOrURL.startsWith(str); - if (!str.isEmpty() && scriptOrURL.startsWith(str)) { - isInWhitelist = true; - qCDebug(scriptengine) << whitelistPrefix << "Script approved."; - break; // bail early since we found a match - } - } - } + + if (ScriptEngine::getContext() == "entity_server") { + isInWhitelist = true; + } else { + for (const auto& str : safeURLS) { + qCDebug(scriptengine) << whitelistPrefix << "Script URL: " << scriptOrURL << "TESTING AGAINST" << str << "RESULTS IN" + << scriptOrURL.startsWith(str); + if (!str.isEmpty() && scriptOrURL.startsWith(str)) { + isInWhitelist = true; + qCDebug(scriptengine) << whitelistPrefix << "Script approved."; + break; // bail early since we found a match + } + } + } if (!isInWhitelist) { qCDebug(scriptengine) << whitelistPrefix << "(disabled entity script)" << entityID.toString() << scriptOrURL; From d87cd0112916b402740464d8d87a2a358379ff78 Mon Sep 17 00:00:00 2001 From: Kasen IO Date: Tue, 7 Jan 2020 03:03:08 -0500 Subject: [PATCH 4/7] Adds major QOL updates to whitelist --- libraries/script-engine/src/ScriptEngine.cpp | 34 ++++++++++++++++---- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 1e46e55eff..f4438f3c7b 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -85,9 +85,7 @@ #include "MIDIEvent.h" #include "SettingHandle.h" -// #include "SettingManager.h" -// #include "SettingInterface.h" -// #include "SettingHelpers.h" +#include const QString ScriptEngine::_SETTINGS_ENABLE_EXTENDED_EXCEPTIONS { "com.highfidelity.experimental.enableExtendedJSExceptions" @@ -2364,10 +2362,18 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co } else { // ENTITY SCRIPT WHITELIST STARTS HERE + auto nodeList = DependencyManager::get(); + bool isInWhitelist = false; // assume unsafe + bool autoPassList = false; QString whitelistPrefix = "[WHITELIST ENTITY SCRIPTS]"; - QList safeURLS = { "" }; + QList safeURLS = { "file:///", "atp:", "cache:" }; safeURLS += qEnvironmentVariable("EXTRA_WHITELIST").trimmed().split(QRegExp("\\s*,\\s*"), QString::SkipEmptyParts); + // IF WHITELIST IS DISABLED IN SETTINGS + bool whitelistEnabled = Setting::Handle("private/whitelistEnabled", true).get(); + if (!whitelistEnabled) { + autoPassList = true; + } // PULL SAFEURLS FROM INTERFACE.JSON Settings QVariant raw = Setting::Handle("private/settingsSafeURLS").get(); @@ -2376,9 +2382,23 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co // END PULL SAFEURLS FROM INTERFACE.JSON Settings - bool isInWhitelist = false; // assume unsafe + // GET CURRENT DOMAIN WHITELIST BYPASS, IN CASE AN ENTIRE DOMAIN IS WHITELISTED + QString currentDomain = DependencyManager::get()->getDomainURL().host(); + + QString domainSafeIP = nodeList->getDomainHandler().getHostname(); + QString domainSafeURL = "hifi://" + currentDomain; + for (const auto& str : safeURLS) { + if(domainSafeURL.startsWith(str) || domainSafeIP.startsWith(str)) { + qCDebug(scriptengine) << whitelistPrefix << "Whitelist Bypassed. Current Domain Host: " + << nodeList->getDomainHandler().getHostname() + << "Current Domain: " << currentDomain; + isInWhitelist = true; + autoPassList = true; + } + } + // END CURRENT DOMAIN WHITELIST BYPASS - if (ScriptEngine::getContext() == "entity_server") { + if (ScriptEngine::getContext() == "entity_server" || autoPassList == true) { // If running on the server or waved through, do not engage whitelist. isInWhitelist = true; } else { for (const auto& str : safeURLS) { @@ -2392,7 +2412,7 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co } } - if (!isInWhitelist) { + if (!isInWhitelist || autoPassList == false) { qCDebug(scriptengine) << whitelistPrefix << "(disabled entity script)" << entityID.toString() << scriptOrURL; exception = makeError("UNSAFE_ENTITY_SCRIPTS == 0"); } else { From 13d79fec8b23153671b0d7ea4a77c2714ea753cd Mon Sep 17 00:00:00 2001 From: Kasen IO Date: Tue, 7 Jan 2020 13:04:28 -0500 Subject: [PATCH 5/7] Fixes bools and tab. --- libraries/script-engine/src/ScriptEngine.cpp | 23 ++++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index f4438f3c7b..aa96e738f3 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -2361,10 +2361,9 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co } } else { - // ENTITY SCRIPT WHITELIST STARTS HERE + // ENTITY SCRIPT WHITELIST STARTS HERE auto nodeList = DependencyManager::get(); - bool isInWhitelist = false; // assume unsafe - bool autoPassList = false; + bool passList = false; // assume unsafe QString whitelistPrefix = "[WHITELIST ENTITY SCRIPTS]"; QList safeURLS = { "file:///", "atp:", "cache:" }; safeURLS += qEnvironmentVariable("EXTRA_WHITELIST").trimmed().split(QRegExp("\\s*,\\s*"), QString::SkipEmptyParts); @@ -2372,14 +2371,13 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co // IF WHITELIST IS DISABLED IN SETTINGS bool whitelistEnabled = Setting::Handle("private/whitelistEnabled", true).get(); if (!whitelistEnabled) { - autoPassList = true; + passList = true; } - // PULL SAFEURLS FROM INTERFACE.JSON Settings + // PULL SAFEURLS FROM INTERFACE.JSON Settings QVariant raw = Setting::Handle("private/settingsSafeURLS").get(); QStringList settingsSafeURLS = raw.toString().trimmed().split(QRegExp("\\s*[,\r\n]+\\s*"), QString::SkipEmptyParts); safeURLS += settingsSafeURLS; - // END PULL SAFEURLS FROM INTERFACE.JSON Settings // GET CURRENT DOMAIN WHITELIST BYPASS, IN CASE AN ENTIRE DOMAIN IS WHITELISTED @@ -2392,27 +2390,28 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co qCDebug(scriptengine) << whitelistPrefix << "Whitelist Bypassed. Current Domain Host: " << nodeList->getDomainHandler().getHostname() << "Current Domain: " << currentDomain; - isInWhitelist = true; - autoPassList = true; + passList = true; } } // END CURRENT DOMAIN WHITELIST BYPASS - if (ScriptEngine::getContext() == "entity_server" || autoPassList == true) { // If running on the server or waved through, do not engage whitelist. - isInWhitelist = true; + // START CHECKING AGAINST THE WHITELIST + if (ScriptEngine::getContext() == "entity_server" || passList == true) { // If running on the server or waved through, do not engage whitelist. + passList = true; } else { for (const auto& str : safeURLS) { qCDebug(scriptengine) << whitelistPrefix << "Script URL: " << scriptOrURL << "TESTING AGAINST" << str << "RESULTS IN" << scriptOrURL.startsWith(str); if (!str.isEmpty() && scriptOrURL.startsWith(str)) { - isInWhitelist = true; + passList = true; qCDebug(scriptengine) << whitelistPrefix << "Script approved."; break; // bail early since we found a match } } } + // END CHECKING AGAINST THE WHITELIST - if (!isInWhitelist || autoPassList == false) { + if (!passList) { // If the entity failed to pass for any reason, it's blocked and an error is thrown. qCDebug(scriptengine) << whitelistPrefix << "(disabled entity script)" << entityID.toString() << scriptOrURL; exception = makeError("UNSAFE_ENTITY_SCRIPTS == 0"); } else { From a6dc494d7ca5bc7af2b58b8226f45e1e254fcf75 Mon Sep 17 00:00:00 2001 From: Kasen IO Date: Tue, 7 Jan 2020 19:40:42 -0500 Subject: [PATCH 6/7] housekeeping --- libraries/script-engine/src/ScriptEngine.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index aa96e738f3..d1daa9923d 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -2386,7 +2386,7 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co QString domainSafeIP = nodeList->getDomainHandler().getHostname(); QString domainSafeURL = "hifi://" + currentDomain; for (const auto& str : safeURLS) { - if(domainSafeURL.startsWith(str) || domainSafeIP.startsWith(str)) { + if (domainSafeURL.startsWith(str) || domainSafeIP.startsWith(str)) { qCDebug(scriptengine) << whitelistPrefix << "Whitelist Bypassed. Current Domain Host: " << nodeList->getDomainHandler().getHostname() << "Current Domain: " << currentDomain; @@ -2396,9 +2396,9 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co // END CURRENT DOMAIN WHITELIST BYPASS // START CHECKING AGAINST THE WHITELIST - if (ScriptEngine::getContext() == "entity_server" || passList == true) { // If running on the server or waved through, do not engage whitelist. + if (ScriptEngine::getContext() == "entity_server") { // If running on the server, do not engage whitelist. passList = true; - } else { + } else if (!passList) { // If waved through, do not engage whitelist. for (const auto& str : safeURLS) { qCDebug(scriptengine) << whitelistPrefix << "Script URL: " << scriptOrURL << "TESTING AGAINST" << str << "RESULTS IN" << scriptOrURL.startsWith(str); From 2c7911acb8044bc00d4bdf93d1f6c423165b5862 Mon Sep 17 00:00:00 2001 From: Kasen IO Date: Thu, 9 Jan 2020 16:15:41 -0500 Subject: [PATCH 7/7] more housekeeping --- libraries/script-engine/src/ScriptEngine.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index d1daa9923d..de7fc488aa 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -86,6 +86,8 @@ #include "SettingHandle.h" #include +#include + const QString ScriptEngine::_SETTINGS_ENABLE_EXTENDED_EXCEPTIONS { "com.highfidelity.experimental.enableExtendedJSExceptions" @@ -2359,14 +2361,13 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co } else if (testConstructor.isError()) { exception = testConstructor; } - } - else { + } else { // ENTITY SCRIPT WHITELIST STARTS HERE auto nodeList = DependencyManager::get(); bool passList = false; // assume unsafe QString whitelistPrefix = "[WHITELIST ENTITY SCRIPTS]"; - QList safeURLS = { "file:///", "atp:", "cache:" }; - safeURLS += qEnvironmentVariable("EXTRA_WHITELIST").trimmed().split(QRegExp("\\s*,\\s*"), QString::SkipEmptyParts); + QList safeURLPrefixes = { "file:///", "atp:", "cache:" }; + safeURLPrefixes += qEnvironmentVariable("EXTRA_WHITELIST").trimmed().split(QRegExp("\\s*,\\s*"), QString::SkipEmptyParts); // IF WHITELIST IS DISABLED IN SETTINGS bool whitelistEnabled = Setting::Handle("private/whitelistEnabled", true).get(); @@ -2377,15 +2378,15 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co // PULL SAFEURLS FROM INTERFACE.JSON Settings QVariant raw = Setting::Handle("private/settingsSafeURLS").get(); QStringList settingsSafeURLS = raw.toString().trimmed().split(QRegExp("\\s*[,\r\n]+\\s*"), QString::SkipEmptyParts); - safeURLS += settingsSafeURLS; + safeURLPrefixes += settingsSafeURLS; // END PULL SAFEURLS FROM INTERFACE.JSON Settings // GET CURRENT DOMAIN WHITELIST BYPASS, IN CASE AN ENTIRE DOMAIN IS WHITELISTED QString currentDomain = DependencyManager::get()->getDomainURL().host(); QString domainSafeIP = nodeList->getDomainHandler().getHostname(); - QString domainSafeURL = "hifi://" + currentDomain; - for (const auto& str : safeURLS) { + QString domainSafeURL = URL_SCHEME_HIFI + "://" + currentDomain; + for (const auto& str : safeURLPrefixes) { if (domainSafeURL.startsWith(str) || domainSafeIP.startsWith(str)) { qCDebug(scriptengine) << whitelistPrefix << "Whitelist Bypassed. Current Domain Host: " << nodeList->getDomainHandler().getHostname() @@ -2399,7 +2400,7 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co if (ScriptEngine::getContext() == "entity_server") { // If running on the server, do not engage whitelist. passList = true; } else if (!passList) { // If waved through, do not engage whitelist. - for (const auto& str : safeURLS) { + for (const auto& str : safeURLPrefixes) { qCDebug(scriptengine) << whitelistPrefix << "Script URL: " << scriptOrURL << "TESTING AGAINST" << str << "RESULTS IN" << scriptOrURL.startsWith(str); if (!str.isEmpty() && scriptOrURL.startsWith(str)) {