History

Fixed entity script whitelist and a bug in makeError

ksuprynowicz committed 3 years ago

Commit f72e8941 parent 8de13312 files · +71 −2Browse files

Showing the changes to libraries/script-engine/src/ScriptManager.cpp (1 of 2 files). Show all

Unified · Split

libraries/script-engine/src/ScriptManager.cpp+71−1
@@ -2059,7 +2059,6 @@ void ScriptManager::entityScriptContentAvailable(const EntityItemID& entityID, c · 2058 unmodified lines
20592059 exception = testConstructor;
20602060 }
20612061 } else {
2062− // V8TODO: re-enable entity script whitelist
20632062 // ENTITY SCRIPT WHITELIST STARTS HERE
20642063 auto nodeList = DependencyManager::get<NodeList>();
20652064 bool passList = false; // assume unsafe
@@ -2171,6 +2170,77 @@ void ScriptManager::entityScriptContentAvailable(const EntityItemID& entityID, c · 105 unmodified lines
21712170 return; // done processing script
21722171 }*/
21732172
2173+ // ENTITY SCRIPT WHITELIST STARTS HERE
2174+ auto nodeList = DependencyManager::get<NodeList>();
2175+ bool passList = false; // assume unsafe
2176+ QString whitelistPrefix = "[WHITELIST ENTITY SCRIPTS]";
2177+ QList<QString> safeURLPrefixes = { "file:///", "atp:", "cache:" };
2178+ safeURLPrefixes += qEnvironmentVariable("EXTRA_WHITELIST").trimmed().split(QRegExp("\\s*,\\s*"), Qt::SkipEmptyParts);
2179+
2180+ // Entity Script Whitelist toggle check.
2181+ Setting::Handle<bool> whitelistEnabled {"private/whitelistEnabled", false };
2182+
2183+ if (!whitelistEnabled.get()) {
2184+ passList = true;
2185+ }
2186+
2187+ // Pull SAFEURLS from the Interface.JSON settings.
2188+ QVariant raw = Setting::Handle<QVariant>("private/settingsSafeURLS").get();
2189+ QStringList settingsSafeURLS = raw.toString().trimmed().split(QRegExp("\\s*[,\r\n]+\\s*"), Qt::SkipEmptyParts);
2190+ safeURLPrefixes += settingsSafeURLS;
2191+ // END Pull SAFEURLS from the Interface.JSON settings.
2192+
2193+ // Get current domain whitelist bypass, in case an entire domain is whitelisted.
2194+ QString currentDomain = DependencyManager::get<AddressManager>()->getDomainURL().host();
2195+
2196+ QString domainSafeIP = nodeList->getDomainHandler().getHostname();
2197+ QString domainSafeURL = URL_SCHEME_OVERTE + "://" + currentDomain;
2198+ for (const auto& str : safeURLPrefixes) {
2199+ if (domainSafeURL.startsWith(str) || domainSafeIP.startsWith(str)) {
2200+ qCDebug(scriptengine) << whitelistPrefix << "Whitelist Bypassed, entire domain is whitelisted. Current Domain Host: "
2201+ << nodeList->getDomainHandler().getHostname()
2202+ << "Current Domain: " << currentDomain;
2203+ passList = true;
2204+ }
2205+ }
2206+ // END bypass whitelist based on current domain.
2207+
2208+ // Start processing scripts through the whitelist.
2209+ if (ScriptManager::getContext() == "entity_server") { // If running on the server, do not engage whitelist.
2210+ passList = true;
2211+ } else if (!passList) { // If waved through, do not engage whitelist.
2212+ for (const auto& str : safeURLPrefixes) {
2213+ qCDebug(scriptengine) << whitelistPrefix << "Script URL: " << scriptOrURL << "TESTING AGAINST" << str << "RESULTS IN"
2214+ << scriptOrURL.startsWith(str);
2215+ if (!str.isEmpty() && scriptOrURL.startsWith(str)) {
2216+ passList = true;
2217+ qCDebug(scriptengine) << whitelistPrefix << "Script approved.";
2218+ break; // Bail early since we found a match.
2219+ }
2220+ }
2221+ }
2222+ // END processing of scripts through the whitelist.
2223+
2224+ ScriptValue exception;
2225+ if (!passList) { // If the entity failed to pass for any reason, it's blocked and an error is thrown.
2226+ qCDebug(scriptengine) << whitelistPrefix << "(disabled entity script)" << entityID.toString() << scriptOrURL;
2227+ exception = _engine->makeError(_engine->newValue("UNSAFE_ENTITY_SCRIPTS == 0"));
2228+ }
2229+
2230+ if (exception.isError()) {
2231+ setError(formatException(exception, _enableExtendedJSExceptions.get()), EntityScriptStatus::ERROR_RUNNING_SCRIPT);
2232+ auto scriptRuntimeException = std::make_shared<ScriptRuntimeException>();
2233+ ScriptValue message = exception.property("stack"); //This contains more details along with the error message
2234+ scriptRuntimeException->errorMessage = message.toString();
2235+ scriptRuntimeException->thrownValue = exception;
2236+ emit unhandledException(scriptRuntimeException);
2237+ return;
2238+ }
2239+ // ENTITY SCRIPT WHITELIST ENDS HERE, uncomment below for original full disabling.
2240+
2241+ // qCDebug(scriptengine) << "(disabled entity script)" << entityID.toString() << scriptOrURL;
2242+ // exception = makeError("UNSAFE_ENTITY_SCRIPTS == 0");
2243+
21742244 // (this feeds into refreshFileScript)
21752245 int64_t lastModified = 0;
21762246 if (isFileUrl) {