Skip to content

CWE-201: Insertion of Sensitive Information Into Sent Data - Remediation Guide

In short CWE-201 is sensitive information, such as PII, included in data that code sends to another actor who should not have access to it. Prevent it by omitting sensitive data that is not needed, masking values, and encrypting data during transmission.

CWE-201: Insertion of Sensitive Information Into Sent Data occurs when code transmits data to another actor, but a portion of that data includes sensitive information that should not be accessible to that actor. When the sensitive data consists of Personally Identifiable Information (PII), the risks escalate significantly. This article delves into the specific risks associated with PII exposure through CWE-201 and provides practical remediation techniques to secure PII data in applications developed in Java, JavaScript, and Python.

  • Identity Theft: Exposure of PII such as Social Security numbers, birthdates, or credit card information can lead directly to identity theft.

  • Financial Loss: Compromised bank details or payment card information can result in direct financial theft.

  • Access to Additional Accounts: Leaked information like email addresses and passwords can be used to gain access to other personal and business accounts.

  • Reputation Damage: Incidents of PII exposure can harm the reputation of the involved organization, leading to lost trust and customer churn.

  • Legal and Regulatory Penalties: Non-compliance with data protection regulations such as GDPR, HIPAA, or CCPA can result in hefty fines and legal actions.

  • Operational Disruption: Dealing with the aftermath of a data breach often requires significant resources, diverting focus from normal business operations.

Effective remediation of CWE-201 when PII is involved includes several strategies such as omitting sensitive data where unnecessary, masking data to prevent real values from being exposed, and encrypting data to protect its confidentiality during transmission.

Java
public class UserInfo {
private String name;
private String address; // PII not required in the output
public UserInfo(String name, String address) {
this.name = name;
this.address = address;
}
public String getName() {
return name;
}
// No getAddress method to prevent exposure
}
Javascript
function getUserInfo(user) {
return {
name: user.name
// Omit address even if it's part of the user object
};
}
Python
class UserInfo:
def __init__(self, name, address):
self.name = name
self.address = address # PII not to be exposed
def get_name(self):
return self.name
# No method to get address to prevent exposure
Java
public class User {
public String maskEmail(String email) {
String[] parts = email.split("@");
String maskedLocal = parts[0].replaceAll("(?<=.{2}).", "*");
return maskedLocal + "@" + parts[1];
}
}
Javascript
function maskEmail(email) {
const parts = email.split('@');
const maskedLocal = parts[0].replace(/.(?=..)/g, '*');
return maskedLocal + '@' + parts[1];
}
Python
def mask_email(email):
local, domain = email.split('@')
masked_local = local[:2] + '*' * (len(local) - 2)
return f'{masked_local}@{domain}'
Java
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
public class EncryptionUtil {
// secretKey is supplied by the caller, sourced from your KMS or secret store
public static String encryptData(String data, SecretKey secretKey) throws Exception {
byte[] iv = new byte[12];
new SecureRandom().nextBytes(iv);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey, new GCMParameterSpec(128, iv));
byte[] encrypted = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
byte[] payload = ByteBuffer.allocate(iv.length + encrypted.length).put(iv).put(encrypted).array();
return java.util.Base64.getEncoder().encodeToString(payload);
}
}
Javascript
const crypto = require('crypto');
// key: 32-byte Buffer loaded from your KMS or secret store
function encryptData(data, key) {
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
const encrypted = Buffer.concat([cipher.update(data, 'utf8'), cipher.final()]);
return iv.toString('hex') + ':' + encrypted.toString('hex');
}
Python
from cryptography.fernet import Fernet
# key: Fernet key loaded from your secret store, never generated per call
def encrypt_data(data, key):
cipher = Fernet(key)
encrypted = cipher.encrypt(data.encode())
return encrypted

HoundDog.ai’s Privacy Code Scanner (hounddog scan) reports CWE-201 when unsanitized sensitive data reaches a data sink that sends it to another party. It identifies sensitive data elements in source code and traces them through assignments, transformations, string interpolations, and function calls to the sinks they reach.

  • Sensitive data types. The scanner ships with over 100 data element definitions covering common PII, PHI, CHD, PIFI, and secret data (tags PII, PHI, CHD, PIFI, SECRET); the full list is in the scanner’s data-elements.md. A finding names the data element involved, such as Email or Social Security Number.

  • Sinks. CWE-201 is reported on data sinks for third-party services, including payment processors, AI integrations, and observability SDKs such as Sentry. Each sink is marked safe or risky. Sensitive data reaching a risky sink is flagged unless the data element is on that sink’s allowlist; for example, the Stripe sink allowlists bank account number, card number, and name, because a payments integration needs them, while a Social Security Number sent to Stripe is flagged. Trust modes and allowlists can be adjusted under Scanner Rules. Per-language sink support is listed in the scanner’s data-sinks.md.

  • Languages. Dataflows are reported for Python, JavaScript, TypeScript, Java, C#/.NET, and Go. Other supported languages are scanned for data elements only and produce no dataflows. See Supported Languages.

  • Sanitizers. If the data passes through a recognized sanitizer (masking, hashing, encryption, redaction) before it reaches the sink, the dataflow is treated as safe and is not flagged. Organizations can add their own patterns under Sanitizers.

For example, scanning a Python file that sends a user’s email address to Sentry produces a finding like this (console output, excerpt; the file path is shortened):

sentry_sdk.capture_message(f"Signup for {user.email}")
🟨 LOW: Email sent to Sentry in /path/to/project/app.py:5:5
5 │ sentry_sdk.capture_message(f"Signup for {user.email}")
Associated Compliance Frameworks
────────────────────────────────
CWE: CWE-201
OWASP: A01:2021
Privacy: CCPA, GDPR-A5-32, NIST-800-53

To run a scan, see the quickstart. For how data elements, data sinks, and sanitizers are defined and customized, see the scanner rules reference.

Implementing these remediation strategies will significantly reduce the risk of PII exposure through CWE-201 vulnerabilities. Developers should assess their applications for potential data exposure points and apply the appropriate methods to protect sensitive information.