Live data from Hacker News

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

allvpv.org

111–120 of 194 posts

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

#111
post #3

Environment variables are often used to pass secrets around. But, despite its ubiquity, I believe that's a bad practice: - 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. - IMO, this has become an even more…

Not an answer, but I do wish there was a low level primitive and a corresponding high level language construct to pass around secrets. Something like: my_secret = create_secret(value) Then ideally it's an opaque value from that point on

Until when? Secrets in applications in many cases (I would probably wager majority of the cases) are only useful if they're in plaintext at some point, for example if you're constructing a HTTP client or authenticating to some other remote system.

As far as high-level language constructs go, there were similarish things like SecureString (in .NET) or GuardedString (in Java), although as best as I can tell they're relatively unused mostly because the ergonomics around them make them pretty annoying to use.

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

#112

Earlier quoted context omitted.

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

Program args can be seen with tools like 'ps', so passing credentials that way is a poor choice.

They can also be caught by bash and system audit logs.

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

#113
post #59

Earlier quoted context omitted.

Is there consensus around that? Given how containers and bubblewrap/flatpak are considered (to some degree) security boundaries, I approach statements like this with skepticism.

You answered your own question. Bubblewrap uses namespaces, but not by themselves. They're used in conjunction with other tools to provide a security boundary. Even then, it's not a very good security boundary. A serious security boundary should hold up even to privilege escalation, which is not true for bubblewrap.

Each kind of namespace provides its own kind of boundary. Yes, you need something like bubblewrap to stitch that all together. And it is kinda leaky, especially without taking some degree of care.

What're you saying about privilege escalation? I don't see how a user namespace does not prevent/limit privilege escalation.

More than that, I'm interested if there is some broader consensus I'm missing on the shortcomings of namespaces.

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

#114
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…

NetBSD has had getenv_r() for ages, [0] and I believe FreeBSD has very recently copied it. [1] If FreeBSD has it, macOS might eventually adopt it too. People tried already to get it into both glibc and POSIX, and it was rejected, but if it becomes more common on other platforms, that increases the chance they’ll both eventually accept it. [0] https://man.netbsd.org/getenv_r.3 [1] https://github.com/freebsd/freebsd-sr…

You still don’t know if some library you use calls getenv() and stores the returned pointer (or, potentially, runs in a different thread). Using getenv_r() protects your code against setenv(), but other code that may be using getenv() is still unprotected against your (or anyone else’s) use of setenv().

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

#115

Environment variables also suck due to having zero typo existence. Write FOO_BAR instead of FOO_BARS? Silent failure. V1 of your package recognizes FOO_BAR and V2 changes it to FOO_BARS (because now we can have more than one)? Silent failure.

In a shell script, set -u. It’ll terminate if you reference an unset variable. In other languages, check that the var you pulled in isn’t falsey before proceeding.

> In a shell script, set -u

Won't help. I'm _running a program_ want to configure it with environment variables, not _writing a program_ that I expect the user to configure for himself.

> falsey

There are more than two programming languages in the world.

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

#116
post #24
post #3

Environment variables are often used to pass secrets around. But, despite its ubiquity, I believe that's a bad practice: - 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. - IMO, this has become an even more…

If are like most users you have secrets stored in read-protected files in ~/.ssh. There's nothing wrong with that.

They are (should be) encrypted though, and not usable by someone who might somehow gain access to your ~/.ssh files.

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

#117
post #94
post #89

Earlier quoted context omitted.

Yes, you can consider all processes running under the same user as able to peek at each other's data. This is the point of running under the same uid: sharing data.One uid should be considered one security domain, with any separators inside it being guardrails, not brick walls. If you want to prevent other processes from peeking into your process, run it under a different uid. Again. that's the point. A bunch of good…

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…

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 regards to anything to do with user accounts.

The real security barrier on most operating systems to date is the user account and if you want full isolation (modulo kernel bugs), run a process as a separate user if you're that concerned about leakage (or ideally, don't run it at all).

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

#118
post #101

That was a hard to read font.

I'm surprised you say that. Iosevka is quite beloved as a monospace font. I use it for all my terminals, etc.

Prose in monospace is harder to read regardless of the specific font.

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

#119

Earlier quoted context omitted.

You have a config file, it needs to have secrets so likely you are going to run some templating system where you replace dbpassword: ${dbPassword} with password from some secret system. Hopefuly you understand possible issues with any templating system that could result in replacement failures. String manipulating is one of those "This is easy" until it's not.

Apparently I'm still unclear. I don't mean to hardcode secrets into the config file either. I was suggesting to put a command into the configuration file that the application then calls to get the secret. This way the secret is only ever passed over a file descriptor between two processes.

My initial Ops gut feeling says "This is as lock in and error prone as Application Vault Libraries" but if Dev wanted to propose this, I'd be willing to see it in real operation.

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

#120
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 full root exploit is leveraged, it's already game over already, basically anything at that point is just going to be rearranging deck chairs.
Post reply on HN