diff --git a/lib/internal/bootstrap/node.js b/lib/internal/bootstrap/node.js
index 78d04fe4446d5b..995495532886b1 100644
--- a/lib/internal/bootstrap/node.js
+++ b/lib/internal/bootstrap/node.js
@@ -187,13 +187,6 @@ if (browserGlobals) {
 
 setupDOMException();
 
-// On OpenBSD process.execPath will be relative unless we
-// get the full path before process.execPath is used.
-if (process.platform === 'openbsd') {
-  const { realpathSync } = NativeModule.require('fs');
-  process.execPath = realpathSync.native(process.execPath);
-}
-
 Object.defineProperty(process, 'argv0', {
   enumerable: true,
   configurable: false,
diff --git a/src/node_process_object.cc b/src/node_process_object.cc
index a95677686ec904..c673b90955a95b 100644
--- a/src/node_process_object.cc
+++ b/src/node_process_object.cc
@@ -285,21 +285,34 @@ MaybeLocal<Object> CreateProcessObject(
 
   // process.execPath
   {
-    size_t exec_path_len = 2 * PATH_MAX;
-    std::vector<char> exec_path(exec_path_len);
-    Local<String> exec_path_value;
-    if (uv_exepath(exec_path.data(), &exec_path_len) == 0) {
-      exec_path_value = String::NewFromUtf8(env->isolate(),
-                                            exec_path.data(),
-                                            NewStringType::kInternalized,
-                                            exec_path_len).ToLocalChecked();
+    char exec_path_buf[2 * PATH_MAX];
+    size_t exec_path_len = sizeof(exec_path_buf);
+    std::string exec_path;
+    if (uv_exepath(exec_path_buf, &exec_path_len) == 0) {
+      exec_path = std::string(exec_path_buf, exec_path_len);
     } else {
-      exec_path_value = String::NewFromUtf8(env->isolate(), args[0].c_str(),
-          NewStringType::kInternalized).ToLocalChecked();
+      exec_path = args[0];
     }
-    process->Set(env->context(),
-                 FIXED_ONE_BYTE_STRING(env->isolate(), "execPath"),
-                 exec_path_value).FromJust();
+    // On OpenBSD process.execPath will be relative unless we
+    // get the full path before process.execPath is used.
+#if defined(__OpenBSD__)
+    uv_fs_t req;
+    req.ptr = nullptr;
+    if (0 ==
+        uv_fs_realpath(env->event_loop(), &req, exec_path.c_str(), nullptr)) {
+      CHECK_NOT_NULL(req.ptr);
+      exec_path = std::string(static_cast<char*>(req.ptr));
+    }
+#endif
+    process
+        ->Set(env->context(),
+              FIXED_ONE_BYTE_STRING(env->isolate(), "execPath"),
+              String::NewFromUtf8(env->isolate(),
+                                  exec_path.c_str(),
+                                  NewStringType::kInternalized,
+                                  exec_path.size())
+                  .ToLocalChecked())
+        .FromJust();
   }
 
   // process.debugPort