Yeah, fork()+immediately exec() should be safe, but those use cases are almost always better with posix_spawn(), due to issues with fork(), like memory copying. And if you want to use the p-variant of posix_spawn you’re back to setting PATH beforehand. These APIs designed back in Stone Age just aren’t very well thought-out wrt concurrency and high performance.
Why would you change the path just to call posix_spawnp()? If you want that control, that is an indication that you want to specify the path to the executable, not use PATH.