This check flags AWS load balancers whose HTTPS listeners run on a deprecated SSL/TLS security policy that still permits weak protocols like TLS 1.0 and 1.1. Outdated policies expose you to downgrade attacks and compliance failures. Fix it by switching the listener to a modern policy such as ELBSecurityPolicy-TLS13-1-2-2021-06.
An HTTPS listener is only as strong as the security policy backing it. That policy decides which TLS protocol versions and cipher suites your load balancer will negotiate with clients. AWS ships a range of predefined policies, and a fair number of them date back to a time when TLS 1.0 and TLS 1.1 were still considered acceptable. They are not anymore.
The lb_outdated_tls check looks at every HTTPS (and TLS) listener on your Application and Network Load Balancers, reads the attached security policy, and flags any listener still pinned to a deprecated policy.
What this check detects
AWS load balancers reference a named SSL policy on each TLS-terminating listener. The policy name maps to a fixed set of supported protocol versions and ciphers. For example:
- ELBSecurityPolicy-2016-08 — the long-standing default, which still negotiates TLS 1.0 and 1.1.
- ELBSecurityPolicy-TLS-1-0-2015-04 — explicitly allows TLS 1.0.
- ELBSecurityPolicy-TLS-1-1-2017-01 — minimum TLS 1.1.
- ELBSecurityPolicy-FS-2018-06 — forward secrecy ciphers but still permits TLS 1.0.
The check raises a finding when a listener uses any policy that allows TLS versions below 1.2, or that includes ciphers AWS and the wider industry now flag as weak. The goal is simple: every HTTPS listener should negotiate TLS 1.2 at minimum, ideally with TLS 1.3 available.
Note: The SSL policy controls the connection between the client and the load balancer only. Traffic from the load balancer to your backend targets is governed separately, so terminating TLS at the LB does not automatically secure the second hop.
Why it matters
TLS 1.0 and 1.1 were deprecated by the IETF in RFC 8996 in 2021. They carry known weaknesses that modern TLS versions fix outright.
Real-world risk
- Downgrade attacks. If a listener still offers TLS 1.0, an attacker positioned on the network can attempt to force a client and server to negotiate the weaker protocol, then exploit flaws like BEAST or POODLE against it.
- Weak cipher suites. Older policies include ciphers using RC4, 3DES, or CBC mode constructions that are vulnerable to padding oracle and birthday-bound attacks (Sweet32).
- No forward secrecy. Some legacy policies allow static RSA key exchange. If the server's private key is ever compromised, an attacker who captured past traffic can decrypt it retroactively.
Business and compliance impact
This is not just a theoretical concern. The PCI DSS standard has required TLS 1.2 or higher since mid-2018. NIST SP 800-52 Rev. 2 mandates TLS 1.2 as a minimum for federal systems. Auditors for SOC 2, HIPAA, and FedRAMP routinely scan public endpoints with tools like SSL Labs, and a deprecated policy will drop your grade and surface as a finding. A single overlooked listener can stall an audit.
Warning: Before tightening a policy, check who actually connects to the listener. Very old clients, embedded devices, legacy Java 7 applications, or some IoT firmware may only support TLS 1.0/1.1. Forcing TLS 1.2 will break those connections. Confirm your client base with access logs first.
How to fix it
The fix is to point the listener at a modern security policy. No certificate changes are required, and the update applies near-instantly with no load balancer recreation.
Step 1: Find the offending listener
List your load balancers and inspect their listeners:
# List all load balancers and their ARNs
aws elbv2 describe-load-balancers \
--query 'LoadBalancers[].{Name:LoadBalancerName,ARN:LoadBalancerArn}' \
--output table
# Inspect listeners and their SSL policies for a given LB
aws elbv2 describe-listeners \
--load-balancer-arn arn:aws:elasticloadbalancing:us-east-1:111122223333:loadbalancer/app/my-alb/abc123 \
--query 'Listeners[?Protocol==`HTTPS`].{Port:Port,Policy:SslPolicy,ARN:ListenerArn}' \
--output table
Step 2: Pick a modern policy
For most workloads, use one of these:
- ELBSecurityPolicy-TLS13-1-2-2021-06 — supports TLS 1.2 and 1.3. A good general-purpose default.
- ELBSecurityPolicy-TLS13-1-2-Res-2021-06 — TLS 1.2/1.3 with a restricted, forward-secrecy-only cipher set for stricter environments.
- ELBSecurityPolicy-TLS13-1-3-2021-06 — TLS 1.3 only, for when every client supports it.
You can list the full set of available policies and their ciphers:
aws elbv2 describe-ssl-policies \
--query 'SslPolicies[].Name' \
--output table
Step 3: Apply the new policy
Danger: This command modifies a live production listener. The change is immediate. If any active clients only support TLS below 1.2, their connections will start failing the moment it applies. Validate against access logs and run it in a maintenance window for high-traffic endpoints.
aws elbv2 modify-listener \
--listener-arn arn:aws:elasticloadbalancing:us-east-1:111122223333:listener/app/my-alb/abc123/def456 \
--ssl-policy ELBSecurityPolicy-TLS13-1-2-2021-06
Step 4: Verify
Confirm the policy took effect, then test the actual handshake from outside AWS:
# Confirm the policy is set
aws elbv2 describe-listeners \
--listener-arn arn:aws:elasticloadbalancing:us-east-1:111122223333:listener/app/my-alb/abc123/def456 \
--query 'Listeners[0].SslPolicy'
# This should now fail, proving TLS 1.0 is rejected
openssl s_client -connect my-alb-1234.us-east-1.elb.amazonaws.com:443 -tls1
# This should succeed
openssl s_client -connect my-alb-1234.us-east-1.elb.amazonaws.com:443 -tls1_2
Fixing it in Terraform
If your load balancers are managed as code, update the ssl_policy attribute on the listener resource:
resource "aws_lb_listener" "https" {
load_balancer_arn = aws_lb.app.arn
port = 443
protocol = "HTTPS"
ssl_policy = "ELBSecurityPolicy-TLS13-1-2-2021-06"
certificate_arn = aws_acm_certificate.app.arn
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.app.arn
}
}
For CloudFormation:
HttpsListener:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
LoadBalancerArn: !Ref AppLoadBalancer
Port: 443
Protocol: HTTPS
SslPolicy: ELBSecurityPolicy-TLS13-1-2-2021-06
Certificates:
- CertificateArn: !Ref AppCertificate
DefaultActions:
- Type: forward
TargetGroupArn: !Ref AppTargetGroup
Tip: If you manage dozens of listeners, script the audit and fix together. Loop over describe-load-balancers, filter listeners whose SslPolicy is in your deprecated list, and call modify-listener on each. Roll out region by region so a bad assumption about client support does not take down everything at once.
How to prevent it from happening again
Remediating today does not stop the next listener from being created with a stale policy. Bake the requirement into the places where infrastructure gets defined and shipped.
Policy-as-code in CI/CD
Catch deprecated policies before they merge. With Checkov scanning Terraform:
checkov -d ./infra --check CKV_AWS_103
CKV_AWS_103 enforces that load balancer listeners use a TLS 1.2 minimum policy. Wire it into your pull request pipeline so any change touching a listener gets evaluated automatically.
For a custom OPA/Conftest rule that pins an explicit allowlist:
package terraform.lb
deprecated_policies := {
"ELBSecurityPolicy-2016-08",
"ELBSecurityPolicy-TLS-1-0-2015-04",
"ELBSecurityPolicy-TLS-1-1-2017-01",
"ELBSecurityPolicy-FS-2018-06",
}
deny[msg] {
resource := input.resource.aws_lb_listener[name]
resource.protocol == "HTTPS"
deprecated_policies[resource.ssl_policy]
msg := sprintf("Listener '%s' uses deprecated SSL policy '%s'", [name, resource.ssl_policy])
}
Continuous monitoring
Infrastructure drifts. Someone clicks through the console, restores an old snapshot, or copies a template from an internal wiki written in 2017. Keep a recurring scan running so the gap between a regression and its detection stays small. Lensix runs lb_outdated_tls on every account scan, so a newly created listener on a stale policy surfaces in your next report rather than your next audit.
Set an organization default
Publish a single approved policy name in your shared Terraform modules and platform templates, then default every listener to it. When teams consume the module, they inherit the right policy without thinking about it.
Best practices
- Standardize on TLS 1.2 minimum, TLS 1.3 enabled. Use
ELBSecurityPolicy-TLS13-1-2-2021-06as your baseline unless you have a documented reason not to. - Review policies on a schedule. AWS releases new security policies as the threat landscape shifts. What is modern today may be deprecated in three years. Treat the policy name as something to revisit, not set once and forget.
- Secure the second hop too. Terminating TLS at the load balancer is fine, but if backend traffic crosses untrusted boundaries, enable encryption between the LB and targets as well.
- Test before tightening. Pull your access logs, identify the negotiated TLS versions in use, and confirm no real clients depend on the old protocols before you switch.
- Validate externally. After a change, scan the endpoint with SSL Labs or
testssl.shto confirm the handshake behaves the way you expect from a real client's perspective.
Updating a TLS policy is one of the lowest-effort, highest-value security changes available on AWS. It takes one API call, requires no certificate rotation, and closes off a whole class of downgrade and weak-cipher attacks. The hard part is not the fix, it is knowing which listeners need it and making sure new ones never ship broken.

