Published on:Dec 01, 2016
Views: 13769
Number of votes: 11
Average rating:

Security checklist for Episerver or .NET website

So you have built a great website for your customer, but is it secure? Code review your solution for these top issues. 

Added some levels to indicate in what order I would do them in. 

  • Level A - Most important fixes / low effort that all sites should have yesterday.
  • Level AA - Important / medium effort
  • Level AAA - If you complete these you are probably top 1% of the sites out there in terms of security.

Level A

  • Use Https

    Without https you are wide open for a whole bunch of man-in-the-middle (MITM) attacks. Don't release a site without it. Use it on the entire site and not only on the logged in part. Check that you are using at least TLS 1.2 and disallow older versions
    You can also add the following to global.asax for older .NET versions (4.5) for application start to force all outgoing requests to use TLS 1.2

    ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
  • Secure edit and admin mode

    For the strongest security, use a separate editor server node. If the public server doesn't even have publishing capabilities, that part is much more secure. Check option 2 on the url below:

    Shut down edit mode on public web front

      <location path="episerver">
            <deny users="*" />

    If you can't afford it, at least choose hard-to-guess custom urls for util and cms and force your editors to use strong passwords.

    Another cheaper option instead of a separate editor server is to use ip restrictions for the relevant directories to lock the server down.

            <ipSecurity allowUnlisted="false" denyAction="NotFound">
                <add allowed="true" ipAddress="123.456.0.0" subnetMast=""/>
    • Secure cookies

      For an https site, your session cookies and authentication cookies should be marked as secure. Small fix to web.config required. Might need to have a few lines of code in the end request event in global.asax to handle the authentication cookie as well. See

            <httpCookies requireSSL="true" />
    • Turn off detailed errors and set compilation mode to release

      Easily done in web.config.

    • Avoid click jacking attacks

      Add a response header for X-Frame-Options.

              <add name="X-Frame-Options" value="SAMEORIGIN" />
    • Restrict editors

      Give them the least access rights needed and avoid making shared accounts. If something goes wrong, you want to know who did what. Use WebEditors to give access to edit mode only and a separate role to give access to the part of the content tree "Editors_Sweden, Editors_Norway" or similar. 

    • Remove test users

      Especially all admin accounts to EPiServer and similar that was used during development needs to be deleted before launch.

    • Use a service account for scheduled jobs and similar

      It happens that the developer uses his own account instead of creating a separate service account to run scheduled jobs. Don't.

    • Check that your search result page (SRP) never displays secured content.

      Depending on search solution, this can be a problem. I've seen it a couple of times that excerps are shown on the SRP of secured content to the anonymous user. Double check that pages in waste basket isn't shown.

    • Check that pages in waste basket is not shown / crashes site

      If you list content in any way by using GetChildren / FindPagesByCriteria in the background, make sure you filter your list for access rights before displaying them. EPiServer controls do this out-of-the-box but if you use custom code to render your lists/menus you will have to solve this problem to avoid any issue. Test by sending some content to wastebasket and check that they are handled correctly. They should not be visible in menus or in search results for instance.

    • Move your log files

      Having your log files in web root is not a good idea from a security point of view. EPiServer has log4net as logging tool and by default they end up in webroot if you turn on logging. They should ideally be on a separate harddrive (since it happens that too large log files crash the website).

    • IIS File access rights

      Double check that your file access rights are correct and that noone added full access rights for everyone when they were troubleshooting something. Check this url if you are unsure:

    • Email is not a secure channel

      Never send passwords and similar on email. Send a temporary link instead.

    • Remove unused membership providers

      If you don't use your windows membership provider, remove it.

    • Turn off detailed error messages for WCF
                      <serviceDebug includeExceptionDetailInFaults="false" />
    • Check vulnerabilities in used frameworks node modules / nuget
      Easy to do with npm audit if you are using node modules. Running an audit using chrome will also show javascript vulnerabilities. 
      Check nuget packages with tools like Audit.Net visual studio plugin. Locking external packages to a specific version to avoid automatic upgrades by build servers is a good idea. Using signed packages if possible is another, especially for secondary feeds like a private feed. Beware of private package high jacking detailed below if you are using multiple package sources. 

    • Avoid leaking user data to countries you do not trust with frontend scripts (GDPR)
      Some scripts like google analytics and hotjar provide great functionality but is also a security risk that needs to be discussed. How much user data from your site are you willing to let someone else in another country control? You can easily see to which country you are sending user data to using running this script in your google chrome console window

    • Require strong passwords

      Long passwords beat complex passwords. A minimum of 9 characters is recommended. Preferably more if your users don't start screaming too loud. This is easy to configure on your membership provider in web.config. Make it possible to copy passwords to enable password managers to work well.

    Level AA

    • Check SSL certificate

      Old versions of protocols and algorithms are vulnerable to attacks. Use for instance: or
      to check if you are using the latest and greatest without known security holes.

    • Prevent cross site forgery

      Do use the [ValidateAntiForgeryToken] attribute in MVC controller for post actions and @Html.AntiForgeryToken() in your views. Check out some nasty example on

    • Have a company security feedback process
      If Troy Hunt says jump the proper response is "How high?". Seriously though. You need to have a feedback function on your website where people can report security issues in a safe way. The proper response to someone reporting a security issue is "Thank you. We will look into it." 
      If you fail on this it might mean that someone decides to report the issue to the local paper instead to warn of an unsafe site. You don't want that
    • Double check your content caching strategies

      Make sure you never cache non-public content. E.g. if you cache the menu (that is filtered on access rights) and you then surf around with an admin user followed by an anonymous user you might show menu items that only admins should see to the anonymous user. Normally you don't need to cache EPiServer content lists if you just use GetChildren. EPiServer does that for you.

    • Secure your data layer

      Make sure you use an ORM like EF that doesn't allow SQL injections and that you never ever string concat an SQL statement together. If you run SQL stored procedures it might be worth checking those for string concatenation as well. I've seen some ugly code hidden there as well...

    • Secure your service layer

      For websites that are more application oriented, it's wise to secure your service layer so that some functions are only available to certain roles e.g. delete user can only be run by someone logged in as administrator. It's easy to solve this by simply hiding the button for this in the presentation layer but a more secure way is to add it above your service layer. I use custom attributes and AOP for this but the exact implementation is less important.

    • Lock down webservices and handlers

      It's easy to get lazy when EPiServer is handling security for content out-of-the-box. Check through your solution for other access points that the solution uses like webservices, web api, handlers etc and secure them / validate all input.

    • Lock down plugins and other .NET files

      Check if you have admin/editor plugins, regular aspx files and similar and secure them. This can normally be done easily by adding a location tag in web.config and restrict it to a certain role

    • Validate querystring params

      Similar to the one above but easier to forget but equally important. Let's avoid those pesky sql injections and similar...

    • Html encode all output (XSS)

      Especially important for all data that comes from other systems / user input to avoid javascript cross site scripting (XSS) attacks.

      For webforms, check that you are using webcontrols that support htmlencoding or the

      <span class="label label-info"><%#: Item.QuestionNumber %></span>

      If you are using MVC, use the standard Model. syntax and stay away from Html.Raw as much as possible.

    Level AAA

    • Enable HSTS
      This is used to secure https one step furter to disallow any http requests whatsoever. If you only use a http => https redirect it leaves a security hole where a man-in-the-middle can hijack the request.
    • Protect vs XXE (Xml Extended Elements)
      Read more here. Part of OWASP top 10 list. 
      Avoid using XmlTextReader at all and make sure you have .NET version 4.6 or higher and you should be pretty safe.
      If you have to use XmlTextReader use
      XmlTextReader myReader = new XmlTextReader(new StringReader(xml));
      myReader.DtdProcessing = DtdProcessing.Prohibit;​
    • Use Content Security Policy, CSP to protect against XSS attacks

    • Use a single package source for nuget / node packages
      If you don't you will likely be vulnerable to supply chain attacks. If you decide to use multiple sources like an additional private package source you will need to add extra security measures. This is because it's possible to create a new version of your private package on the public package source which will then be downloaded instead. Having a single package source protects against this. Signed packages and locking down versions to a specific version to avoid automatic upgrades on CI server also helps reducing risk.  

    If you went through this checklist you will hopefully have a more secure site than you had before. Do check out the OWASP top 10 for 2017 official recommendations as well. Nothing is unbreakable of course but let's avoid the obvious security holes at least. Ending up in the news because your website got hacked is not fun. 

    Dec 01, 2016

    ( 6/17/2015 4:39:07 PM)

    Great list Daniel!  This covers many of the OWASP points. 

    I'd add to this to remember to secure any plugin URLs you add for custom plugins.  If you have a folder called Plugins for example simply add another Location node in your web.config to secure ~/Plugins

    ( 6/17/2015 6:56:34 PM)

    Where did the "Test this websites security" button go? ;-)

    ( 6/17/2015 7:21:49 PM)

    They got the message Oerjan :)

    Lets leave it at that, sorry for my poor sense of developer humor.

    ( 6/18/2015 8:53:58 AM)

    I added your suggestion to the list Janaka. I've seen some admin plugins that wasn't secured correctly so it's definitely something to think about.

    Arve Systad
    ( By Arve Systad, 6/22/2015 9:56:24 AM)

    Neat list, but regarding validating user input: I'd rather do things properly and protect myself against SQL attacks in other ways than not letting "Dr. Ing. John-Peter Mc'Doe" register with his proper name. And for email-adresses, you can be pretty sure to miss out on something that's actually allowed by using one of the thousands of "email regexes" out there. I know 99% of people will do just fine with just [a-Z] in the name, but for those pesky exceptions, it's going to be a nightmare to use your site.

    Protect against SQL injections by using properly protected existing APIs, or parameterized SQL if you're doing that part yourself.

    ( 6/22/2015 8:05:41 PM)

    So to sum up Arve:

    Yes to using existing API and parameterized SQL

    No to storing any user input as name or email or any text field without server validation vs white list of characters. Too risky for XSS if nothing else.

    Henrik Fransas
    ( By Henrik Fransas, 6/23/2015 9:11:24 AM)

    I will also add the possibility to secure the editing part with ip-restrictions so you are only alowing users that are logged in to your own network to access it.

    Nice list, thanks a lot!

    ( 6/23/2015 9:18:25 AM)

    That's a decent cheap solution instead of having a separate server for editors. Definitely a useful option that I'll add to the list, thanks for the input!

    ( 6/23/2015 11:29:34 AM)

    Yes, message received.

    I've blocked script inclusions in blog posts, at least the most obvious way of doing it. If you used some other trick please don't blog about it - drop us a line at :)

    ( 5/10/2016 10:23:40 AM)

    Updated post with a few more items and some examples...

    ( 6/15/2016 1:12:28 PM)

    Updated post after my latest PEN test and OWASP test of a new website with some SSL suggestions...PEN test went great btw :)

    ( 12/1/2016 3:06:38 PM)

    Updated with some more tools from mr Jones

    ( 12/1/2016 4:04:52 PM)

    Hmm, wonder why it was dated to 1st of december 2016 again just because I updated it. Oh well...nm :)

    Arve Systad
    ( By Arve Systad, 12/1/2016 7:58:14 PM)

    I'd just say "Use HTTPS" regardless of anything. It's cheap and ensures the integrity of your site, even if you have no log-in-functionality. Ever used In flight-WIFI that puts ads on your site? This is in practice a man-in-the-middle-attack, which is not possible if running on HTTPS.

    ( By valdis, 12/8/2016 9:41:03 PM)

    Chrome will get you warnings in your face when site is not running on HTTPS. I would say - that's not recommendation, but demand instead.

    ( 8/30/2017 9:40:16 AM)

    Here two pages that can test your site security.

    However, verify the implementation on a dev/test/stage environment first, before it is placed at a production environment.

    Daniel Ovaska
    ( By Daniel Ovaska, 2/25/2021 9:57:57 AM)

    Updating with information about high jacking private package sources if you are using multiple sources for nuget / node etc.

    Please login to comment.