That's because the only special characters in file paths in Unix are / and NUL. You can't pass NUL through environment variables, both because of the C API for manipulating environment variables and how the environment is passed to the host program by the kernel--environment variables are delimited by NUL, as are argv arguments, and the argv and environ lists are delimited by a double NUL. So the shell had to pick some random delimiter, and whatever it chose would conflict with existing path semantics. Fortunately, it only effects the semantics of PATH--the colon is irrelevant everywhere else, and PATH isn't strictly necessary for anything, not even in the shell.
There's no easy way to fix that. I suppose PATH could instead be split into PATH_1, PATH_2, PATH_3, etc, with a single path per environment variable. I've used such a solution to emulate arrays for both internal and environment variables. But that ship sailed a long time ago: the semantics of PATH are built into the shell, libc (because libc's execvp, etc are what traverse $PATH looking for an executable, not the kernel), countless other programs, not to mention the POSIX standard itself.
There's no easy way to fix that. I suppose PATH could instead be split into PATH_1, PATH_2, PATH_3, etc, with a single path per environment variable. I've used such a solution to emulate arrays for both internal and environment variables. But that ship sailed a long time ago: the semantics of PATH are built into the shell, libc (because libc's execvp, etc are what traverse $PATH looking for an executable, not the kernel), countless other programs, not to mention the POSIX standard itself.