I think it's worth specifically calling out that the right way to set environment variables is in execve() only, as communication across an exec() is the precise niche for which they are the right tool.
Well yeah of course. What you could do though would be to have e.g. --secrets-file and at startup time the application reads that file to get the secret. Then you could use file permissions to make sure only the (application) user running the application can read that file (or even more extreme, the application destroys the file after reading it).
I think that would still be better than env vars, which are more likely to leak somewhere you didn't intend them to.
Env vars are unordered name=value pairs, so are suited for such data.
In contrast, arguments are an ordered sequence of strings, so are more suited for present/not-present flags (e.g. --dry-run) , or listing a variable number of values (e.g. filenames). Using arguments for name=value data either requires individual strings to be parsed into components, or requires a pair of name and value strings to appear sequentially (without overlapping another pair, etc.). Arguments also tend to require disambiguation, e.g. prepending names with `--`, to account for optional arguments not being present, or for allowing options to be given in any order, etc. That may also require escape hatches, like a standalone `--` argument, in case user data conflicts with such reserved patterns, etc.
Sure, there are libraries for parsing this stuff; and conventions that we can get used to (except when a tool doesn't follow them...), but it's still a complicated mess compared to `NAME1=val1 NAME2=val2 my-command --flag1 --flag2 file1 file2 file3`