diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 482bde9fd4..de7fc488aa 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -85,9 +85,9 @@ #include "MIDIEvent.h" #include "SettingHandle.h" -// #include "SettingManager.h" -// #include "SettingInterface.h" -// #include "SettingHelpers.h" +#include +#include + const QString ScriptEngine::_SETTINGS_ENABLE_EXTENDED_EXCEPTIONS { "com.highfidelity.experimental.enableExtendedJSExceptions" @@ -2361,32 +2361,58 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co } else if (testConstructor.isError()) { exception = testConstructor; } - } - else { - // ENTITY SCRIPT WHITELIST STARTS HERE + } else { + // ENTITY SCRIPT WHITELIST STARTS HERE + auto nodeList = DependencyManager::get(); + bool passList = false; // assume unsafe QString whitelistPrefix = "[WHITELIST ENTITY SCRIPTS]"; - QList safeURLS = { "" }; - 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); - // PULL SAFEURLS FROM INTERFACE.JSON Settings + // IF WHITELIST IS DISABLED IN SETTINGS + bool whitelistEnabled = Setting::Handle("private/whitelistEnabled", true).get(); + if (!whitelistEnabled) { + passList = true; + } + // 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 - 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 + // 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 = 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() + << "Current Domain: " << currentDomain; + passList = true; } } - if (!isInWhitelist) { + // END CURRENT DOMAIN WHITELIST BYPASS + + // START CHECKING AGAINST THE WHITELIST + 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 : safeURLPrefixes) { + qCDebug(scriptengine) << whitelistPrefix << "Script URL: " << scriptOrURL << "TESTING AGAINST" << str << "RESULTS IN" + << scriptOrURL.startsWith(str); + if (!str.isEmpty() && scriptOrURL.startsWith(str)) { + passList = true; + qCDebug(scriptengine) << whitelistPrefix << "Script approved."; + break; // bail early since we found a match + } + } + } + // END CHECKING AGAINST THE WHITELIST + + 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 {