Preventing sensitive data leakage :sys.get_state in a GenServer

So, I know about Process.flag(:sensitive, true) and format_status/2. But even if I do everything recommended by https://erlef.github.io/security-wg/secure_coding_and_deployment_hardening/sensitive_data , :sys.get_state/1 still exposes sensitive data. For now I’ve converted the state of my GenServer to a struct with a custom inspect protocol implementation. It works, but I feel this is suboptimal.
How do you prevent leakage through :sys.get_state?

I don’t know the answer to your question regarding:sys.get_state, but maybe you could put some of that state in a private ETS table?

The recommendations in that chapter are primarily about accidental leakage outside of the BEAM, e.g. through logs or stacktraces reported to application monitoring services. It is virtually impossible to hide information within the BEAM from other processes (see also the chapter on sandboxing).

2 Likes

Thank you for the answers, I wasn’t clear enough about the risks I wanted to prevent. The ‘attack’ scenario here was something like a client or colleague hovering around or maybe an intern trying out sys functions.

My issue here was mainly that it felt wrong that we could use format_status to prevent poking from :sys.get_status, Process.flag to prevent from poking from observer and a host of other debug functions… yet I couldn’t find an obvious way to prevent leaking from sys.get_state. However encoding the state as a struct and implementing the inspect protocol for it solves the issue for my scenario, I was just surprised it wasn’t covered by the other steps.

It doesn’t though, does it? If someone is actively poking around they can just disable the Inspect protocol: IO.inspect(:sys.get_state(process), structs: false), or they can turn your struct into a plain map: Map.delete(:sys.get_state(process), :__struct__)

3 Likes

You’re correct. Well it does prevent shoulder surfing, but not actually poking.
For now I’ll avoid providing remshell access to anyone.
I still think it would be nice if there was a way to protect GenServer state from being poked at. But I can live with that.