The MSDN documentation for the customErrors element states that it is implemented by System.Web.Configuration.CustomErrorsSection. If we use Red Gate's .NET Reflector to analyze that class, we can see where that setting is used in the Framework.
It is used by System.Web.UI.Page.HandleError and System.Web.HttpResponse.ReportRuntimeError.
Both of these end up calling System.Web.HttpResponse.RedirectToErrorPage. (The name of this method is confusing: it is important to note that RedirectToErrorPage takes the redirectMode setting as a parameter, so it is called even if you are using ResponseRewrite and no redirection actually happens.)
The relevant part of the RedirectToErrorPage method is:
if (redirectMode == CustomErrorsRedirectMode.ResponseRewrite)
{
this.Context.Server.Execute(url);
}
There doesn't appear to be any way to set the response code in the error handling: at the end of the day it's just a plain Server.Execute. It therefore seems unavoidable that you would need to write code to achieve the HTTP response you want.
Can you re-examine why you want to use a plain .html file? This seems a sensible choice for error handling, because you don't want to go through all the overhead of a .aspx page when that might cause another error to occur.
But perhaps there is some middle ground which will be just as robust as a .html file?
For example, you could make a precompiled HttpHandler, register it to the URL /500.error, and then make 500.error your defaultRedirect page. (This would be similar to how ScriptResource.axd works.) If you precompile your module into a DLL (as opposed to on-the-fly compilation from a plain old .axd file), you may find it is just as robust in the face of error conditions. If you encounter an error where not even this will work, then a static .html file probably won't work either -- keep in mind that the customErrors directive still relies on .NET running under the hood, and still uses the StaticFileHandler to serve your .html file.
Alternatively you could consider a reverse proxy in front of your IIS application which would serve a friendly 500 page even in the face of catastrophic failure of the application pool. This would be more work to set up, but would be even more robust than customErrors, e.g. if your web.config becomes corrupted, even customErrors won't work.