Showing the changes to libraries/script-engine/src/ScriptManager.cpp (1 of 2 files). Show all
Unified · Split
| @@ -2059,7 +2059,6 @@ void ScriptManager::entityScriptContentAvailable(const EntityItemID& entityID, c · 2058 unmodified lines | |||
| 2059 | exception = testConstructor; | 2059 | exception = testConstructor; |
| 2060 | } | 2060 | } |
| 2061 | } else { | 2061 | } else { |
| 2062 | // V8TODO: re-enable entity script whitelist | ||
| 2063 | // ENTITY SCRIPT WHITELIST STARTS HERE | 2062 | // ENTITY SCRIPT WHITELIST STARTS HERE |
| 2064 | auto nodeList = DependencyManager::get<NodeList>(); | 2063 | auto nodeList = DependencyManager::get<NodeList>(); |
| 2065 | bool passList = false; // assume unsafe | 2064 | bool passList = false; // assume unsafe |
| @@ -2171,6 +2170,77 @@ void ScriptManager::entityScriptContentAvailable(const EntityItemID& entityID, c · 105 unmodified lines | |||
| 2171 | return; // done processing script | 2170 | return; // done processing script |
| 2172 | }*/ | 2171 | }*/ |
| 2173 | 2172 | ||
| 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 | |||
| 2174 | // (this feeds into refreshFileScript) | 2244 | // (this feeds into refreshFileScript) |
| 2175 | int64_t lastModified = 0; | 2245 | int64_t lastModified = 0; |
| 2176 | if (isFileUrl) { | 2246 | if (isFileUrl) { |