@@ -96,28 +96,11 @@ static inline bool EndsWith(const std::string& value, const std::string& suffix)
9696 return std::equal (suffix.rbegin (), suffix.rend (), value.rbegin ());
9797}
9898
99- // HTTP ESM loader helpers
100-
10199static inline bool StartsWith (const std::string& s, const char * prefix) {
102100 size_t n = strlen (prefix);
103101 return s.size () >= n && s.compare (0 , n, prefix) == 0 ;
104102}
105103
106- // Security gate
107- // In debug mode, all URLs are allowed. In production, checks security.allowRemoteModules and security.remoteModuleAllowlist
108- static inline bool IsHttpUrlAllowedForLoading (const std::string& url) {
109- return IsRemoteUrlAllowed (url);
110- }
111-
112- // Helper to create a security error message for blocked remote modules
113- static std::string GetRemoteModuleBlockedMessage (const std::string& url) {
114- if (!IsRemoteModulesAllowed ()) {
115- return " Remote ES modules are not allowed in production. URL: " + url +
116- " . Enable via security.allowRemoteModules in nativescript.config" ;
117- }
118- return " Remote URL not in security.remoteModuleAllowlist: " + url;
119- }
120-
121104
122105static v8::MaybeLocal<v8::Module> CompileModuleFromSource (v8::Isolate* isolate, v8::Local<v8::Context> context,
123106 const std::string& code, const std::string& urlStr) {
@@ -741,17 +724,8 @@ static bool IsDocumentsPath(const std::string& path) {
741724 // ── Early absolute-HTTP fast path ─────────────────────────────
742725 // If the specifier itself is an absolute HTTP(S) URL, resolve it immediately via
743726 // the HTTP loader and return before any filesystem candidate logic runs.
727+ // Security: HttpFetchText gates remote module access centrally.
744728 if (StartsWith (spec, " http://" ) || StartsWith (spec, " https://" )) {
745- // Security check: block if remote modules not allowed
746- if (!IsHttpUrlAllowedForLoading (spec)) {
747- std::string msg = GetRemoteModuleBlockedMessage (spec);
748- if (IsScriptLoadingLogEnabled ()) {
749- Log (@" [resolver][security] blocked remote module: %s " , spec.c_str ());
750- }
751- isolate->ThrowException (v8::Exception::Error (tns::ToV8String (isolate, msg.c_str ())));
752- return v8::MaybeLocal<v8::Module>();
753- }
754-
755729 std::string key = CanonicalizeHttpUrlKey (spec);
756730 // Added instrumentation for unified phase logging
757731 Log (@" [http-esm][compile][begin] %s " , key.c_str ());
@@ -850,7 +824,7 @@ static bool IsDocumentsPath(const std::string& path) {
850824 // ("./" or "../") or root-absolute ("/") specifiers should resolve against the
851825 // referrer's URL, not the local filesystem. Mirror browser behavior by using NSURL
852826 // to construct the absolute URL, then return an HTTP-loaded module immediately.
853- // Security: Gated by IsHttpUrlAllowedForLoading .
827+ // Security: HttpFetchText gates remote module access centrally .
854828 bool referrerIsHttp = (!referrerPath.empty () && (StartsWith (referrerPath, " http://" ) || StartsWith (referrerPath, " https://" )));
855829 bool specIsRootAbs = !spec.empty () && spec[0 ] == ' /' ;
856830 if (referrerIsHttp && (specIsRelative || specIsRootAbs)) {
@@ -871,16 +845,7 @@ static bool IsDocumentsPath(const std::string& path) {
871845 }
872846 }
873847 if (!resolvedHttp.empty () && (StartsWith (resolvedHttp, " http://" ) || StartsWith (resolvedHttp, " https://" ))) {
874- // Security check: block if remote modules not allowed
875- if (!IsHttpUrlAllowedForLoading (resolvedHttp)) {
876- std::string msg = GetRemoteModuleBlockedMessage (resolvedHttp);
877- if (IsScriptLoadingLogEnabled ()) {
878- Log (@" [resolver][security] blocked remote module (rel): %s " , resolvedHttp.c_str ());
879- }
880- isolate->ThrowException (v8::Exception::Error (tns::ToV8String (isolate, msg.c_str ())));
881- return v8::MaybeLocal<v8::Module>();
882- }
883-
848+ // Security: HttpFetchText gates remote module access centrally.
884849 if (IsScriptLoadingLogEnabled ()) {
885850 Log (@" [resolver][http-rel] base=%s spec=%s -> %s " , referrerPath.c_str (), spec.c_str (), resolvedHttp.c_str ());
886851 }
@@ -1045,17 +1010,8 @@ static bool IsDocumentsPath(const std::string& path) {
10451010 std::string absPath;
10461011
10471012 // If the specifier is an HTTP(S) URL, fetch via HTTP loader and return
1013+ // Security: HttpFetchText gates remote module access centrally.
10481014 if (StartsWith (spec, " http://" ) || StartsWith (spec, " https://" )) {
1049- // Security check: block if remote modules not allowed
1050- if (!IsHttpUrlAllowedForLoading (spec)) {
1051- std::string msg = GetRemoteModuleBlockedMessage (spec);
1052- if (IsScriptLoadingLogEnabled ()) {
1053- Log (@" [resolver][security] blocked remote module: %s " , spec.c_str ());
1054- }
1055- isolate->ThrowException (v8::Exception::Error (tns::ToV8String (isolate, msg.c_str ())));
1056- return v8::MaybeLocal<v8::Module>();
1057- }
1058-
10591015 std::string key = CanonicalizeHttpUrlKey (spec);
10601016 if (IsScriptLoadingLogEnabled ()) {
10611017 Log (@" [http-esm][compile][begin] %s " , key.c_str ());
@@ -1141,7 +1097,7 @@ static bool IsDocumentsPath(const std::string& path) {
11411097
11421098 // If a candidate accidentally embeds a collapsed HTTP URL like '/app/http:/host/...',
11431099 // reconstruct the HTTP URL and resolve via the HTTP loader instead of touching the filesystem.
1144- // Security: Gated by IsHttpUrlAllowedForLoading .
1100+ // Security: HttpFetchText gates remote module access centrally .
11451101 auto rerouteHttpIfEmbedded = [&](const std::string& p) -> bool {
11461102 size_t pos1 = p.find (" /http:/" );
11471103 size_t pos2 = p.find (" /https:/" );
@@ -1156,16 +1112,6 @@ static bool IsDocumentsPath(const std::string& path) {
11561112 }
11571113 if (!(StartsWith (tail, " http://" ) || StartsWith (tail, " https://" ))) return false ;
11581114
1159- // Security check: block if remote modules not allowed
1160- if (!IsHttpUrlAllowedForLoading (tail)) {
1161- if (IsScriptLoadingLogEnabled ()) {
1162- Log (@" [resolver][security] blocked embedded remote module: %s " , tail.c_str ());
1163- }
1164- std::string msg = GetRemoteModuleBlockedMessage (tail);
1165- isolate->ThrowException (v8::Exception::Error (tns::ToV8String (isolate, msg.c_str ())));
1166- return false ;
1167- }
1168-
11691115 if (IsScriptLoadingLogEnabled ()) { Log (@" [resolver][http-embedded] %s -> %s " , p.c_str (), tail.c_str ()); }
11701116 std::string key = CanonicalizeHttpUrlKey (tail);
11711117 auto itExisting = g_moduleRegistry.find (key);
@@ -1970,17 +1916,8 @@ static bool IsDocumentsPath(const std::string& path) {
19701916 }
19711917
19721918 // If spec is an HTTP(S) URL, try HTTP fetch+compile directly
1919+ // Security: HttpFetchText gates remote module access centrally.
19731920 if (!normalizedSpec.empty () && (StartsWith (normalizedSpec, " http://" ) || StartsWith (normalizedSpec, " https://" ))) {
1974- // Security check: block if remote modules not allowed
1975- if (!IsHttpUrlAllowedForLoading (normalizedSpec)) {
1976- std::string msg = GetRemoteModuleBlockedMessage (normalizedSpec);
1977- if (IsScriptLoadingLogEnabled ()) {
1978- Log (@" [dyn-import][security] blocked remote module: %s " , normalizedSpec.c_str ());
1979- }
1980- resolver->Reject (context, v8::Exception::Error (tns::ToV8String (isolate, msg.c_str ()))).FromMaybe (false );
1981- return scope.Escape (resolver->GetPromise ());
1982- }
1983-
19841921 if (IsScriptLoadingLogEnabled ()) {
19851922 Log (@" [dyn-import][http-loader] trying URL %s " , normalizedSpec.c_str ());
19861923 }
0 commit comments