0

I've inherited a legacy internal site written using ASP.NET MVC. It uses Elmah to mail uncaught exceptions. Unfortunately, those emails contain sensitive information, such as passwords. Following this guide, I implemented this ErrorLogModule class to remove sensitive fields from the error reports:

using Elmah;
using System.Linq;
using ElmahErrorLogModule = Elmah.ErrorLogModule;

namespace HRCommittee
{
    // method taken and modified from https://stackoverflow.com/a/24914392/713735
    public class ErrorLogModule : ElmahErrorLogModule
    {
        protected override void OnErrorSignaled(object sender, ErrorSignalEventArgs args)
        {
            string[] serverVariables = args.Context.Request.ServerVariables.AllKeys;
            string[] varsToRemove = { "AUTH_PASSWORD", "HTTP_COOKIE", "ALL_HTTP", "ALL_RAW" };

            if (serverVariables != null)
            {
                foreach (string var in varsToRemove)
                {
                    if (serverVariables.Contains(var))
                    {
                        args.Context.Request.ServerVariables.Remove(var);
                    }
                }
            }

            base.OnErrorSignaled(sender, args);
        }
    }
}

However, the emails are unchanged. Furthermore, after implementing the above code, I saw that someone else had placed a file identical to the guide I linked in another location, but also without success. Since Elmah is pretty much undocumented, and I'm quite new to the Microsoft stack, I've been struggling to figure out what's wrong.

By the way, the relevant entries in web.config tell a bit of the story of what has been tried:

<system.webServer>
    <modules>
      <remove name="FormsAuthentication" />
      <!--<add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" preCondition="managedHandler" />-->
      <!--<add name="ErrorLog" type="HRCommittee.App_Start.ErrorLogModule" preCondition="managedHandler" />-->
      <add name="ErrorLog" type="HRCommittee.ErrorLogModule" preCondition="managedHandler" />
      <add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah" preCondition="managedHandler" />
      <add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah" preCondition="managedHandler" />
    </modules>
    <!-- other stuff -->
</system.webServer>

What am I missing?

Update

I've set up a local SMTP server, run the site locally, and triggered an exception thus (copying existing code in the project):

try
{
    throw new Exception("Test message");
}
catch (Exception e)
{
    AccountController.LogToElmah("Error Saving Form", e);
}

In this case, the emails are redacted as expected. I tried it with and without the change to web.config suggested by Haney, with no difference in outcome. I'm now waiting for a production error to be thrown again, but I'm not anticipating any change. The plot thickens.

Scott Severance
  • 943
  • 10
  • 27

2 Answers2

0

In ASP.NET, adding modules via web.config requires a specific Type format of "Class, Assembly". For your case, it is currently:

<add name="ErrorLog" type="HRCommittee.ErrorLogModule" preCondition="managedHandler" />

It needs to be this:

<add name="ErrorLog" type="HRCommittee.ErrorLogModule, HRCommittee" preCondition="managedHandler" />

Replace HRCommittee with whatever the assembly that's being compiled is actually named.

Haney
  • 32,775
  • 8
  • 59
  • 68
  • Thanks for the reply. Unfortunately, it doesn't seem to make a difference either way. However, see my update to the OP for additional information I've learned. – Scott Severance Jul 25 '23 at 21:23
0

While implementing your own module can be a valid solution, I think that it is much simpler to just use error filtering to modify each error before sending it to ELMAH.

In your Global.asax.cs file include code like this:

void ErrorLog_Filtering(object sender, ExceptionFilterEventArgs args)
{
    var httpContext = args.Context as HttpContext;
    if (httpContext != null)
    {
        var error = new Error(args.Exception, httpContext);
        
        // TODO: iterate over server variables, etc. in the error object to remove sensitive data

        ErrorLog.GetDefault(httpContext).Log(error);
        args.Dismiss();
    }
}

What the code basically does it to dismiss all errors logged to ELMAH but create a new one where you are in better control of what is being logged.

Source: https://blog.elmah.io/enrich-elmah-errors-using-error-filtering-hook/

ThomasArdal
  • 4,999
  • 4
  • 33
  • 73
  • Thanks. This is helpful. One challenge, though. `ErrorLog.GetDefault(httpContext).Log(error)` logs the error to the database, but doesn't email it. I can't find an equivalent that sends email. That's how the existing code works. But this doesn't change what gets emailed. – Scott Severance Jul 26 '23 at 19:55
  • Oh I see. What if you use `ErrorSignal.FromContext(httpContext).Raise(error);` instead of the `Log` call? – ThomasArdal Jul 27 '23 at 06:31