VA1279, “Force encryption should be enabled for TDS”, means the SQL Server instance does not force TLS on client connections, so any client can connect and exchange data unencrypted. Fix it by binding a trusted certificate that matches the server’s FQDN, setting Force Encryption to Yes in SQL Server Configuration Manager (network.forceencryption 1 on Linux), and restarting the service.
The flag itself is one click. The real work is the certificate behind it and the clients that will start validating that certificate.
What the scanner is actually detecting
This is a configuration check with no CVE attached. Microsoft Defender for Cloud’s SQL vulnerability assessment (Defender for SQL servers on machines) reports it through two related Data Protection rules:
| Rule | Finding title | What it means |
|---|---|---|
| VA1279 (High) | Force encryption should be enabled for TDS (recommendation title “Force encryption should be enabled for TDS for SQL Servers”) | Platform SQL Server 2012+. Checks that the instance’s Force Encryption option is on, so every session is encrypted whether or not the client asked for it. |
| VA1220 (High) | Database communication using TDS should be protected through TLS | Platforms SQL Server 2012+ and SQL Managed Instance. Checks that all connections to the server are encrypted through TLS. |
The two usually fail together: VA1279 looks at the server setting, VA1220 at the connections. Defender’s scan is read-only and runs every 12 hours for SQL servers on machines. If this arrived in a batch of Defender findings, our guide to triaging Defender for Cloud recommendations covers routing and prioritizing them.
Real-world risk
Without Force Encryption, encryption is the client’s choice, and older drivers don’t ask (ODBC Driver 17 and earlier default to Encrypt=no). Those sessions carry queries, parameters and result sets in cleartext. Anyone who can capture traffic on the path, such as a compromised host on the same segment, can read that data, and an attacker in a man-in-the-middle position could alter it.
Two limits keep this honest. SQL Server always encrypts the login packet, so this finding does not mean passwords cross the wire in cleartext. And the attacker needs a position on the network path, so on a well-segmented database network the exposure is lower than “High” suggests. Note too that forcing encryption with SQL Server’s self-generated certificate does not, per Microsoft, protect against server identity spoofing. A CA-issued certificate that clients validate closes that gap.
How to confirm it on the host
From a login with VIEW SERVER STATE (VIEW SERVER PERFORMANCE STATE on SQL Server 2022 and later), read the instance’s network flags:
SELECT registry_key, value_name, value_data
FROM sys.dm_server_registry
WHERE registry_key LIKE N'%SuperSocketNetLib%'
AND value_name IN (N'ForceEncryption', N'ForceStrict', N'Certificate');
ForceEncryption = 0 confirms the finding. An empty Certificate value means none is explicitly configured, so SQL Server uses a qualifying certificate from the machine store or a self-generated one. In PowerShell on the host (MSSQL16.MSSQLSERVER is the SQL Server 2022 default instance; adjust for yours):
Get-ItemProperty 'HKLM:SOFTWAREMicrosoftMicrosoft SQL ServerMSSQL16.MSSQLSERVERMSSQLServerSuperSocketNetLib' |
Select-Object ForceEncryption, Certificate
Next, see who will be affected, grouped by client, driver and encryption state:
SELECT c.client_net_address, s.program_name, s.client_interface_name,
c.net_transport, c.encrypt_option, COUNT(*) AS sessions
FROM sys.dm_exec_connections AS c
JOIN sys.dm_exec_sessions AS s ON s.session_id = c.session_id
GROUP BY c.client_net_address, s.program_name, s.client_interface_name,
c.net_transport, c.encrypt_option
ORDER BY c.encrypt_option, c.client_net_address;
Rows with encrypt_option = FALSE are the clients whose drivers you need to test. On Linux, run sudo cat /var/opt/mssql/mssql.conf; if there is no forceencryption line, the default of 0 applies.
How to fix it
Step 1: get a certificate SQL Server will accept
Force Encryption works without one (SQL Server falls back to a self-generated certificate), but then clients can’t verify the server. Use a certificate from an internal or public CA that meets Microsoft’s requirements:
- Installed in the Local Computer Personal store (Cert:LocalMachineMy), with the current date inside its validity period.
- Enhanced Key Usage includes Server Authentication (1.3.6.1.5.5.7.3.1).
- KeySpec AT_KEYEXCHANGE, which requires a legacy CSP such as Microsoft RSA SChannel Cryptographic Provider. Key Storage Provider certificates (KeySpec 0) are not compatible.
- Subject Alternative Name lists every name clients use: host name, FQDN, aliases, and availability group listener names.
Check before binding. The output should show KeySpec = 1 — AT_KEYEXCHANGE and Server Authentication:
certutil -v -store My "<certificate_thumbprint>"
Step 2: bind the certificate and force encryption (Windows)
- Install the certificate on every node of a failover cluster instance or every replica of an availability group.
- Configuration Manager from SQL Server 2019 or later has built-in certificate management that validates the requirements, including for earlier versions. With older builds, import the certificate using the Certificates MMC snap-in (Computer account), then right-click it, choose All Tasks > Manage Private Keys, and grant Read to the SQL Server service account.
- In SQL Server Configuration Manager, expand SQL Server Network Configuration, right-click Protocols for <instance>, and select Properties.
- On the Certificate tab, select the certificate.
- On the Flags tab, set Force Encryption to Yes and select OK.
- Restart the SQL Server service in a maintenance window, then confirm SQL Server Agent is running again.
On failover cluster instances the Certificate registry value stays Null even with the certificate in the store. Paste the thumbprint, spaces removed, into HKLMSOFTWAREMicrosoftMicrosoft SQL Server<instance>MSSQLServerSuperSocketNetLibCertificate on each node, failing over before restarting the node you changed.
SQL Server 2022 and later: Force Strict Encryption
SQL Server 2022 adds a Force Strict Encryption option on the Flags tab. It moves connections to TDS 8.0, where TLS starts before any TDS traffic, TLS 1.3 becomes possible, and clients cannot skip certificate validation. It goes beyond VA1279 and needs newer drivers (ODBC 18.1.2.1, OLE DB 19.2.0, JDBC 11.2.0 or later). SQL Server Agent, sqlcmd, bcp, linked servers, replication and log shipping only gained TDS 8.0 support in SQL Server 2025, so on 2022 treat strict mode as a separate, tested project.
SQL Server on Linux
Give the mssql account ownership of the certificate and key, then point mssql-conf at them:
sudo chown mssql:mssql /etc/ssl/certs/mssql.pem /etc/ssl/private/mssql.key
sudo chmod 400 /etc/ssl/certs/mssql.pem /etc/ssl/private/mssql.key
sudo systemctl stop mssql-server
sudo /opt/mssql/bin/mssql-conf set network.tlscert /etc/ssl/certs/mssql.pem
sudo /opt/mssql/bin/mssql-conf set network.tlskey /etc/ssl/private/mssql.key
sudo /opt/mssql/bin/mssql-conf set network.forceencryption 1
sudo systemctl restart mssql-server
The folders must be accessible to the mssql user, and the certificate CN should match the server’s FQDN. For SQL Server 2022 and earlier, Microsoft’s example also sets network.tlsprotocols 1.2 if clients support it. On SQL Server 2025, network.forcestrict 1 is the Linux equivalent of Force Strict Encryption. On Ubuntu 20.04 and later, use a SHA-256 or stronger signature; SHA-1 certificates cause connection failures.
How to verify the fix and rescan
- Rerun the sys.dm_server_registry query. ForceEncryption should now be 1.
- Run Microsoft’s verification query. After the restart it should return only TRUE:
SELECT DISTINCT encrypt_option FROM sys.dm_exec_connections WHERE net_transport <> 'Shared memory'; - Prove the server enforces it. With sqlcmd 18 (ODBC), -No requests optional encryption, so TRUE means the server forced it. In this case ODBC Driver 18 also validates the certificate, which tests the name and trust chain too:
sqlcmd -S sql01.corp.example.com -E -No -Q "SELECT encrypt_option FROM sys.dm_exec_connections WHERE session_id = @@SPID;" - Search the current SQL Server error log for “A self-generated certificate was successfully loaded for encryption.” If it appears after you configured a CA certificate, SQL Server did not load yours.
- Rescan. Defender runs every 12 hours; VA1279 and VA1220 should both pass on the next cycle.
What can break and how to roll back
- SQL Server does not start. A configured certificate that meets only some requirements, or a service account without Read on the private key, can stop the service from starting. Remove the certificate from the instance’s configuration (Certificate tab or registry value), fix it, and retry.
- ODBC Driver 18+ clients using Encrypt=no. Once the server forces encryption, these drivers validate the certificate (ODBC Driver 17 and older don’t). They fail if the client doesn’t trust the CA or connects by a name or IP not in the certificate, typically with “The certificate chain was issued by an authority that is not trusted” or “The target principal name is incorrect”. Fix trust or the connection name, or set HostNameInCertificate. TrustServerCertificate=true works but gives up server verification, so treat it as a temporary exception.
- Clients limited to old TLS versions. They fail, often with “An existing connection was forcibly closed by the remote host”.
- Downtime. The change applies only at restart; on clusters and availability groups, go node by node.
Record the Certificate value before you start. To roll back on Windows, set Force Encryption (and Force Strict Encryption, if enabled) back to No on the Flags tab and restart. On Linux:
sudo /opt/mssql/bin/mssql-conf set network.forceencryption 0
sudo systemctl restart mssql-server
Common false positive reasons
- Stale results. The last scan predates the fix. Check the scan time before reopening the ticket.
- The wrong instance. Force Encryption is per instance. On a multi-instance host you may have fixed a different one.
- Scanner can’t read the registry. Defender notes that some VA rules need EXECUTE on xp_instance_regread. The flag lives in the instance’s registry hive, so if VA1279 contradicts Configuration Manager, check that permission for the scanning identity.
- Mirroring endpoints in VA1220. encrypt_option always returns FALSE for HADR mirroring endpoints (availability groups, database mirroring); Microsoft says to check sys.database_mirroring_endpoints instead. Look at net_transport on any other FALSE rows before assuming the fix failed.
The reverse also happens: a check that reads only the configured flag can pass before the restart, while the running service still accepts unencrypted sessions.
FAQ
Does enabling Force Encryption require a restart?
Yes, on Windows and Linux. Plan a maintenance window or roll through cluster nodes.
Can I just use SQL Server’s self-generated certificate?
It encrypts traffic and satisfies VA1279, but it doesn’t prove the server’s identity, and Microsoft advises against relying on self-signed TLS in production. ODBC Driver 18 clients will also reject it unless they set TrustServerCertificate.
What is the difference between Force Encryption and Force Strict Encryption?
Force Encryption requires TLS on TDS 7.x sessions, where the prelogin exchange is still cleartext. Force Strict Encryption (SQL Server 2022 and later) requires TDS 8.0, which wraps the whole session in TLS, supports TLS 1.3 and always validates the certificate. VA1279 checks Force Encryption.
Were passwords sent in cleartext before the fix?
No. SQL Server encrypts the login packet even when encryption isn’t configured. Force Encryption protects everything after login: queries, parameters and results.
Tracking this finding across many hosts
Across a large estate, the hard part is proving that every instance has the flag set, a valid certificate bound and the service restarted. SITEY, a self-hosted vulnerability management platform, imports findings from 16 scanners and merges duplicates within each scanner, not across scanners. Its AI can draft host-specific remediation scripts that run only after human approval through its agents on Windows and Linux endpoints, and it re-tests after the fix to verify closure; per-finding retest is available for Nessus, Acunetix and Burp results.
Sources
- Microsoft Learn: SQL vulnerability assessment rules reference (Defender for Cloud)
- Microsoft Learn: Encrypt connections by importing a certificate
- Microsoft Learn: Certificate requirements for SQL Server
- Microsoft Learn: ODBC DSN and connection string keywords (Encrypt and Force Encryption behavior)
- Microsoft Learn: Encrypt connections to SQL Server on Linux