Live data from Hacker News

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

allvpv.org

121–130 of 194 posts

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

#121

Earlier quoted context omitted.

Yes you can? The container should be completely agnostic to the fact that it's running in kubernetes. You can do config the same way. Configmaps are mounted as regular files and environment variables. The application doesn't care if the configmap came from the cluster resource or a file your created on your dev machine with dev credentials. You can mount local files into the container yourself. It's docker run -v "so…

sigh I’m extremely competent Ops type and I know. If you mount secrets as Volume or Env Var, that’s Config file or Env var from Application PoV. We are looking at this from Application PoV. I’ve seen Applications that do direct calls to Kubernetes API and retrieve the secret from it. So they have custom role with bindings and service account and Kubernetes client libraries.

If you're not developing k8s operators, you're calling the api server directly, then complaining about lock in, then that's a skill issue. If you're developing k8s operators, then you should use a tool like kind for integration tests and dependency injection for other stuff and the concept of lock in doesn't make sense. You can also deploy your helm chart directly to kind.

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

#122
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?

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

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

> Environment variables are often used to pass secrets around. But, despite its ubiquity, I believe that's a bad practice: I think environment variables are recommended to pass configuration parameters, and also secrets, in containerized applications managed by container orchestration systems. By design, other processes cannot inspect what environment variables are running in a container. Also, environment variables…

> By design, other processes cannot inspect what environment variables are running in a container.

That’s not exactly true. If a process is running in a container, and someone is running bash outside of that container, reading that processes environment variables is as simple as “cat /proc//environ”. If you meant that someone in one container cannot inspect the environment variables of a process running in a different container, that’s more true. That said, containers should not be considered a security boundary in the same way a hypervisor is.

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

#124

Earlier quoted context omitted.

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.

It isn't lock in, because all the application depends on is that it gets a string it can pass to exec/the shell and then reads all data from stdout until EOF as the secret.

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

#125

Earlier quoted context omitted.

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.

I do something similar. I usually have a flag, something like --password-file. It can only be used to specify a file containing the secret and at startup the application reads it.

Yes, this is also possible, but which the approach I stated, the secret can be generated by another program or received from the network, it isn't just limited to a file.

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

#126
post #61

Earlier quoted context omitted.

An infinitesimal leak becomes a problem if it is done an infinite number of times... execve seems like the preferable choice on a lot of grounds.

It would be a problem, except that the behaviour you're moving away from is a stale pointer. So surely any application that'd be leaking under that new behaviour would be crashing today.

The same advice applies to a correct program regardless of the implementation: using setenv is a bug. Only use getenv.

Getenv in a program without setenv is fine in both implementations. Setenv is unusable with all conforming implementations.

To pass environments to children, use execve.

The Linux behavior allows a careful single threaded program to use setenv correctly. The BSD/Solaris behavior makes all usage incorrect, but the incorrectness comes in the form of a memory leak, which is preferable to a security issue, usually.

There's no correct, portable use of setenv. If you call it, it's a bug.

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

#127
post #114

Earlier quoted context omitted.

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().

> You still don’t know if some library you use calls getenv()

Well, you can know, if you check their imported symbols. (I suppose they could be getting it via dlsym, but what are the odds of that...)

So if getenv_r() is added to the C library, and over time third party libraries started adopting it, you could get to the point that you could know no code in your process is calling getenv(), because none of the libraries your process loads import that symbol.

They could even add a glibc tunable to make getenv() call abort()... then you could be very sure nobody is calling getenv(), because if anyone ever did, boom

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

#128
post #61

Earlier quoted context omitted.

An infinitesimal leak becomes a problem if it is done an infinite number of times... execve seems like the preferable choice on a lot of grounds.

It would be a problem, except that the behaviour you're moving away from is a stale pointer. So surely any application that'd be leaking under that new behaviour would be crashing today.

No it always leaks, regardless if your program now correctly invalidates all derived pointers upon calling setenv.

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

#130
post #113

Earlier quoted context omitted.

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…

> I don't see how a user namespace does not prevent/limit privilege escalation.

They only prevent a single class of privilege escalation from setuid usage within the namespace. You can still obtain root using race conditions, heap overflows, side-channels, etc. or by coordinating with something outside of the namespace like a typical chroot escape.

Here's an old (patched) example of escaping the sandbox:

https://lwn.net/Articles/543273/

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

The consensus is that they're not security features on Linux. I'm not sure who sold you on the idea that they were, because that was not handed down by the kernel devs.

https://lwn.net/Articles/657744/

Post reply on HN