diff --git a/bin/foamJob b/bin/foamJob
index 75a963e93cd39c838f2e40f1ba5568279233802b..6221eb67dfff9b13330d68b1dcd14a45fb67f5b5 100755
--- a/bin/foamJob
+++ b/bin/foamJob
@@ -23,13 +23,6 @@
 # If dispatching via foamExec
 foamExec="$WM_PROJECT_DIR/bin/tools/foamExec"
 
-# Darwin workaround - SIP clearing DYLD_LIBRARY_PATH variable
-if [ -n "$FOAM_LD_LIBRARY_PATH" ] && [ -z "$DYLD_LIBRARY_PATH" ]
-then
-    export DYLD_LIBRARY_PATH="$FOAM_LD_LIBRARY_PATH"
-fi
-
-
 #------------------------------------------------------------------------------
 
 usage() {
diff --git a/bin/tools/RunFunctions b/bin/tools/RunFunctions
index f8482f63f29545223fb7fa4d9d3ec7901742cfe6..68364b7738b18a0e6f21b68fa66006f652364e91 100644
--- a/bin/tools/RunFunctions
+++ b/bin/tools/RunFunctions
@@ -25,13 +25,6 @@
 # Basic sanity checks
 [ -d "$FOAM_TUTORIALS" ] || echo "No OpenFOAM tutorials? : $FOAM_TUTORIALS" 1>&2
 
-# Darwin workaround - SIP clearing DYLD_LIBRARY_PATH variable
-if [ -n "$FOAM_LD_LIBRARY_PATH" ] && [ -z "$DYLD_LIBRARY_PATH" ]
-then
-    export DYLD_LIBRARY_PATH="$FOAM_LD_LIBRARY_PATH"
-fi
-
-
 #------------------------------------------------------------------------------
 
 #
diff --git a/src/OSspecific/POSIX/POSIX.C b/src/OSspecific/POSIX/POSIX.C
index 826ac470215922bd608ccd3cdcc000edb17c84ae..dffd5e0a540d8c26bb5d442aaa49790617bc1201 100644
--- a/src/OSspecific/POSIX/POSIX.C
+++ b/src/OSspecific/POSIX/POSIX.C
@@ -41,6 +41,7 @@ Description
 #include "timer.H"
 #include "DynamicList.H"
 #include "CStringList.H"
+#include "stringOps.H"
 #include "IOstreams.H"
 #include "Pstream.H"
 
@@ -108,6 +109,52 @@ static inline void redirects(const bool bg)
 }
 
 
+// Library loading is normally simply via dlopen(),
+// but SIP (System Integrity Protection) on Apple will generally
+// clear out the DYLD_LIBRARY_PATH set from shell scripts.
+// We thus have FOAM_LD_LIBRARY_PATH as a shadow parameter and use
+// that to attempt loading ourselves
+static inline void* loadLibrary(const Foam::fileName& libName)
+{
+    constexpr int ldflags = (RTLD_LAZY|RTLD_GLOBAL);
+
+#ifdef __APPLE__
+    const char* normal = nullptr;
+    const char* shadow = nullptr;
+
+    if
+    (
+        !libName.isAbsolute()
+     && ((normal = ::getenv("DYLD_LIBRARY_PATH"))    == nullptr || !*normal)
+     && ((shadow = ::getenv("FOAM_LD_LIBRARY_PATH")) != nullptr && *shadow)
+    )
+    {
+        // SIP appears to have cleared DYLD_LIBRARY_PATH but the
+        // shadow parameter is available
+
+        const Foam::string ldPaths(shadow);
+        const auto paths = Foam::stringOps::split<Foam::string>(ldPaths, ':');
+
+        for (const auto& p : paths)
+        {
+            if (p.length())  // Split removes empty, but be paranoid
+            {
+                const Foam::fileName fullPath(p.str()/libName);
+                void* handle = ::dlopen(fullPath.c_str(), ldflags);
+                if (handle)
+                {
+                    return handle;
+                }
+            }
+        }
+    }
+#endif
+
+    // Regular loading
+    return ::dlopen(libName.c_str(), ldflags);
+}
+
+
 // * * * * * * * * * * * * * * * * Local Classes * * * * * * * * * * * * * * //
 
 namespace Foam
@@ -1752,16 +1799,13 @@ int Foam::system(const Foam::UList<Foam::string>& command, const bool bg)
 
 void* Foam::dlOpen(const fileName& libName, const bool check)
 {
-    constexpr int ldflags = (RTLD_LAZY|RTLD_GLOBAL);
-
     if (POSIX::debug)
     {
         std::cout
-            << "dlOpen(const fileName&)"
-            << " : dlopen of " << libName << std::endl;
+            << "dlopen() of " << libName << std::endl;
     }
 
-    void* handle = ::dlopen(libName.c_str(), ldflags);
+    void* handle = loadLibrary(libName);
 
     if (!handle)
     {
@@ -1771,13 +1815,12 @@ void* Foam::dlOpen(const fileName& libName, const bool check)
         {
             // Try with 'lib' prefix
             libso = "lib" + libName;
-            handle = ::dlopen(libso.c_str(), ldflags);
+            handle = loadLibrary(libso);
 
             if (POSIX::debug)
             {
                 std::cout
-                    << "dlOpen(const fileName&)"
-                    << " : dlopen of " << libso << std::endl;
+                    << "   dlopen() as " << libso << std::endl;
             }
         }
         else
@@ -1790,13 +1833,12 @@ void* Foam::dlOpen(const fileName& libName, const bool check)
         if (!handle && !libso.has_ext(EXT_SO))
         {
             libso.replace_ext(EXT_SO);
-            handle = ::dlopen(libso.c_str(), ldflags);
+            handle = loadLibrary(libso);
 
             if (POSIX::debug)
             {
                 std::cout
-                    << "dlOpen(const fileName&)"
-                    << " : dlopen of " << libso << std::endl;
+                    << "   dlopen() as " << libso << std::endl;
             }
         }
     }
@@ -1810,8 +1852,7 @@ void* Foam::dlOpen(const fileName& libName, const bool check)
     if (POSIX::debug)
     {
         std::cout
-            << "dlOpen(const fileName&)"
-            << " : dlopen of " << libName
+            << "dlopen() of " << libName
             << " handle " << handle << std::endl;
     }