CWE-319: Cleartext Transmission of Sensitive Information
Overview
Cleartext transmission occurs when sensitive information is sent over the network without encryption, so anyone who can intercept the traffic can read it. Passwords, session tokens, personal information such as SSNs and health records, API keys, and payment data are typical examples, sent over HTTP instead of HTTPS or over some other unencrypted channel.
Attackers intercept cleartext data through network sniffing on public WiFi, man-in-the-middle attacks, compromised network infrastructure, or ISP-level interception.
Relationship to Other CWEs
Report a finding here rather than against its parent CWE-311 (Missing Encryption of Sensitive Data) whenever the exposure is data crossing a network. CWE-311 is the right level only when the missing protection is not specific to a channel, and MITRE marks it Discouraged for exactly that reason.
The pages around it differ by where the unprotected data sits and by what is actually missing:
- CWE-319 (this page) - sensitive data travels over a network channel with no encryption protecting it, so anyone on the path can read it
- CWE-312 (Cleartext Storage of Sensitive Information) - the sibling under CWE-311 covering data at rest rather than in transit. One value often earns both findings, and the fixes are unrelated: TLS does nothing for the copy sitting in the database, the log file, or the backup
- CWE-614 (Sensitive Cookie in HTTPS Session Without 'Secure' Attribute) - MITRE's child for the case where the transport is already HTTPS but a cookie set without
Secureis still sent on any plain HTTP request the browser makes. The fix is a cookie attribute, not a transport change - CWE-295 (Improper Certificate Validation) - the traffic is encrypted, but to whoever answered the connection. MITRE records no formal relationship between the two and they are easy to confuse. What separates them is which control is missing: closing a CWE-319 finding takes an encrypted channel and a client that checks who is on the other end of it, because a client that skips validation hands the plaintext to anyone in the path. A CWE-295 finding is about that check alone, and changing the scheme does nothing for it
MITRE gives CWE-319 two further children with no page here: CWE-1428 (Reliance on HTTP instead of HTTPS), which a scanner may report in place of this entry for a plain http:// endpoint and which the guidance below treats identically; and CWE-5 (J2EE Misconfiguration: Data Transmission Without Encryption), the same defect expressed as a missing transport-guarantee constraint in a J2EE deployment descriptor.
OWASP Classification
A04:2025 - Cryptographic Failures
Risk
High: Anything the channel carries is readable by anyone who can see the traffic:
- Credential theft: Usernames and passwords captured by network sniffers
- Session hijacking: Session cookies stolen and reused for account takeover
- Privacy violations: Personal information exposed to unauthorized parties
- Identity theft: SSN, passport numbers, health records intercepted
- Financial fraud: Credit card numbers and banking credentials compromised
- Compliance exposure: PCI DSS forbids transmitting cardholder data over open networks in cleartext outright. HIPAA treats encryption in transit as addressable and GDPR Article 32 is risk-based, so there the exposure is failing a control your own risk assessment called for
- Business data leakage: Proprietary information and trade secrets exposed
- API compromise: Authentication tokens for third-party services stolen
Public WiFi networks make these attacks trivial - tools like Wireshark can capture cleartext traffic in seconds.
Remediation Steps
Core Principle: Never transmit sensitive data over cleartext channels; require TLS and secure transport.
Locate the cleartext transmission
- Start from the file, line number, and code pattern the finding names
- Identify what sensitive information travels in cleartext: passwords, session tokens, PII, API keys, credit cards
- Identify the channel: HTTP instead of HTTPS, ws:// instead of wss://, FTP instead of SFTP, or a plaintext database connection
- Work out who can intercept the traffic: public WiFi, a compromised network, the ISP
Use TLS/HTTPS for all communications (Primary Defense)
- Use HTTPS for the entire site: Not only the login page
- Use TLS 1.2 or higher: Prefer TLS 1.3; disable TLS 1.0, TLS 1.1, SSL 2.0 and SSL 3.0. RFC 8996 deprecates TLS 1.0 and 1.1 outright
- Obtain valid certificates: Use publicly trusted CAs for public services and properly distributed internal CAs for private services; avoid unverifiable self-signed leaf certificates
- Turn on both halves of certificate validation in the client: Chain validation and hostname verification are separate settings, and a client that checks the chain but skips the name authenticates nobody - the attacker needs one valid certificate for a domain they own, which is free. Moving a URL from
http://tohttps://while either check is off leaves the data readable to anyone in the path, so it does not close the finding. See CWE-295 - Configure strong cipher suites: Prefer ECDHE key exchange with AEAD ciphers (AES-GCM, ChaCha20-Poly1305); disable RC4, 3DES, DES, export and anonymous suites. Take the list from a generator that tracks current guidance rather than maintaining one by hand
- Redirect all HTTP to HTTPS: Use a 301 permanent redirect, but treat it as damage limitation rather than the fix. The plaintext request has already gone out by the time the redirect arrives, carrying any cookie that lacks the
Secureflag, and a non-browser client that POSTs tohttp://has sent the whole body before it sees the 301. HSTS below is what stops the next request - Avoid mixed content: HTTP resources loaded into an HTTPS page
Enable HTTP Strict Transport Security (HSTS) and secure cookies
- Configure HSTS header:
Strict-Transport-Security: max-age=31536000; includeSubDomainsafter confirming all subdomains support HTTPS; addpreloadonly when you are ready to meet preload-list requirements - Benefits of HSTS: Reduces SSL stripping risk and blocks accidental HTTP requests after the browser has learned the policy; preload can protect first visits for listed domains
- Limits of HSTS: It is a browser mechanism. API clients, mobile SDKs and service-to-service callers generally ignore the header;
curldoes honour it, but only when handed a cache file with--hsts, which nothing does by default. For all of those the scheme has to be fixed in code or configuration rather than left to the header - Secure cookie transmission: Set
Set-Cookie: sessionid=...; Secure; HttpOnly; SameSite=LaxorSameSite=Strictwhere the application flow supports it. Secure restricts cookie transmission to HTTPS, HttpOnly limits JavaScript access, and SameSite reduces cross-site request risk. Every session and authentication cookie must carry the Secure flag
Encrypt database and backend connections
- Use TLS for database connections: PostgreSQL
sslmode=verify-fullwhere possible, MySQLrequire_secure_transport=ONon the server with--ssl-mode=VERIFY_IDENTITYon the client, MongoDBtls=true. The weaker modes are the two-part control again: PostgreSQLrequireguarantees encryption and nothing else,verify-cachecks the chain but not the host name, and onlyverify-fulldoes both - the same split as MySQL'sREQUIRED,VERIFY_CAandVERIFY_IDENTITY. Underrequire, libpq does quietly behave asverify-cawhen a root certificate file happens to be installed, a backwards-compatibility quirk its own documentation discourages relying on - Secure internal APIs: Use HTTPS for service-to-service communication and mutual TLS (mTLS) for authentication
- Check where TLS terminates: A load balancer, ingress or CDN that terminates TLS protects only the segment in front of it. The leg from there to the application is a separate decision, and leaving it plaintext because it is "internal" is the usual way this finding gets closed without being fixed
- Encrypt message queues: RabbitMQ SSL, Kafka SSL/TLS, Redis TLS
- Secure file transfers: Use SFTP, SCP, or HTTPS instead of FTP; for email, require TLS for controlled channels and consider MTA-STS or DANE where applicable instead of relying only on opportunistic STARTTLS
Monitor and audit cleartext transmission
- Search the code for 'http://', 'ws://' and plaintext connection strings
- Monitor certificate expiration and renewal
- Log TLS handshake failures and version or cipher downgrades. Do not expect these, or anything else in your own logs, to reveal SSL stripping: the proxy strips the victim's leg to plaintext and then speaks ordinary HTTPS to your server on their behalf, so the requests reach you over TLS looking entirely normal. Port 80 traffic is no signal either - it is the same population of people who typed
http://, present whether or not anyone is being attacked. With no reliable server-side indicator, HSTS and the preload list above are the control for it - Use network monitoring tools such as Wireshark or tcpdump to detect cleartext traffic
- Scan web applications for mixed content warnings
Test the TLS/HTTPS implementation
- Verify every HTTP request redirects to HTTPS, with curl and a browser
- Check that the HSTS header is present, in browser DevTools or a security headers scanner
- Verify cookies carry the Secure flag by inspecting Set-Cookie headers
- Test the TLS configuration with SSL Labs (https://www.ssllabs.com/ssltest/)
- Confirm with a network sniffer such as Wireshark that no sensitive data leaves in cleartext
- Confirm the server itself refuses TLS 1.0 and 1.1. Plain
openssl s_client -tls1_1is not that test: OpenSSL 3.x rejects the version locally withno protocols availableand never sends a ClientHello, so it reports failure whatever the server allows - and a tester who does not know that records a pass they never ran. Adding-cipher 'DEFAULT@SECLEVEL=0'drops the security level far enough for the handshake to be attempted: a server that still allows TLS 1.1 completes the handshake and negotiates a real cipher, while one that refuses returnsalert number 70withCipher is (NONE). Read the cipher and the alert, not theProtocol :line in the session summary -s_clientprintsProtocol : TLSv1.1on the refused connection as well, because it reports what was attempted rather than what was agreed. A scanner built for the job - SSL Labs above,testssl.sh, ornmap --script ssl-enum-ciphers- covers the whole version and cipher matrix in one run instead of one probe at a time - Where the finding was an outbound client, point it at a host whose certificate is issued for a different name (
wrong.host.badssl.comis the usual target) and confirm the connection fails, then point it back at the real endpoint and confirm it still succeeds. The second assertion is the one that separates working validation from a client that now refuses everything - Re-scan with the security scanner to confirm the finding is resolved