Install this skill
npx skills add mukul975/Anthropic-Cybersecurity-SkillsFramework mappings
MITRE ATT&CK
NIST CSF 2.0
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 policyKey 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 |
| Attachment scanning | |
| Clipboard | Process monitoring |
| 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
- Microsoft Purview DLP: https://learn.microsoft.com/en-us/purview/dlp-learn-about-dlp
- CrowdStrike Falcon DLP: https://www.crowdstrike.com/platform/data-protection/
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 KBKeep exploring