{"id":7126,"date":"2026-01-15T14:53:10","date_gmt":"2026-01-15T19:53:10","guid":{"rendered":"https:\/\/andreas-wolter.com\/?p=7126"},"modified":"2026-01-16T13:43:56","modified_gmt":"2026-01-16T18:43:56","slug":"2026_sqlserverdatabaseapplicationsecurityandhighavailabilitychecklist_v2","status":"publish","type":"post","link":"https:\/\/andreas-wolter.com\/en\/2026_sqlserverdatabaseapplicationsecurityandhighavailabilitychecklist_v2\/","title":{"rendered":"The SQL Server Database Application Security &#038; High Availability Checklist by Sarpedon Quality Lab &#8211; Version 2"},"content":{"rendered":"\n<style type=\"text\/css\" data-created_by=\"avia_inline_auto\" id=\"style-css-av-m0cxh8ps-e3e17b0c3bbc76a457cff32a82c11519\">\n#top .av-special-heading.av-m0cxh8ps-e3e17b0c3bbc76a457cff32a82c11519{\npadding-bottom:10px;\n}\nbody .av-special-heading.av-m0cxh8ps-e3e17b0c3bbc76a457cff32a82c11519 .av-special-heading-tag .heading-char{\nfont-size:25px;\n}\n.av-special-heading.av-m0cxh8ps-e3e17b0c3bbc76a457cff32a82c11519 .av-subheading{\nfont-size:15px;\n}\n<\/style>\n<div  class='av-special-heading av-m0cxh8ps-e3e17b0c3bbc76a457cff32a82c11519 av-special-heading-h3 blockquote modern-quote  avia-builder-el-0  el_before_av_textblock  avia-builder-el-first '><h3 class='av-special-heading-tag'  itemprop=\"headline\"  >The SQL Server Database Application Security <span class='special_amp'>&amp;<\/span> High Availability Checklist by Sarpedon Quality Lab<\/h3><div class=\"special-heading-border\"><div class=\"special-heading-inner-border\"><\/div><\/div><\/div>\r\n\r\n<section  class='av_textblock_section av-m0cxgkjy-c935304b4106b45214698f40e83a9894 '   itemscope=\"itemscope\" itemtype=\"https:\/\/schema.org\/BlogPosting\" itemprop=\"blogPost\" ><div class='avia_textblock'  itemprop=\"text\" ><p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-large wp-image-7127\" src=\"https:\/\/andreas-wolter.com\/wp-content\/uploads\/2026\/01\/2026_01_DatabaseApplicationSecurityChecklistSQL-1030x659.png\" alt=\"Database Application Security Checklist\" width=\"1030\" height=\"659\" srcset=\"https:\/\/andreas-wolter.com\/wp-content\/uploads\/2026\/01\/2026_01_DatabaseApplicationSecurityChecklistSQL-1030x659.png 1030w, https:\/\/andreas-wolter.com\/wp-content\/uploads\/2026\/01\/2026_01_DatabaseApplicationSecurityChecklistSQL-300x192.png 300w, https:\/\/andreas-wolter.com\/wp-content\/uploads\/2026\/01\/2026_01_DatabaseApplicationSecurityChecklistSQL-768x492.png 768w, https:\/\/andreas-wolter.com\/wp-content\/uploads\/2026\/01\/2026_01_DatabaseApplicationSecurityChecklistSQL-705x451.png 705w, https:\/\/andreas-wolter.com\/wp-content\/uploads\/2026\/01\/2026_01_DatabaseApplicationSecurityChecklistSQL.png 1200w\" sizes=\"auto, (max-width: 1030px) 100vw, 1030px\" \/><\/p>\n<p>As a database application vendor, the security and reliability of your software are key competitive differentiators. As a Database Administrator, your priority is ensuring that hosted databases do not expose data or the environment to risk. To support this, we have developed a checklist designed as a blueprint for building secure-by-default, resilient data applications. Following this guidance not only helps you align with ISO 27001 controls but also ensures that your customers can trust your product against the backdrop of a demanding enterprise environment and an evolving threat landscape.<\/p>\n<p>This list is also available as pdf here: <a href=\"https:\/\/andreas-wolter.com\/wp-content\/uploads\/2026\/01\/SQLServerDatabaseApplicationSecurityandHighAvailabilityChecklist.pdf\">SQLServerDatabaseApplicationSecurityandHighAvailabilityChecklist.pdf<\/a><\/p>\n<p><strong>Version 2, 2026\/01\/15<\/strong><\/p>\n<p>This list is structured into 3 buckets:<\/p>\n<ul>\n<li>Deployment Security<\/li>\n<li>Operational Security (Data Protection &#038; Code Integrity)<\/li>\n<li>High Availability and Business continuity<\/li>\n<\/ul>\n<h2>1) Deployment Security<\/h2>\n<table>\n<tbody>\n<tr>\n<td width=\"151\"><strong>Checklist item<\/strong><\/td>\n<td width=\"409\"><strong>Details<\/strong><\/td>\n<\/tr>\n<tr>\n<td width=\"151\"><strong>(D1)<br \/>\nCan the database be pre-deployed by a DBA?<\/strong><\/td>\n<td width=\"409\">Ideally, the DBA should be able to provision an empty database, after which the application setup can be pointed to that database and take full responsibility for creating the database schema and all required objects.<br \/>\nThis has 4 advantages:1.\u00a0\u00a0\u00a0\u00a0\u00a0 Eliminates the need for server-level permissions, even on a temporary basis.2.\u00a0\u00a0\u00a0\u00a0\u00a0 Simplifies a potential future migration to Azure SQL Database.<\/p>\n<p>3.\u00a0\u00a0\u00a0\u00a0\u00a0 Provides the most efficient deployment workflow for Contained Availability Groups (also see here my remarks on <strong><em>Deployment<\/em><\/strong>: <a href=\"https:\/\/andreas-wolter.com\/en\/2504_sqlserver_contained_availability_groups\/\">Why you should use SQL Server contained availability groups to save time \u2013 and why consultants may not tell you about them<\/a> )<\/p>\n<p>4.\u00a0\u00a0\u00a0\u00a0\u00a0 Allows the DBA to optimize file placement which for fast-growing systems will become necessary eventually. The physical layout of your database should be transparent to the application and database-code.<\/td>\n<\/tr>\n<tr>\n<td width=\"151\"><strong>(D2)<br \/>\nPermissions for database-deployment<\/strong><\/td>\n<td width=\"409\">If (D1 is impossible)<br \/>\nThe database-creation phase of an application setup should typically require no more than the CREATE ANY DATABASE permission.<br \/>\nIf SQL Agent jobs are involved, use the msdb roles (<a href=\"https:\/\/learn.microsoft.com\/en-us\/ssms\/agent\/sql-server-agent-fixed-database-roles\" target=\"_blank\" rel=\"noopener\">SQL Server Agent fixed database roles<\/a>)-\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Other server level objects, if required, usually have distinct permissions as well.<strong>Membership in the sysadmin role is never required.<\/strong><\/p>\n<p><strong>Access to the Windows Host such as local Windows Administrator is never required.<br \/>\n<\/strong>&#8211; All Database-files are created by the SQL Server Service account. No user or application-account must have access to SQL Server\u2019s data folders, as this may allow the user to corrupt files.<\/td>\n<\/tr>\n<tr>\n<td width=\"151\"><strong>(D3)<br \/>\nRemove server-level permissions after setup<\/strong><\/td>\n<td width=\"409\">If your application requires server-level permissions during setup, ensure that all such permissions can be revoked once setup is complete. Elevated privileges should be temporary and strictly limited to the installation phase.<\/td>\n<\/tr>\n<tr>\n<td width=\"151\"><strong>(D4)<br \/>\nDedicated secure application identity<\/strong><\/td>\n<td width=\"409\">Support using <strong>Group Managed Service Accounts<\/strong> (gMSA) for the Application service account, especially if it connects to database.<br \/>\n(Using gMSAs provides automatic password management, reducing the risk associated with long-lived or manually managed passwords.)<\/td>\n<\/tr>\n<tr>\n<td width=\"151\"><strong>(D5)<br \/>\nUse Windows Authentication<\/strong><\/td>\n<td width=\"409\">Use Windows Authentication instead of SQL Authentication to avoid transmitting and storing passwords. Requiring SQL Authentication may require the customer to prepare a dedicated SQL Server, as SQL Authentication is an Instance-level configuration and increases the attack-vector for all databases on the system.<\/td>\n<\/tr>\n<tr>\n<td width=\"151\"><strong>(D6)<br \/>\nSecure Credentials<\/strong><\/td>\n<td width=\"409\">If SQL Server Authentication is required, ensure the setup enforces strong password policies and that <strong>connection strings<\/strong> are <strong>encrypted<\/strong> and <strong>never stored in plain text<\/strong> in config files.<\/td>\n<\/tr>\n<tr>\n<td width=\"151\"><strong>(D7)<br \/>\nLeast privileges for temporary files<\/strong><\/td>\n<td width=\"409\">When the deployment involves importing data from the file system using <strong>BULK INSERT<\/strong>, use a dedicated folder (network Share) and only grant the SQL Server Service account Read-permissions. &#8211; The application account does not need access to the files when using BULK INSERT.<\/p>\n<p>For exporting data to the file system, the required permissions depend on the method used (e.g., bcp, SSIS, or custom code) and the account performing the operation.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2>2) Operational Security (Data Protection &#038; Code Integrity)<\/h2>\n<p>These are the operational standards that protect the database itself, addressing the most common application-level security-risks.<\/p>\n<table>\n<tbody>\n<tr>\n<td width=\"151\"><strong>Checklist item<\/strong><\/td>\n<td width=\"409\"><strong>Details<\/strong><\/td>\n<\/tr>\n<tr>\n<td width=\"151\"><strong>(O1)<br \/>\nPermissions \u2013 Comply with the Principle of Least Privilege<\/strong><\/td>\n<td width=\"409\">Application user accounts should <strong>not require membership in the db_owner role<\/strong>\u2014let alone ownership of the database itself.<\/p>\n<p>Most applications operate correctly with the following database database roles respectively permissions:<\/p>\n<p>\u00b7\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 db_datareader<\/p>\n<p>\u00b7\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 db_datawriter<\/p>\n<p>\u00b7\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 EXECUTE permission on the database (preferably via a dedicated database role to comply with the LURP-model*)<\/p>\n<p>CREATE DATABASE ROLE db_executor<\/p>\n<p>GRANT EXECUTE to db_executor<\/p>\n<p>Applications that create or modify database objects during normal operation may also require membership in the <em>db_ddladmin<\/em> role. However, this role includes powerful permissions that can be abused for elevation-attacks. Therefore, it should be avoided unless absolutely necessary. It\u2019s still better than requiring <em>db_owner<\/em> though.<\/p>\n<p>* LURP = Login -> User -> Role -> Permission<\/td>\n<\/tr>\n<tr>\n<td width=\"151\"><strong>(O2)<br \/>\nSchema-level permissions<\/strong><\/td>\n<td width=\"409\">If your database supports multiple different processes, each accessing different areas (objects) of the database, you can further lock down permissions by using schema-level permissions, if your database-schema is developed with those processes in mind. Read here for further details:<\/p>\n<p><a href=\"https:\/\/andreas-wolter.com\/en\/schema-design-for-sql-server-recommendations-for-schema-design-with-security-in-mind\/\">Schema-design for SQL Server: recommendations for Schema design with security in mind<\/a><\/td>\n<\/tr>\n<tr>\n<td width=\"151\"><strong>(O3)<br \/>\nEncrypt sensitive data<\/strong><\/td>\n<td width=\"409\">If your application stores sensitive data (PCI, HealthCare, PII), <strong>use data encryption<\/strong> to make sure no unauthorized user can read the data. (Do not confuse with TDE which works at the file-level: <a href=\"https:\/\/andreas-wolter.com\/en\/protecting-database-data-at-rest-tde-backupencryption-alwaysencrypted\/\">Protecting database data at rest: Transparent Data Encryption, Backup Encryption or Always Encrypted<\/a> ). This can save millions of dollars in a breach!<\/td>\n<\/tr>\n<tr>\n<td width=\"151\"><strong>(O4)<br \/>\nAvoid Triggers<\/strong><\/td>\n<td width=\"409\">Triggers can be abused for elevation-attacks. If the application requires triggers, <strong>sign triggers<\/strong> with a certificate (<a href=\"https:\/\/learn.microsoft.com\/en-us\/sql\/t-sql\/statements\/add-signature-transact-sql?view=sql-server-ver17\" target=\"_blank\" rel=\"noopener\">ADD SIGNATURE (Transact-SQL)<\/a> so you can ensure to detect any tampering.<\/td>\n<\/tr>\n<tr>\n<td width=\"151\"><strong>(O5)<br \/>\nAvoid CLR<\/strong><\/td>\n<td width=\"409\">CLR-code can contain malicious code that is difficult to detect and can be used for elevation-attacks. When using CLR-assemblies, use certificate-signed assemblies. <strong>Do not require the Trustworthy-database property. <\/strong>(also see O7)<\/td>\n<\/tr>\n<tr>\n<td width=\"151\"><strong>(O6)<br \/>\nNever construct dynamic SQL directly from user input and validate parameters<\/strong><\/td>\n<td width=\"409\">To <strong>prevent<\/strong> <strong>SQL Injection<\/strong>, validate string- and binary-parameters. Never construct dynamic SQL directly from user input.<\/td>\n<\/tr>\n<tr>\n<td width=\"151\"><strong>(O7)<br \/>\nDo not set the Trustworthy-database option to ON<\/strong><\/td>\n<td width=\"409\">Databases with the <em>TRUSTWORTHY<\/em>-property set to ON can be exploited for elevation-of-privilege (EoP) attacks that impact the entire SQL Server instance. Due to this high-risk exposure, customers should not co-host such databases with other databases on the same server.<\/p>\n<p>Most scenarios that the <em>TRUSTWORTHY<\/em>-property is intended to address can be implemented securely using certificate-signed modules, which provide the required permissions without exposing the server to instance-wide privilege escalation.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2>3) High Availability and Business continuity<\/h2>\n<table>\n<tbody>\n<tr>\n<td width=\"189\"><strong>Checklist item<\/strong><\/td>\n<td width=\"409\"><strong>Details<\/strong><\/td>\n<\/tr>\n<tr>\n<td width=\"189\"><strong>(H1)<br \/>\nTest application for common High Availability Technologies<\/strong><\/td>\n<td width=\"409\">Understanding the differences between these technologies and testing your application\u2019s behavior under each scenario helps ensure reliability, failover resilience, and proper connection handling.<\/p>\n<p>\u00b7\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <strong>Failover Clustering<\/strong><\/p>\n<p>\u00b7\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <strong>Availability Groups<\/strong><\/p>\n<p>\u00b7\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <strong>Contained Availability Groups<\/strong><\/td>\n<\/tr>\n<tr>\n<td width=\"189\"><strong>(H2)<br \/>\nAllow using DNS Alias instead of Hostnames or IPs<\/strong><\/td>\n<td width=\"409\">To support Availability Groups, applications must connect via the Availability Group Listener Name, rather than directly to a specific replica. Ideally, use a DNS alias (CNAME), pointing to the Listener.<br \/>\n<em>Sarpedon Quality Lab<\/em> recommends <strong>using DNS aliases for all database connections<\/strong>, to simplify future migrations and environment changes.<\/td>\n<\/tr>\n<tr>\n<td width=\"189\"><strong>(H3)<br \/>\nAlways set \u00a0MultiSubnetFailover=True in Connection String<\/strong><\/td>\n<td width=\"409\">Always include <strong><em>MultiSubnetFailover=True <\/em><\/strong>in your connection strings to give customers using Availability Groups faster failover. This setting ensures <strong>fast reconnection<\/strong> during a failover <u>even within the same subnets<\/u>.<br \/>\nIf no Availability Group is used, this setting has no effect.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>By adopting these standards, you are not just ensuring compliance; you are guaranteeing that your application is secure by design, a critical assurance that builds confidence with every enterprise customer.<\/p>\n<p>We hope that our checklist answers some of the common questions and is useful as a reference by both DBA\u2019s and Application Developers.<\/p>\n<p>Any feedback and input on refining this checklist is welcome!<\/p>\n<p>Happy securing<\/p>\n<p>Andreas<\/p>\n<\/div><\/section>\r\n\r\n<div  class='hr av-baku8u-c77559299fb7cb036a9bcb2d27e7c839 hr-default  avia-builder-el-2  el_after_av_textblock  el_before_av_social_share '><span class='hr-inner '><span class=\"hr-inner-style\"><\/span><\/span><\/div>\r\n\r\n<div  class='av-social-sharing-box av-5n5vpa-78ffdd9d224b4a246af65bdc00dce900 av-social-sharing-box-default  avia-builder-el-3  el_after_av_hr  el_before_av_hr  av-social-sharing-box-fullwidth'><div class=\"av-share-box\"><h5 class='av-share-link-description av-no-toc '>Share article<\/h5><ul class=\"av-share-box-list noLightbox\"><li class='av-share-link av-social-link-facebook' ><a target=\"_blank\" aria-label=\"Share on Facebook\" href=\"https:\/\/www.facebook.com\/sharer.php?u=https:\/\/andreas-wolter.com\/en\/2026_sqlserverdatabaseapplicationsecurityandhighavailabilitychecklist_v2\/&#038;t=The%20SQL%20Server%20Database%20Application%20Security%20%26%20High%20Availability%20Checklist%20by%20Sarpedon%20Quality%20Lab%20%E2%80%93%20Version%202\" aria-hidden=\"false\" data-av_icon=\"\ue8f3\" data-av_iconfont=\"entypo-fontello\" title=\"\" data-avia-related-tooltip=\"Share on Facebook\" rel=\"noopener\"><span class='avia_hidden_link_text'>Share on Facebook<\/span><\/a><\/li><li class='av-share-link av-social-link-twitter' ><a target=\"_blank\" aria-label=\"Share on Twitter\" href=\"https:\/\/twitter.com\/share?text=The%20SQL%20Server%20Database%20Application%20Security%20%26%20High%20Availability%20Checklist%20by%20Sarpedon%20Quality%20Lab%20%E2%80%93%20Version%202&#038;url=https:\/\/andreas-wolter.com\/en\/?p=7126\" aria-hidden=\"false\" data-av_icon=\"\ue8f1\" data-av_iconfont=\"entypo-fontello\" title=\"\" data-avia-related-tooltip=\"Share on Twitter\" rel=\"noopener\"><span class='avia_hidden_link_text'>Share on Twitter<\/span><\/a><\/li><li class='av-share-link av-social-link-linkedin' ><a target=\"_blank\" aria-label=\"Share on LinkedIn\" href=\"https:\/\/linkedin.com\/shareArticle?mini=true&#038;title=The%20SQL%20Server%20Database%20Application%20Security%20%26%20High%20Availability%20Checklist%20by%20Sarpedon%20Quality%20Lab%20%E2%80%93%20Version%202&#038;url=https:\/\/andreas-wolter.com\/en\/2026_sqlserverdatabaseapplicationsecurityandhighavailabilitychecklist_v2\/\" aria-hidden=\"false\" data-av_icon=\"\ue8fc\" data-av_iconfont=\"entypo-fontello\" title=\"\" data-avia-related-tooltip=\"Share on LinkedIn\" rel=\"noopener\"><span class='avia_hidden_link_text'>Share on LinkedIn<\/span><\/a><\/li><\/ul><\/div><\/div>\r\n\r\n\n<style type=\"text\/css\" data-created_by=\"avia_inline_auto\" id=\"style-css-av-4ofg9q-c2108540b480aba02923089240a3a176\">\n#top .hr.hr-invisible.av-4ofg9q-c2108540b480aba02923089240a3a176{\nheight:50px;\n}\n<\/style>\n<div  class='hr av-4ofg9q-c2108540b480aba02923089240a3a176 hr-invisible  avia-builder-el-4  el_after_av_social_share  el_before_av_comments_list '><span class='hr-inner '><span class=\"hr-inner-style\"><\/span><\/span><\/div>\r\n\r\n<div  class='av-buildercomment av-284ftq-f5a1564cd6b8ffad6ce835e2d40de4b7  av-blog-meta-author-disabled av-blog-meta-html-info-disabled'><\/div>","protected":false},"excerpt":{"rendered":"","protected":false},"author":4,"featured_media":7127,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[57],"tags":[206],"class_list":["post-7126","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-security-en","tag-sql-security"],"_links":{"self":[{"href":"https:\/\/andreas-wolter.com\/en\/wp-json\/wp\/v2\/posts\/7126","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/andreas-wolter.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/andreas-wolter.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/andreas-wolter.com\/en\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/andreas-wolter.com\/en\/wp-json\/wp\/v2\/comments?post=7126"}],"version-history":[{"count":3,"href":"https:\/\/andreas-wolter.com\/en\/wp-json\/wp\/v2\/posts\/7126\/revisions"}],"predecessor-version":[{"id":7130,"href":"https:\/\/andreas-wolter.com\/en\/wp-json\/wp\/v2\/posts\/7126\/revisions\/7130"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/andreas-wolter.com\/en\/wp-json\/wp\/v2\/media\/7127"}],"wp:attachment":[{"href":"https:\/\/andreas-wolter.com\/en\/wp-json\/wp\/v2\/media?parent=7126"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/andreas-wolter.com\/en\/wp-json\/wp\/v2\/categories?post=7126"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/andreas-wolter.com\/en\/wp-json\/wp\/v2\/tags?post=7126"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}