Hangfire icon indicating copy to clipboard operation
Hangfire copied to clipboard

Hide job arguments in hangfire dashboard for security

Open sebastienlabine opened this issue 5 years ago • 8 comments

Problem

I am using Hangfire and saw that every job arguments are logged as part of the available details of a job in the Hangfire dashboard.

However, some arguments should never be exposed to the dashboard. For example, when using hangfire with Identity, the IdentityUser information like the password hash and the security stamp of the user should not be seen in the dashboard.

public DoBackgroundJob(IdentityUser user) { /* */}

IdentityUser user = _userManager.findById(id);
BackgroundJob.Enqueue(() => DoBackgroundJob(user));

Result

image

As you can see, the fields "PasswordHash", "ConcurrencyStamp" and "SecurityStamp" are being exposed as well as other personnal information.

It's needless exposure and a security flaw, because if someone gains access to the dashboard maliciously, he could easily access to sensible information. Also, some people would love to be able to hide them for different reasons #1126 .

Solution

Provide the ability to mask some arguments by either allowing a custom Json Serializer, a list of classes to ignore when serializing or by having the options to turn off arguments logging.

sebastienlabine avatar Aug 01 '19 16:08 sebastienlabine

As explained in the Hangfire best practices, It is not recommended to serialized whole entities in the job arguments.

A solution to your problem would be to just pass the Id into the job, Then fetch that user and do work with it.

stevendesrochers avatar Aug 02 '19 11:08 stevendesrochers

I understand. However, isn't it counter productive?

For example, If I need to find do some task (not in the background) on a specific user, I access the DB, retrieve it than execute my task on it. After my task is executed, I need to send a notification (as a background task). I'll need to pass the id of the user, then retrieve it again which would make two database request for the sole purpose of security? Thinking of performance, that's really not optimal.

sebastienlabine avatar Aug 06 '19 21:08 sebastienlabine

@sebastienlabine I think you have raised a reasonable request for a feature but your example scenario is in my opinion not the best one to showcase the need for the request.

Usually the approach you have taken to expose the full user record wouldn't be recommended for other reasons and the suggestion provided by @stevendesrochers is very reasonable. I agree there may be a performance hit but it would be minimal. You can also store the Id in memory and avoid the database call.

In terms of your request, the ability to execute the job and via some key passed into the job retrieve more sensitive information is likely what most others are doing (I am doing this right now).

walizada avatar Aug 06 '19 21:08 walizada

Please act responsibly and store our personal information properly encrypted in a dedicated storage, and don't smear it on different parts of the system directly, otherwise it will be very hard if not impossible to comply with current and possibly upcoming laws like GDPR. There were enough recent data breaches to take this consideration seriously.

  • Performance doesn't play any role here as written above.
  • User data may be changed after creating a job and before executing it.
  • You likely don't need all of the properties above, and storing all of them is bad for performance too.

odinserj avatar Aug 07 '19 08:08 odinserj

Sorry to resurrect.

I have a similar requirement to obfuscate job arguments from the dashboard.

A different use case where I am creating job that requires a secure key to perform an action as a background task and would not like the input value to be visible in the Hangfire dashboard.

Although the reasons above make sense, this could be interpreted to mean:

  • "Dont use Hangfire for background jobs that might contain sensitive information"

Which I imagine is a majority of users of the library.

For now I am encrypting the arguments on queue and decrypting on action but again this is a performance hit.

Thanks for all the efforts with the project.

etherealbacon avatar Mar 05 '23 00:03 etherealbacon

+1 to this. I want to enqueue a series of jobs per customer and include an access token to call a 3rd party API without creating a new token from the STS service each time. The desired code is to get some 3rd party information per customer, and enqueueing jobs per customer allows a much greater control of failure scenarios than to just lump it all together and hope it doesn't take hours. This pattern also allows me to deal with 202's (HTTP Accepted) that have expected results against said 3rd party API, which have a turn around time of about 2 minutes and ensure I can track any failures per customer to figure out the why's individually. (Is it my STS service that doesn't have authorization on that customer [Business permission issues], or is it an actual networking problem?)

At the moment I'm refactoring things to try get around this and not log sensitive tokens, but I feel like obfuscating parameters on a job should really be available especially with POPI/GDPR/CPA/[Whatever your local is...] requirements now days.

DevlinSmith0 avatar Nov 23 '23 10:11 DevlinSmith0

+1. Even if the original request brings the wrong example, I'm really missing the feature.

MatteoSp avatar Feb 14 '24 17:02 MatteoSp

FYI: had to create an entirely new caching mechanism for injection on top of my ORM and STS integration in order to batch the jobs in the fashion I want (IE: 350 customer data acquisitions in parallel) just to avoid letting HangFire log customer/token data. I'm also hitting my Db way more times than before.

DevlinSmith0 avatar May 22 '24 07:05 DevlinSmith0