Live data from Hacker News

Environment variables are a legacy mess: Let's dive deep into them

allvpv.org

171–180 of 194 posts

Re: Environment variables are a legacy mess: Let's dive deep into them

#171
post #151
post #94

Earlier quoted context omitted.

I think this part of Unix is exceedingly problematic. I want to be able to run program that don't have the ability to do anything that I, personally, can do. Ideally this would be doable without nasty kludges or root's help. Linux has some ways to accomplish this, for example: - seccomp. It can be done quite securely, but running general purpose software in seccomp is not necessarily a good way to prevent it from act…

Yes, if we talk about interactive use, where the user may want to run a program with isolation on a whim, and can't be bothered to prepare a separate account for it. Namespaces, to my mind, are a huge help, starting from trivial chroot and nsenter, all the way to bubblewrap [2] and containers (rootless, of course). Also, with a properly prepared disk image, and the OS state frozen when everything heavyweight has star…

Part of the problem with namespaces in general comes from setuid/setgid binaries. Now, nosuid helps, but the argument goes (and this is why dropping privileges on Linux sometimes requires root) that blocking setuid can actually increase attack surface (because many programs, as part of their initialization routines setuid to a specific service user). Blocking setuid blocks this which can lead to a program unintentionally running, paradoxically, with too many privileges (or the incorrect set of ones).

And in the case of allowing setuid and filesystem views, the issue here becomes that an unprivileged user could create a view of the filesystem that has an /etc/passwd and /etc/shadow file that the attacker knows in their home directory. Run some setuid program (like su or sudo) with this view and we've successfully became root, breaking out of the sandbox.

And you can't whitelist /etc/passwd or whatever either. This is why allowing anyone to play with mount points is fraught with danger.

Now is suid/sgid a fundamental part of a Unix-like system? No, but setuid was created in the world that was and even though these are arguably bugs, releasing a Linux kernel that creates a bunch of security holes in userspace is a very very bad breakage of userspace.

---

No New Privileges does make this a bit better (as you can never gain more privileges than you already have, and this is a one-way door) and the kernel docs even say that eventually unshare or chroot may be allowed when operating under no new privileges

But this is currently why you can't chroot as an unprivileged user as you can trivially blow through the security domain on most Linux distributions

Re: Environment variables are a legacy mess: Let's dive deep into them

#172
post #142

Earlier quoted context omitted.

It's not your (unprivileged user account's) place to decide the security posture of the entire system, that's why you're running into issues with root. Even Yama, an LSM, requires root (or de facto equivalent) for initial setup (as it should). Namespaces, if done incorrectly, can significantly increase the attack surface of the entire system (mount namespaces especially need to be treated with care) and same with reg…

> It's not your (unprivileged user account's) place to decide the security posture of the entire system, that's why you're running into issues with root. Tell that to literally any unprivileged user who would like to run any sort of software without exposing their entire account to any possible code execution bug or malicious code in the software they're running. > The real security barrier on most operating systems…

I think the main point here is that... well if you can help it, don't run untrusted software, since it's by definition not trusted. There are some times where you can't really get around it (JavaScript is an increasingly big example of this and there are many ecosystems in which you are prevented from running trusted software without great difficulty) and there are many general protections that are in OSes that will help you there.

On Linux you have some combination of Landlock, AppArmor, SELinux, calling prctl(PR_SET_NO_NEW_PRIVS), and the kitchen sink. On FreeBSD you have capsicum. Windows has integrity labeling + a bunch of stuff related to Job objects + a few things to disable win32k.sys calls.

But these are helpful and shouldn't be considered a panacea. The expectation is that you're delegating authority to a computer program to perform a certain task. Do computer programs abuse that authority sometimes? Absolutely. But nonetheless that's the fundamental model of most computer security, thanks in part to its usefulness.

Re: Environment variables are a legacy mess: Let's dive deep into them

#173

SRE/Sysadmin/DevOps/Whatever here, while blog didn't talk about doing anything difficult but setting ENVVAR standards, I will point out all replacements are just as frustrating especially when talking about secrets. Anything involving vaults where Application reaches out to specific secret vault like Hashicorp Vault/OpenBao/Secrets Manager quickly becomes massive vendor lock in where replacement is very difficult due…

> Getting secrets from Kubernetes Secrets API I've seen done but lock in again.

I don't get this part. Why would you use Kubernetes secrets alone for storing secrets if they are not encrypted by default? Using k8s secrets only makes sense if (0) you are using k8s, (1) you already did some groundwork like encryption at rest for the control plane, and (2) you are actually using a solution like Secrets Store CSI Driver (or alternatives - just don't depend on k8s secret being actually more secret than a ConfigMap by default).

And then, it's the opposite of lock-in as the Secrets Store CSI Driver uspports multiple backends, including open source Conjur.

Re: Environment variables are a legacy mess: Let's dive deep into them

#174
post #53

Earlier quoted context omitted.

> On Linux systems, any user process can inspect any other process of that same user for it's environment variables. We can argue about threat model but, especially for a developer's system, there are A LOT of processes running as the same user as the developer. This is a very good point I'd never realised! I'm not sure how you get around it, though, as if that program can even find a credential and decrypt a file, i…

If a root exploit is leveraged, then /proc/*/environ of all processes is visible to the adversary. The classical alternative has been to store (FTP) credentials in a .netrc file (also used by curl). I have some custom code to pull passwords out of a SQLite database. For people who are really concerned with this, a "secrecy manger" is more appropriate, such as Cyberark conjur and summon, or Hashicorp Vault.

> If a root exploit is leveraged, then /proc/*/environ of all processes is visible to the adversary.

> The classical alternative has been to store (FTP) credentials in a .netrc file (also used by curl).

You're not suggesting that a netrc file would stop a root exploit?

Re: Environment variables are a legacy mess: Let's dive deep into them

#175
post #27
post #15

Earlier quoted context omitted.

AFAIK Solaris solved that problem but Linux refuses to copy their solution.

Their solution was that setenv leaks memory rather than overwriting in place. FreeBSD does the same. See here for discussion: https://freebsd-current.freebsd.narkive.com/NwqZQDWm/fix-for...

Yes. Changing the implementation to the Solaris/FreeBSD solution now would probably break lots of applications that nowadays works without issue.

Re: Environment variables are a legacy mess: Let's dive deep into them

#176
post #129

Unix is a legacy mess. The sooner we rid ourselves of this scourge, the better. Posted from a productive Windows workstation.

I feel that Windows Registry is similar legacy cruft as environment variables. Worse yet, most software doesn't document which registry keys it's using, so you have to find them on some ancient forum comment or do the detective work by yourself.

Re: Environment variables are a legacy mess: Let's dive deep into them

#177
post #35

Earlier quoted context omitted.

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.

Why are they the right tool for that instead of passing data with program args or another way of IPC?

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`

Re: Environment variables are a legacy mess: Let's dive deep into them

#178

>"Wow, I really enjoyed writing this… …and I hope it wasn’t a boring read." No, it was very interesting actually! An excellent deep-dive into the murky area of Unix/Linux environment variables, how they are set, how they are passed, what's really going on behind the scenes. Basically a must-read for any present or future OS designer... Observation (if I might!) -- environment variables are to programs (especially cha…

> environment variables are to programs (especially chains of programs, parent processes, sub processes and sub-sub processes, etc.) what parameters are to functions -- and/or what command-line parameters are... they're sort of like global variables that get passed around a lot...

They're not globals, since they're copied into sub-processes; so mutation doesn't propagate upwards.

My own opinion is that environment variables are dynamically scoped keyword arguments http://www.chriswarbo.net/blog/2021-04-08-env_vars.html

Re: Environment variables are a legacy mess: Let's dive deep into them

#179

SRE/Sysadmin/DevOps/Whatever here, while blog didn't talk about doing anything difficult but setting ENVVAR standards, I will point out all replacements are just as frustrating especially when talking about secrets. Anything involving vaults where Application reaches out to specific secret vault like Hashicorp Vault/OpenBao/Secrets Manager quickly becomes massive vendor lock in where replacement is very difficult due…

I am not sure if this considered an anti-pattern, but in one of my teams, we wrote a lightweight generic Secrets library with configurable/pluggable backends (such as AWS Secrets Manager). It had a configurable local cache, with per-parameter overrides to bypass the cache. It meant vendor specific fetch logic was in the pluggable backends, while the app and the secrets lib remained vendor neutral. When we moved it to…

This is how it should be done. Vendor lock-in can almost always be avoided with proper design

Re: Environment variables are a legacy mess: Let's dive deep into them

#180
post #4

Interesting read. Another interesting fact is that `setenv()` is fundamentally broken on POSIX, and should essentially never be called in library code. In application code, it should be called only in the absence of any alternative, and certainly before any threads have started. The reason is that `getenv()` hands out raw pointers to the variables, so overwriting a variable using `setenv()` is impossible to guard aga…

Why would you ever call setenv in library code to begin with?

I mean, it would be perfectly fine if it wasn’t for the fact that it’s not perfectly fine…
Post reply on HN