facet (rust) allows tagging fields as sensitive so they won't show up in logs: https://facet.rs/guide/attributes/#sensitive
I'm sure other languages have equivalents but I rarely see this.. for example I was about to say serde doesn't do it, but it looks like it's possible with a wrapper type? https://docs.rs/redactrs/latest/redactrs/
Anyway, this kind of tagging is good, I want more!
PuTTY has added a -pwfile option for use in ssh. If not exported, this interface is likely the best for non-key batch use. It seems much superior to sshpass.
The old .netrc format can be adapted for storage (which appears popular for curl), but I prefer sqlite databases, with permissions removed for all but the owner.
He's explicitly not using export, so they won't show up there. Plain variables are not in the environment.
(it's good to bring up this file as well as getting inherited by child processes though)
Oh, memfd_secret?
The memory areas backing the file created with memfd_secret(2) are visible only to the processes that have ac‐
cess to the file descriptor. The memory region is removed from the kernel page tables and only the page tables
of the processes holding the file descriptor map the corresponding physical memory. (Thus, the pages in the re‐
gion can't be accessed by the kernel itself, so that, for example, pointers to the region can't be passed to
system calls.)Before Linux 6.5, memfd_secret() was disabled by default and only available if the system administrator turned it on using "secretmem.enable=y" kernel parameter. [...]
"To prevent potential data leaks of memory regions backed by memfd_secret() from a hybernation image, hybernation is prevented when there are active memfd_secret() users."
What isn't visible to root? Maybe if you're willing to go down a really deep rabbit hole you can play that game, but I would generally explicitly exclude root from my threat model.
Your justification is the kind of thing I mention as out-of-scope (for my purposes!) in my conclusion:
> There are also many bases that I don’t cover and routes through which sufficiently-smart malware could easily still obtain the secrets I’m working with.
/proc/$pid/environ, /proc/$pid/mem and other such vectors (ptrace, bpftrace, equivalents on other platforms) are real, but:
- they're not vectors of _accidental_ leakage like dumping the full process environment to logs or shell history are
- they rely on privileged access existing at the time that I'm handling the secret, while logs or shell history can be obtained _in the future_
- they're not the kind of thing I expect broad-spectrum malware to go rooting for: the memory of all processes is a lot of data to classify/exfiltrate, and if I were a malware author I'd fear that that would be far too resource-intensive and thus conspicuous. Browser cookie storage, password manager databases, keylogging, and the like are much easier and more valuable pickings.
EDIT: FWIW, ksh93 also behaves like pdksh (inherited ksh88 feature?), while zsh behaves like bash. read -s was added to bash 2.04 (2000) and zsh 4.1.1 (2003, committed 2002), both long after the flag was used in ksh--at least as early as the initial pdksh commit to OpenBSD in 1996.
Android selected another fork, mksh, as their system shell. This is also included in Red Hat, along with ksh93.
I had read that zsh has strict emulation modes for ksh and bash. Is it possible that zsh behavior changes when those are triggered?
It doesn't look that way, at least looking at the option handling code in the read builtin (bin_read): https://github.com/zsh-users/zsh/blob/8a3ee5a/Src/builtin.c#...
The only allowed argument to POSIX read is "-r" which is enforced in Debian/Ubuntu by the dash system shell.
https://pubs.opengroup.org/onlinepubs/9699919799.2018edition...
[0]: https://www.man7.org/linux/man-pages/man1/keyctl.1.html
- It's not supported natively by most software (if I wanted to use it with `curl` for example, it would only be able to replace the `rbw` example since I still need to pass the secret to curl somehow);
- I don't think it's likely to gain widespread adoption, due to being a linux-specific API;
- The API itself suffers from some poor design choices, imho; it is not currently possible to set an expiry on a keyring entry without an intermediate state where the data is loaded but no expiry is set: https://lore.kernel.org/keyrings/ygar0hbrm05.fsf@localhost/T...
It's really nice as a concept and when you're developing an application where you control the entire flow of the secret data, but I don't see much practical value in it for general use cases. Exposing it as a filesystem could be a potential bridge for application support (something like `curl -H @</proc/self/keyring/@u/gitlab-authorization-header`?), though I suspect that wouldn't fly upstream because files aren't generally treated as carefully as explicit secret things. Non-enumerability (`-r` on `/proc/self/keying` and `/proc/self/keyring/*`) would help here, but I still seriously doubt that the keyring maintainers would find this to be a sane proposition :)
You don't need root to do what rootless podman does and create and work in directories that processes spawned from your normal user can't normally read using subuids. tmpfs to keep it off actual disks.
var=value some_command
This will still show up in /proc, but a lot of internal tools often rely on environment variables, so it’s kind of inevitable.
>op read "op://foo/bar/password"
>`$ token=$(rbw get gitlab-access-token) # get the token from a command-line password manager`
If you prepend your command with a space, it will not be added to your shell history.
>One way to avoid this is to prevent the command from being written to history. Bash has a configuration variable named HISTCONTROL, which when set to include ignorespace prevents commands prefixed with whitespace from being saved in history.
It helps with pasting special chars, newlines, and remote sessions without access to the local clipboard.
secret=$(vipe)
echo "$secret"
https://manpages.debian.org/jessie/moreutils/vipe.1It is very common for people to set environment variables for a server process from a config file that is readable by the application which is a bigger problem. At least put them a file that is only root readable (and have the process started by root).
(looking at you `gcloud`)
best practice I've heard is to create a user fs mount that prompts every time it's accessed?
I feel this is probably better than plain text, but if my machine gets popped while logged on you likely have Access to active browser sessions between MFA flows and could do more damage that way.
And then use these tips for when you want to interactively reference those stored secrets.
mpyne•3w ago
The command that needs the sensitive credential to be input is pointed to the FIFO and reads it, and nothing is left over on disk or in the shell's history or memory.
luckman212•3w ago
stouset•3w ago
Pretty simple. This creates a named pipe. One end of a shell command redirects to it, one end redirects from it. rm when finished.
akdev1l•3w ago
cat <(secret-print my-secret)
SoftTalker•3w ago
SoftTalker•3w ago
linuxhackerman•3w ago
What you've hinted at and what I didn't mention in the post is that this is indeed a good way to avoid even having the secret ever be a shell variable. It's a bit of extra fiddling to turn just the token into the Authorization header, but it's certainly possible, something like this:
curl -H @<(rbw get gitlab-access-token | sed 's/^/Authorization: Bearer/') https://gitlab.example.com/api/v4/projects