endpoint security

Implementing Endpoint DLP Controls

Implements endpoint Data Loss Prevention (DLP) controls to detect and prevent sensitive data exfiltration through email, USB, cloud storage, and printing. Use when deploying DLP agents, creating content inspection policies, or preventing unauthorized data movement from endpoints. Activates for requests involving DLP, data exfiltration prevention, content inspection, or sensitive data protection on endpoints.

content-inspectiondata-loss-preventiondata-protectiondlpendpoint
Install this skill
npx skills add mukul975/Anthropic-Cybersecurity-Skills
Framework mappings

When to Use

Use this skill when:

  • Deploying endpoint DLP to prevent sensitive data (PII, PHI, PCI) from leaving the organization
  • Configuring content inspection rules for email attachments, USB transfers, and cloud uploads
  • Implementing Microsoft Purview DLP or Symantec DLP endpoint policies
  • Meeting compliance requirements for data protection (GDPR, HIPAA, PCI DSS)

Do not use for network DLP (inline proxy-based) or cloud-only DLP (CASB).

Prerequisites

  • Microsoft 365 E5 or standalone Microsoft Purview DLP license
  • Microsoft Purview compliance portal access (compliance.microsoft.com)
  • Sensitive Information Types (SITs) defined for organization data
  • Endpoint onboarded to Microsoft Purview (via Intune or SCCM)

Workflow

Step 1: Define Sensitive Information Types

Microsoft Purview → Data Classification → Sensitive info types
 
Built-in SITs for common data:
- Credit card number (PCI)
- Social Security Number (PII)
- Health records (HIPAA)
- Passport number
- Bank account number
 
Custom SIT example (Employee ID):
  Pattern: EMP-[0-9]{6}
  Confidence: High
  Keywords: "employee id", "emp id", "staff number"

Step 2: Create DLP Policy

Microsoft Purview → Data loss prevention → Policies → Create policy
 
Policy Configuration:
1. Template: Financial / Medical / PII (or custom)
2. Locations: Devices (endpoint DLP)
3. Conditions:
   - Content contains: Credit card numbers (min 5 instances)
   - OR Content contains: SSN (min 1 instance)
4. Actions:
   - Block: Prevent copy to USB, cloud, email
   - Audit: Log but allow (for initial deployment)
   - Notify: Show user notification with policy tip
5. User notifications:
   - "This file contains sensitive data and cannot be copied to this location"
   - Allow override with business justification (optional)

Step 3: Configure Endpoint DLP Activities

Monitored endpoint activities:
- Upload to cloud service (OneDrive, Dropbox, Google Drive)
- Copy to removable media (USB drives)
- Copy to network share
- Print document
- Copy to clipboard
- Access by unallowed browser (non-managed browser)
- Access by unallowed app
- Copy to Remote Desktop session
 
For each activity, configure:
- Audit only (log the action)
- Block with override (user can justify and proceed)
- Block (prevent action entirely)

Step 4: Deploy in Audit Mode

Deploy DLP policy in "Test mode with notifications" first:
1. Policy runs in audit mode for 2-4 weeks
2. Review DLP alerts in Activity Explorer
3. Identify false positives
4. Tune SIT patterns and conditions
5. Add exclusions for legitimate workflows
6. Switch to "Turn on the policy" (enforcement)

Step 5: Monitor and Respond

Purview → Data loss prevention → Activity explorer
 
Key metrics:
- DLP policy matches per day/week
- Top matched sensitive info types
- Top users triggering DLP
- Top activities blocked (USB, cloud, email)
- Override rate (percentage of blocks overridden)
 
DLP incident response:
1. Review DLP alert with matched content
2. Verify sensitivity of detected data
3. Assess intent (accidental vs. intentional)
4. If intentional exfiltration → escalate to security incident
5. If accidental → educate user, refine policy

Key Concepts

Term Definition
DLP Data Loss Prevention; technology that detects and prevents unauthorized transmission of sensitive data
SIT Sensitive Information Type; pattern matching rules for identifying sensitive data (regex, keywords, ML classifiers)
Policy Tip User-facing notification explaining why an action was blocked and how to request an override
Content Inspection Deep inspection of file contents to identify sensitive data patterns
Exact Data Match (EDM) DLP matching against a specific database of known sensitive values (exact SSNs, employee records)

Tools & Systems

  • Microsoft Purview DLP: Cloud-managed endpoint DLP included in M365 E5
  • Symantec DLP (Broadcom): Enterprise DLP with endpoint, network, and cloud modules
  • Digital Guardian: Endpoint DLP with data classification and protection
  • Forcepoint DLP: Unified DLP platform with endpoint agent
  • Code42 Incydr: Insider risk detection with file exfiltration monitoring

Common Pitfalls

  • Over-blocking in enforcement mode: Deploy DLP in audit mode first. Blocking common workflows without warning causes productivity loss.
  • Too many SIT false positives: Phone numbers, dates, and random number sequences can match PCI/SSN patterns. Tune confidence levels and require corroborating keywords.
  • Ignoring user education: DLP is most effective when users understand why data is protected. Policy tips should explain the restriction and provide approved alternatives.
  • Not monitoring overrides: If users frequently override DLP blocks, the policy is either too restrictive or users are ignoring data protection requirements. Review override reasons.
Source materials

References and resources

Everything below is rendered for inspection. Script files are read-only and never run.

References 3

api-reference.md1.5 KB

API Reference: Implementing Endpoint DLP Controls

Sensitive Data Patterns

Pattern Regex Severity
SSN \d{3}-\d{2}-\d{4} HIGH
Credit Card 4[0-9]{12}(?:[0-9]{3})? HIGH
AWS Key AKIA[0-9A-Z]{16} CRITICAL
Private Key -----BEGIN.*PRIVATE KEY----- CRITICAL
API Key api[_-]?key\s*[:=]\s*[a-zA-Z0-9]{20,} HIGH

DLP Channels

Channel Monitoring Method
USB/Removable Device event logs
Cloud Storage URL/domain filtering
Email Attachment scanning
Clipboard Process monitoring
Print Print spooler events

Microsoft Purview DLP API

import requests
headers = {"Authorization": "Bearer <token>"}
resp = requests.get(
    "https://graph.microsoft.com/v1.0/security/alerts_v2",
    headers=headers,
    params={"$filter": "category eq 'DataLossPrevention'"})

CrowdStrike Falcon DLP

curl -X GET "https://api.crowdstrike.com/dlp/entities/policies/v1" \
  -H "Authorization: Bearer $TOKEN"

File Scanning

from pathlib import Path
import re
SENSITIVE_EXTS = {".pem", ".key", ".env", ".kdbx", ".pfx"}
for f in Path("/data").rglob("*"):
    if f.suffix in SENSITIVE_EXTS or re.search(r"AKIA", f.read_text()):
        print(f"ALERT: {f}")

References

standards.md0.4 KB

Standards & References

  • NIST SP 800-53 SC-7: Boundary Protection - DLP enforces data boundaries
  • PCI DSS 4.0 Req 3: Protect stored account data
  • GDPR Article 32: Security of processing - preventing unauthorized data transfer
  • HIPAA 164.312(e)(1): Transmission security for ePHI
  • Microsoft Purview DLP: https://learn.microsoft.com/en-us/purview/dlp-learn-about-dlp
workflows.md0.3 KB

Workflows

DLP Deployment

[Identify sensitive data types] → [Create SITs and policies]
  → [Deploy in audit mode] → [Review Activity Explorer for 2-4 weeks]
  → [Tune rules and exclusions] → [Enable enforcement]
  → [Monitor alerts and override rates] → [Quarterly policy review]

Scripts 2

agent.py6.1 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""Agent for implementing and monitoring endpoint DLP controls."""

import json
import argparse
import re
from datetime import datetime
from pathlib import Path


SENSITIVE_PATTERNS = {
    "SSN": r"\b\d{3}-\d{2}-\d{4}\b",
    "Credit Card": r"\b(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|3[47][0-9]{13})\b",
    "Email": r"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b",
    "AWS Key": r"AKIA[0-9A-Z]{16}",
    "Private Key": r"-----BEGIN (RSA |EC )?PRIVATE KEY-----",
    "API Key": r"(?:api[_-]?key|apikey)\s*[:=]\s*['\"]?[a-zA-Z0-9]{20,}",
}

SENSITIVE_EXTENSIONS = [
    ".pem", ".key", ".pfx", ".p12", ".kdbx", ".env",
    ".sql", ".bak", ".dump", ".mdb",
]


def scan_file_for_sensitive_data(file_path):
    """Scan a single file for sensitive data patterns."""
    try:
        with open(file_path, "r", encoding="utf-8", errors="ignore") as f:
            content = f.read(1024 * 1024)
    except (OSError, PermissionError):
        return None
    matches = {}
    for pattern_name, pattern in SENSITIVE_PATTERNS.items():
        found = re.findall(pattern, content)
        if found:
            matches[pattern_name] = len(found)
    ext = Path(file_path).suffix.lower()
    is_sensitive_ext = ext in SENSITIVE_EXTENSIONS
    if not matches and not is_sensitive_ext:
        return None
    return {
        "file": str(file_path),
        "matches": matches,
        "sensitive_extension": is_sensitive_ext,
        "file_size": Path(file_path).stat().st_size,
        "severity": "CRITICAL" if "Private Key" in matches or "AWS Key" in matches
                    else "HIGH" if matches else "MEDIUM",
    }


def scan_directory(dir_path, max_files=10000):
    """Scan a directory for files containing sensitive data."""
    findings = []
    count = 0
    for filepath in Path(dir_path).rglob("*"):
        if filepath.is_file() and count < max_files:
            count += 1
            result = scan_file_for_sensitive_data(filepath)
            if result:
                findings.append(result)
    return sorted(findings, key=lambda x: x["severity"])


def monitor_usb_transfers(event_log_path):
    """Monitor file transfers to USB/removable devices."""
    findings = []
    with open(event_log_path) as f:
        for line in f:
            try:
                entry = json.loads(line)
            except json.JSONDecodeError:
                continue
            dest = entry.get("destination", entry.get("target_path", "")).lower()
            if any(ind in dest for ind in ["removable", "usb", "external"]):
                findings.append({
                    "timestamp": entry.get("timestamp", ""),
                    "user": entry.get("user", ""),
                    "file": entry.get("file_path", entry.get("source", "")),
                    "destination": dest,
                    "size_bytes": entry.get("size", entry.get("bytes", 0)),
                    "severity": "HIGH",
                    "channel": "USB",
                })
    return findings


def monitor_cloud_uploads(event_log_path):
    """Monitor file uploads to cloud storage services."""
    cloud_domains = ["drive.google.com", "dropbox.com", "onedrive.live.com",
                     "box.com", "wetransfer.com", "mega.nz"]
    findings = []
    with open(event_log_path) as f:
        for line in f:
            try:
                entry = json.loads(line)
            except json.JSONDecodeError:
                continue
            url = entry.get("url", entry.get("destination", "")).lower()
            if any(domain in url for domain in cloud_domains):
                findings.append({
                    "timestamp": entry.get("timestamp", ""),
                    "user": entry.get("user", ""),
                    "url": url[:200],
                    "file": entry.get("file_name", entry.get("filename", "")),
                    "severity": "HIGH",
                    "channel": "cloud_upload",
                })
    return findings


def generate_dlp_policy():
    """Generate endpoint DLP policy recommendations."""
    return {
        "data_classification": ["PII", "Financial", "Credentials", "Source Code"],
        "channels_monitored": ["USB", "Cloud Storage", "Email Attachments",
                               "Clipboard", "Print", "Screen Capture"],
        "actions": {
            "PII_to_USB": "block_and_notify",
            "credentials_to_cloud": "block_and_alert_soc",
            "source_code_to_email": "encrypt_and_log",
            "financial_to_print": "log_and_watermark",
        },
    }


def main():
    parser = argparse.ArgumentParser(description="Endpoint DLP Controls Agent")
    parser.add_argument("--scan-dir", help="Directory to scan for sensitive data")
    parser.add_argument("--usb-log", help="USB transfer event log")
    parser.add_argument("--cloud-log", help="Cloud upload event log")
    parser.add_argument("--output", default="endpoint_dlp_report.json")
    parser.add_argument("--action", choices=["scan", "usb", "cloud", "policy", "full"],
                        default="full")
    args = parser.parse_args()

    report = {"generated_at": datetime.utcnow().isoformat(), "findings": {}}

    if args.action in ("scan", "full") and args.scan_dir:
        findings = scan_directory(args.scan_dir)
        report["findings"]["sensitive_data_scan"] = findings
        print(f"[+] Sensitive files found: {len(findings)}")

    if args.action in ("usb", "full") and args.usb_log:
        findings = monitor_usb_transfers(args.usb_log)
        report["findings"]["usb_transfers"] = findings
        print(f"[+] USB transfer events: {len(findings)}")

    if args.action in ("cloud", "full") and args.cloud_log:
        findings = monitor_cloud_uploads(args.cloud_log)
        report["findings"]["cloud_uploads"] = findings
        print(f"[+] Cloud upload events: {len(findings)}")

    if args.action in ("policy", "full"):
        policy = generate_dlp_policy()
        report["findings"]["dlp_policy"] = policy
        print("[+] DLP policy generated")

    with open(args.output, "w") as fout:
        json.dump(report, fout, indent=2, default=str)
    print(f"[+] Report saved to {args.output}")


if __name__ == "__main__":
    main()
process.py1.9 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""DLP Policy Analyzer - Analyzes DLP alert exports for policy tuning."""

import json, csv, sys, os
from collections import Counter
from datetime import datetime


def parse_dlp_alerts(csv_path: str) -> list:
    alerts = []
    with open(csv_path, "r", encoding="utf-8-sig") as f:
        for row in csv.DictReader(f):
            alerts.append({
                "timestamp": row.get("Date", ""),
                "user": row.get("User", ""),
                "activity": row.get("Activity", ""),
                "policy": row.get("Policy", ""),
                "sit": row.get("Sensitive Info Type", ""),
                "action": row.get("Action", ""),
                "location": row.get("Location", ""),
                "overridden": row.get("Override", "").lower() == "true",
            })
    return alerts


def analyze(alerts: list) -> dict:
    return {
        "total": len(alerts),
        "by_policy": dict(Counter(a["policy"] for a in alerts).most_common(20)),
        "by_user": dict(Counter(a["user"] for a in alerts).most_common(20)),
        "by_activity": dict(Counter(a["activity"] for a in alerts).most_common(10)),
        "by_sit": dict(Counter(a["sit"] for a in alerts).most_common(10)),
        "override_rate": round(sum(1 for a in alerts if a["overridden"]) / max(len(alerts), 1) * 100, 2),
        "blocked": sum(1 for a in alerts if "block" in a["action"].lower()),
    }


if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("Usage: python process.py <dlp_alerts.csv>")
        sys.exit(1)
    alerts = parse_dlp_alerts(sys.argv[1])
    result = analyze(alerts)
    out = os.path.join(os.path.dirname(sys.argv[1]) or ".", "dlp_analysis.json")
    with open(out, "w") as f:
        json.dump({"report_generated": datetime.utcnow().isoformat() + "Z", **result}, f, indent=2)
    print(f"Total: {result['total']} | Blocked: {result['blocked']} | Override rate: {result['override_rate']}%")

Assets 1

template.mdtext/markdown · 0.4 KB
Keep exploring