

Context: Recent reports indicate a massive data breach in a major religious mobile application, exposing Personally Identifiable Information (PII) of over 700,000 users. This incident highlights the critical necessity for developers to implement robust data masking, encryption, and PII detection pipelines.
In this guide, we will build a PII Detection & Masking Engine. This tool is designed to scan incoming user data (like prayer requests or profile updates) to detect and redact sensitive information (emails, names, phone numbers) before they are stored in potentially vulnerable databases.
Before implementing the security layer, ensure you have the following:
# Create virtual environment
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install Microsoft Presidio (Industry standard for PII)
pip install presidio-analyzer presidio-anonymizer spacy
# Download the language model for NLP
python -m spacy download en_core_web_lg
# Initialize project
npm init -y
# Install dependencies
# Express for the API, Dotenv for config, Axios for calling Python service
npm install express dotenv axios cors
npm install --save-dev typescript @types/node @types/express ts-node
This service uses NLP to identify PII and masks it to prevent data leaks.
import logging
from presidio_analyzer import AnalyzerEngine
from presidio_anonymizer import AnonymizerEngine
from presidio_anonymizer.entities import OperatorConfig
# Configure logging for audit trails
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class PIISecurityEngine:
def __init__(self):
# Initialize the NLP engines
self.analyzer = AnalyzerEngine()
self.anonymizer = AnonymizerEngine()
def redact_sensitive_data(self, text: str) -> dict:
"""
Analyzes text for PII and returns the redacted version.
"""
try:
if not text:
return {"original": "", "redacted": "", "status": "empty"}
# 1. Analyze text for entities (Person, Email, Phone, etc.)
analysis_results = self.analyzer.analyze(
text=text,
language='en',
entities=["PERSON", "EMAIL_ADDRESS", "PHONE_NUMBER", "LOCATION"]
)
# 2. Define how to mask the data (e.g., replace with <EMAIL_ADDRESS>)
operators = {
"PERSON": OperatorConfig("replace", {"new_value": "<USER_NAME>"}, replace_with_mask=True),
"EMAIL_ADDRESS": OperatorConfig("replace", {"new_value": "<REDACTED_EMAIL>"}, replace_with_mask=True),
"PHONE_NUMBER": OperatorConfig("replace", {"new_value": "<REDACTED_PHONE>"}, replace_with_mask=True)
}
# 3. Perform anonymization
anonymized_result = self.anonymizer.anonymize(
text=text,
analyzer_results=analysis_results,
operators=operators
)
return {
"original": text,
"redacted": anonymized_result.text,
"entities_found": len(analysis_results),
"status": "success"
}
except Exception as e:
logger.error(f"PII Processing Error: {str(e)}")
return {"error": "Processing failed", "status": "error"}
# --- TEST SUITE ---
if __name__ == "__main__":
engine = PIISecurityEngine()
sample_input = "Please pray for John Doe, email john.doe@example.com, living in Rome."
result = engine.redact_sensitive_data(sample_input)
print(f"Input: {result['original']}")
print(f"Redacted: {result['redacted']}")
This simulates a production middleware that intercepts user requests to ensure no PII reaches the database.
import express, { Request, Response, NextFunction } from 'express';
import axios from 'axios';
import dotenv from 'dotenv';
dotenv.config();
const app = express();
app.use(express.json());
// Configuration for the Python Security Microservice
const SECURITY_SERVICE_URL = process.env.SECURITY_SERVICE_URL || 'http://localhost:5000/redact';
/**
* Middleware to intercept requests and scrub PII before reaching the business logic
*/
const piiScrubbingMiddleware = async (req: Request, res: Response, next: NextFunction) => {
try {
// We only scrub the 'prayer_request' field in this example
if (req.body.prayer_request) {
console.log('🛡️ Intercepting request for PII scrubbing...');
// Call the Python Security Engine
const response = await axios.post(SECURITY_SERVICE_URL, {
text: req.body.prayer_request
});
// Replace the raw text with the redacted text
req.body.prayer_request = response.data.redacted;
req.body.is_scrubbed = true;
}
next();
} catch (error) {
console.error('❌ PII Scrubbing Failed:', error);
// In production, we fail-closed (block the request) if security check fails
res.status(500).json({ error: 'Security verification failed. Request blocked.' });
}
};
// Mock endpoint representing the "Prayer Request" submission
app.post('/api/v1/submit-prayer', piiScrubbingMiddleware, (req: Request, res: Response) => {
const { prayer_request, is_scrubbed } = req.body;
// In a real scenario, this data would be saved to a DB
console.log('💾 Saving to Database:', prayer_request);
res.status(201).json({
message: 'Prayer request submitted securely',
saved_data: prayer_request,
security_applied: is_scrubbed
});
});
const PORT = 3000;
app.listen(PORT, () => {
console.log(`🚀 API Gateway running on port ${PORT}`);
});
Never hardcode sensitive endpoints or credentials. Use a .env file.
.env
# Node.js Environment
PORT=3000
NODE_ENV=production
SECURITY_SERVICE_URL=http://localhost:5000/redact
# Python/Microservice Environment (if using Cloud DLP)
AWS_ACCESS_KEY_ID=your_key_here
AWS_SECRET_ACCESS_KEY=your_secret_here
GOOGLE_APPLICATION_CREDENTIALS=./path/to/service-account.json
In the TypeScript example above, if the axios call to the security service fails, we return a 500 Error rather than proceeding.
Rule: If you cannot verify that data is safe, do not save it.
john@email.com with <EMAIL>. Good for logs and UI.Deploy the Python Security Engine as a separate container (Docker) next to your main application. This allows you to scale the CPU-intensive NLP tasks independently from your web server.
| Error | Cause | Fix |
|---|---|---|
ModuleNotFoundError: No module named 'pacy' | Python environment mismatch. | Ensure you activated your venv before installing. |
ECONNREFUSED (Node.js) | Python service is not running. | Start the Python Flask/FastAPI server first. |
Low detection accuracy | The NLP model is too small. | Switch from en_core_web_sm to en_core_web_lg in Python. |
Timeout Error | NLP processing is too slow. | Implement a queue (RabbitMQ/Redis) for asynchronous scrubbing. |
Before deploying any PII-handling system, ensure you have checked:
INSERT permissions, and no SELECT permissions on the PII columns?Source: Dark Reading
Follow ICARAX for more AI insights and tutorials.
