Live data from Hacker News

Keeping secrets out of logs (2024)

allan.reyes.sh

41–50 of 56 posts

Re: Keeping secrets out of logs (2024)

#41
post #20

Earlier quoted context omitted.

Why is logging everything considered lazy?

for one it's extremely costly, in vcpu , storage , transfer rates. and if you're paying a third-party logger , multiply each by 10x

Axiom wants $60/m if you send them a terabyte of logs, which is basically nothing compared to the cost of developers trying to debug issues without detailed logs.

Re: Keeping secrets out of logs (2024)

#42

> If you shift from “any string can be a secret” to “secrets are secrets”, it makes things a lot easier to reason about and protect. > const secret = new Secret("...") one of those things that's obvious in retrospect. That's a cute trick I'll definitely be stealing.

.NET has SecureString: https://learn.microsoft.com/en-us/dotnet/api/system.security... Which reminds me of why I hate tiny standard libraries as seen in JavaScript: features like SecureString work only if they're used pervasively. It has to be in the std lib and it has to be used everywhere so that you almost never have to unwrap them. It's critical that credentials are converted to SecureString as soon as possible a…

Copying GC also have to cooperate with this SecureString feature, so you won't accidentally keep hanging secret in heap dump. Old Java API has the tendency to use `char[]` for secrets. You can zero it after use, so old reference will not contain useful data, but you can't protect it from copying GC, so it might still gets leaked in raw heap dump, even after zeroing it out.

Re: Keeping secrets out of logs (2024)

#43

As far as run-time exposure prevention goes, I feel like in-band signaling might work better than out-of-band for this problem. Along the lines of the taint checking technique mentioned, you can insert some magic string (say, some recognizable prefix + a randomly generated UUID) into your sensitive strings at the source, that you then strip out at the sink. (Or wrap your secrets in a pair of such magic strings.) Then…

Can you elaborate on the situations and reasons that would make this approach appropriate? At first sight it seems a complicated and inferior approximation of techniques from the article: not automatically single use, not statically checked, somewhat error prone for proper secret usage, not really preventing well-intentioned idiots from accidentally extracting, "laundering" and leaking the secret, removing secrets fr…

Also may need to handle special cases where entry is truncated so you get incomplete opening/closing pairs (i.e. quirks mode for log parsing?)

Re: Keeping secrets out of logs (2024)

#44

With java theres a GuardedString implementation https://docs.oracle.com/en/middleware/idm/identity-governanc...

Those are primarily for in-memory security. They apparently uses a "known default key" in its serialized form. At least when it comes to logging, that's more like obfuscation than security.

Re: Keeping secrets out of logs (2024)

#45
post #27

Earlier quoted context omitted.

That makes it foolish, but I'm not sure if it's lazy.

the lazy part comes from the fact that it's easier to be foolish in this case than to be selective about what gets logged. So lazy & foolish.

it's not lazy, it's a good use of time, you don't go back and forth when you realize you forgot to log something important.

Re: Keeping secrets out of logs (2024)

#46
post #7

Great article! I will definitely reference it in my upcoming discussions. I had some hard time defending having an EU based o11y stack for our EU based infra. I found it hard to articulate on the spot that there are myriads of places where sensitive/personal data can get in the logs and cause leaks, or make GDPR angry.

Why do I have to know how many letters are in observability? is this some kind of in group signaling?

you don't need to know, just consider it a new word that's a synonym, and happens to kind of look like o--y

Re: Keeping secrets out of logs (2024)

#48
post #44

With java theres a GuardedString implementation https://docs.oracle.com/en/middleware/idm/identity-governanc...

Those are primarily for in-memory security. They apparently uses a "known default key" in its serialized form. At least when it comes to logging, that's more like obfuscation than security.

According to its documentation, you can’t directly log a GuardedString because it doesn’t implement the toString() method. You have to pass it an accessor instance through its access() method to extract the plaintext.

Re: Keeping secrets out of logs (2024)

#49
post #15

oh god - I had that come up in an issue at work just about a month ago. A development system used really simple usernames and passwords since it was just for testing but all the lines with one of those got gobbled up because they had "secrets" in them. I have very strong opinions on this issue that boils down to. _why are you logging everything you lazy asses_ and _adding all the secrets into another tool just to sca…

Why is logging everything considered lazy?

First "everything":

Logging "everything" could include stack traces and parameter values at every function call. Take the information you can get from a debugger and imagine you log all of it. Would that be necessary to determine why a defect is triggered?

Second, "lazy":

Logging has many useful aspects, but it is also only a step or two above adding print statements to the code, which again leads to the "lazy." If you have the inputs, you should be able to reproduce the execution. The exceptions include "poorly" modularized code, side effects, etc.

Alternatives.

I've found it helpful for complex failures to make sure that I include information about the system. For example, the program couldn't allocate memory: Was it continuous chunks of memory or a memory leak? How much free memory is there, versus the shapes of the free memory (Linux memory slabs)? What can I do to reset this state? (reboot was the only option)

Finally, a quote a colleague shared with me when I once expressed my love of logging. In the context of testing online games:

"Developers seem drawn to Event Recorders like moths to a flame. Recording all game/ mouse/ network/ whatever events while playing the game and playing them back is a bad idea. The problem is that you have an entire team modifying your game's logic and the meaning or structure of internal events on a day-to-day basis. For The Sims Online and other projects, we found that you could only reliably replay an event recording on the same build on which it was recorded. However, the keystone requirement for a testing system is regression: the ability to run the same test across differing builds. Internal Event Recorders just don't cut it as a general-purpose testing system. UI Event Recorders share a similar problem: when the GUI of the game shifts, the recording instantly becomes invalid."

Page 181, "Section 2.1 Automated Testing for Online Games by Larry Mellon of Electronic Arts", in Massively multiplayer game development 2, edited by Thor Alexander, 2005

Re: Keeping secrets out of logs (2024)

#50

As far as run-time exposure prevention goes, I feel like in-band signaling might work better than out-of-band for this problem. Along the lines of the taint checking technique mentioned, you can insert some magic string (say, some recognizable prefix + a randomly generated UUID) into your sensitive strings at the source, that you then strip out at the sink. (Or wrap your secrets in a pair of such magic strings.) Then…

Can you elaborate on the situations and reasons that would make this approach appropriate? At first sight it seems a complicated and inferior approximation of techniques from the article: not automatically single use, not statically checked, somewhat error prone for proper secret usage, not really preventing well-intentioned idiots from accidentally extracting, "laundering" and leaking the secret, removing secrets fr…

I mean, I very much disagree on this being "complicated and inferior". But none of these techniques are substitutes for each other. Like the article said, there are a lot of lead bullets, no silver ones. You absolutely should deploy whatever techniques you can. All I was saying was that I think this one, on its own, would handle a larger set of cases than some of the other (run-time) ones listed.

But one big reason I suggested this technique is that you want the object to keep protection on the String while having it look and feel as much like the underlying contents as possible, so that the final unsealing can occur as little (& as late) as possible. The more warts you put around your secret, the less usable it will be. You thought you made the Secret "single-use", but what you really did was to just encourage someone to keep the unsealed String around and reuse that, because you gave them a Secret type and they needed a String type. And now you have no way to detect if they accidentally log it, or throw an exception with some local variable containing it. Whereas this technique would still immediately catch any leakage in those cases.

Again: this technique is a supplement, not a substitute. You absolutely should still add static checks where you can. Have your Secret type too. The point here is that your Secret.unseal() method can still return a String that is useful for callers while offering you some protection on the value, instead of instantly going from protected->unprotected and exposing the contents with zero protection.

Post reply on HN