Unix doesn't use spawn, it uses fork. Fork clones a process (with a very short list of differences in the child), typically immediately before an exec.
(As said in comment..) The exec system call is where environment variables are passed to the new process. It is up to the parent to either default to using its own env for the new executable or passing something else that is possibly completely different.
In bash (and possibly other shells), the
-c option to the
exec command can clear the environment. It is also possible to change environment variables the usual way by putting
variable=valuebefore exec on the command line. If none of these things are done, the new executable inherits what the shell had.
Note that while fork() makes very few changes in the child, exec() makes a large number of changes. For example, signal handlers are reset. Open file handles can be marked as close on exec so the new executable doesn't get them. The memory map is redone from scratch. And things like environment variables can be inherited or replaced as a set.
So your assumptions about what fork and exec do are somewhat reversed from actual use. The philosophy here is that fork() is frequently done to create a new process whose memory is about to all be thrown away to a new executable, so there's no point in doing any work to change it or set it up. After the fork, the running program may at its option continue with the same memory (typically set as copy on write, opportunistically cloning memory pages as needed), or using exec() to replace it completely with a new program, disassociating from the parent's shared memory pages with no changes to them. Environment variables are one of the few things that can potentially (but not certainly) survive after exec() is called.