It really isn't a kernel problem at all, of course.
The POSIX spec says "The first argument, argv[0], is required and must contain the name of the executable file for the new process image."[1] Linux is not fully POSIX-compliant, but it generally follows the POSIX standard for kernel calls defined in POSIX.
FreeBSD's man page says "At least one argument must be present in the array; by custom, the first element should be the name of the executed program (for example, the last component of path)."[2] So, "must", compatible with the POSIX spec.
QNX implements the POSIX API, pretty much per the spec. The QNX spec says: "The value in argv[0] must point to a filename that's associated with the process being started."[4] So, "must", again compatible with the spec.
The Linux man page says, unfortunately, "By convention, the first of these strings (i.e., argv[0]) should contain the filename associated with the file being executed."[3] That's the problem. POSIX says "must" but the Linux page only says "should". That was a mistake.
One somewhat kludgy fix would be to disallow argv[0] == NULL && envp[0] != NULL. That allows launching a program with no args at all, which might be used somewhere in some ancient program, while disallowing launch with no command line args but with environment args, which is probably a bug.
(I liked the QNX approach to program loading. The kernel isn't involved. The "exec" functions link to a shared object, which requests memory and does the loading using regular I/O operations. The kernel contains no loader and is thus immune to problems from malformed executables.)
[1] https://support.sas.com/documentation/onlinedoc/sasc/doc750/...
[2] https://manpages.debian.org/unstable/freebsd-manpages/execve...
[3] https://www.man7.org/linux/man-pages/man2/execve.2.html
[4] https://www.qnx.com/developers/docs/6.4.0/neutrino/lib_ref/e...