incident response

Performing Insider Threat Investigation

Investigates insider threat incidents involving employees, contractors, or trusted partners who misuse authorized access to steal data, sabotage systems, or violate security policies. Combines digital forensics, user behavior analytics, and HR/legal coordination to build an evidence-based case. Activates for requests involving insider threat investigation, employee data theft, privilege misuse, user behavior anomaly, or internal threat detection.

data-exfiltrationdfirinsider-threatprivilege-misuseuser-behavior-analytics
Install this skill
npx skills add mukul975/Anthropic-Cybersecurity-Skills
Framework mappings

When to Use

  • DLP (Data Loss Prevention) alerts on large data transfers to personal cloud storage or USB devices
  • User behavior analytics (UBA) detects anomalous access patterns for a user account
  • HR reports a departing employee suspected of taking proprietary information
  • A privileged user is observed accessing systems outside their job function
  • Whistleblower or coworker report alleges policy violations or data theft

Do not use for external attacker investigations where compromised credentials are used without insider collusion; use standard incident response procedures instead.

Prerequisites

  • Legal counsel approval before initiating any monitoring or investigation of an employee
  • HR partnership with defined investigation procedures and employee privacy guidelines
  • DLP platform with content inspection and policy enforcement (Symantec DLP, Microsoft Purview, Digital Guardian)
  • User behavior analytics platform (Microsoft Sentinel UEBA, Exabeam, Securonix)
  • Forensic imaging capability for endpoint examination
  • Chain of custody procedures for evidence that may be used in legal proceedings
  • Clear authority and scope documentation approved by legal and HR

Workflow

Step 1: Receive and Validate the Allegation

Document the initial report and validate before proceeding:

  • Record the source of the allegation (DLP alert, UBA detection, HR referral, manager report)
  • Confirm with legal counsel that the investigation is authorized
  • Define the investigation scope: what activity is being investigated, time period, systems involved
  • Establish the investigation team: security, legal, HR (never investigate alone)
  • Create a restricted case file accessible only to the investigation team
Investigation Authorization:
━━━━━━━━━━━━━━━━━━━━━━━━━━━
Case ID:           INV-2025-042
Subject:           [Employee Name] - [Title] - [Department]
Allegation:        Unauthorized transfer of proprietary data to personal cloud storage
Reported By:       DLP system alert + manager concern
Legal Approval:    [Counsel Name] - 2025-11-15
HR Liaison:        [HR Name]
Scope:             File access and transfer activity from 2025-10-01 to present
Systems in Scope:  Workstation, email, cloud storage, VPN, DLP logs

Step 2: Collect Evidence Covertly

Gather evidence without alerting the subject to the investigation:

Log-Based Evidence (non-intrusive):

  • DLP logs: file transfers, policy violations, content matches
  • Cloud access logs: SharePoint, OneDrive, Google Drive activity
  • Email logs: messages to personal accounts, large attachments, forwarding rules
  • VPN and authentication logs: access times, locations, devices
  • Badge access logs: physical access patterns
  • Print logs: large print jobs of sensitive documents
  • USB device connection logs: device type, serial number, connection times

User Activity Monitoring (requires legal approval):

  • Screen capture or session recording (only if legally authorized and documented)
  • Keystroke logging (jurisdiction-dependent, requires explicit legal approval)
  • Network traffic capture for the subject's workstation

Endpoint Forensics (if warranted by evidence):

  • Create forensic image of the subject's workstation
  • Analyze browser history, download history, and installed applications
  • Examine deleted files and Recycle Bin contents
  • Review cloud sync application logs (Dropbox, Google Drive desktop client)

Step 3: Analyze User Behavior Patterns

Build a behavioral profile comparing normal vs. anomalous activity:

Behavioral Analysis:
━━━━━━━━━━━━━━━━━━
Normal Baseline (6-month average):
- Login time: 08:30-09:00 weekdays
- Files accessed: 15-25 per day (marketing department files)
- Email volume: 45 sent, 80 received per day
- Data transferred: 50MB per day average
- USB usage: None
 
Investigation Period (last 30 days):
- Login time: 22:00-02:00 (after hours, multiple occasions)
- Files accessed: 200+ per day (finance, engineering, executive files)
- Email volume: 120 sent per day (30% to personal gmail)
- Data transferred: 2.5GB per day average
- USB usage: 3 unique devices connected (Kingston DataTraveler)
- Print jobs: 847 pages (competitor analysis, customer lists, source code)
 
Anomaly Score: 94/100 (Critical)

Step 4: Reconstruct the Activity Timeline

Build a chronological timeline of the subject's actions:

Timeline of Activity:
2025-10-15  Subject submits resignation (2-week notice)
2025-10-16  First after-hours login at 23:15, accessed engineering Git repository
2025-10-17  USB device (Kingston DT 64GB) first connected at 23:30
2025-10-18  DLP alert: 450 files copied to USB, including CAD drawings
2025-10-19  200+ emails forwarded to personal Gmail account
2025-10-20  Google Drive desktop client installed, syncing corporate SharePoint
2025-10-22  Accessed executive SharePoint site (not normally accessed)
2025-10-25  Second USB device connected, 2.1GB transferred
2025-10-28  Print job: 847 pages including customer contact database

Step 5: Assess Impact and Determine Response

Evaluate the severity and coordinate the response with HR and legal:

Impact Assessment:

  • What data was accessed or exfiltrated (classification level, business impact)
  • Was the data shared externally (competitors, public, personal storage)
  • Regulatory implications (PII, PHI, financial data, export-controlled)
  • Contractual implications (NDA violations, IP assignment agreements)
  • Potential financial damage to the organization

Response Options (determined by legal and HR):

  • Confront the subject with evidence during an interview (HR-led)
  • Terminate employment and revoke all access immediately
  • Pursue civil litigation for breach of NDA or trade secret theft
  • Refer to law enforcement for criminal prosecution (theft of trade secrets, CFAA violation)
  • Negotiate a settlement with return/destruction of data

Step 6: Preserve Evidence for Legal Proceedings

Ensure all evidence meets legal admissibility standards:

  • Maintain strict chain of custody for all physical and digital evidence
  • Document all analysis steps in detail (reproducible by another examiner)
  • Hash all evidence files and maintain an integrity log
  • Store evidence in a secure, access-controlled repository with audit logging
  • Retain evidence per legal hold requirements (do not destroy during active investigation or litigation)

Key Concepts

Term Definition
Insider Threat Risk posed by individuals with authorized access who intentionally or unintentionally cause harm to the organization
User Behavior Analytics (UBA) Technology that analyzes user activity patterns to detect anomalies indicating potential insider threats
Data Loss Prevention (DLP) Technology that monitors, detects, and blocks unauthorized transfer of sensitive data outside the organization
Legal Hold Directive to preserve all relevant evidence and suspend normal document destruction policies during an investigation
Need to Know Information access principle restricting insider threat investigation details to only authorized team members
Exfiltration Vector Method used to move data outside the organization: USB, email, cloud storage, print, screen capture, photography

Tools & Systems

  • Microsoft Purview (formerly Compliance Center): Insider risk management, DLP, eDiscovery, and content search
  • Exabeam / Securonix: User and entity behavior analytics (UEBA) platforms for anomaly detection
  • Digital Guardian: DLP and insider threat detection platform with endpoint agent
  • Magnet AXIOM: Digital forensics platform supporting endpoint, cloud, and mobile evidence analysis
  • Relativity: eDiscovery platform for legal review of collected evidence in insider threat cases

Common Scenarios

Scenario: Departing Engineer Exfiltrating Source Code

Context: A senior software engineer with access to critical repositories submits a two-week resignation notice. The engineering manager reports that the engineer has been working unusual hours and downloading large amounts of code.

Approach:

  1. Obtain legal authorization to investigate before taking any action
  2. Pull Git access logs showing repository clones and downloads for the past 60 days
  3. Review DLP logs for USB device connections and large file transfers
  4. Check email gateway for messages with code attachments sent to personal accounts
  5. Analyze browser history for personal cloud storage uploads
  6. Image the workstation forensically before the employee's last day
  7. Present findings to legal and HR for determination of next steps

Pitfalls:

  • Investigating without legal counsel authorization (may violate employee privacy rights)
  • Alerting the subject to the investigation before evidence is preserved
  • Not preserving the workstation before the employee's departure date
  • Assuming all after-hours access is malicious without comparing to the employee's historical baseline
  • Failing to check personal mobile devices that may have accessed corporate cloud services

Output Format

INSIDER THREAT INVESTIGATION REPORT
=====================================
Case ID:          INV-2025-042
Classification:   CONFIDENTIAL - Need to Know Only
Subject:          [Name Redacted] - Senior Engineer
Investigation Period: 2025-10-01 to 2025-10-28
Investigator:     [Name]
Legal Counsel:    [Name]
HR Liaison:       [Name]
 
ALLEGATION
Unauthorized exfiltration of proprietary source code and customer
data following resignation submission.
 
EVIDENCE SUMMARY
1. Git logs: 47 repositories cloned (vs. baseline of 3)
2. USB transfers: 4.6 GB across 3 unique devices over 12 sessions
3. Email: 200+ emails with attachments forwarded to personal Gmail
4. Cloud: Google Drive sync client installed, syncing corporate files
5. Print: 847 pages including customer contact database
6. Physical access: After-hours badge access on 8 of 12 workdays
 
BEHAVIORAL ANALYSIS
[Baseline vs. anomalous activity comparison]
 
IMPACT ASSESSMENT
Data Classification:  Confidential (source code, customer PII)
Estimated Volume:     7.2 GB exfiltrated
Regulatory Impact:    Potential GDPR notification (customer PII)
Business Impact:      Competitive advantage at risk
 
TIMELINE
[Chronological event listing]
 
RECOMMENDATIONS
1. [Legal/HR decision on employment action]
2. [Evidence preservation actions]
3. [Regulatory notification assessment]
4. [Access control improvements]
Source materials

References and resources

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

References 1

api-reference.md1.9 KB

API Reference: Insider Threat Investigation

Data Sources

Source Log Type Key Fields
DLP System File transfers, USB connections user, action, file_path, bytes, device_id
Email Gateway Sent/received/forwarded emails sender, recipient, subject, attachment_size
VPN / Auth Logs Authentication events user, timestamp, source_ip, result
Cloud Access Broker SaaS application activity user, app, action, data_volume
Badge Access Physical access events user, location, timestamp, direction

Microsoft Graph API (for Microsoft 365 environments)

Endpoint Method Description
/auditLogs/signIns GET User sign-in activity logs
/security/alerts GET Security alerts including DLP
/users/{id}/activities GET User activity feed
/users/{id}/mailFolders/{id}/messages GET Email messages (eDiscovery)

Exabeam UEBA API

Endpoint Description
/api/users/{user}/timeline User activity timeline with risk scores
/api/users/{user}/risk Current risk score and contributing factors

Python Libraries

Library Version Purpose
csv stdlib Parse exported log files
json stdlib Report generation and data exchange
datetime stdlib Timestamp parsing and time-window analysis
requests >=2.28 API access for UEBA and SIEM platforms

References

Scripts 1

agent.py8.7 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""Agent for performing insider threat investigation.

Analyzes user activity logs, detects behavioral anomalies, builds
activity timelines, and generates investigation reports for insider
threat cases.
"""

import json
import sys
import csv
from datetime import datetime
from collections import defaultdict
from pathlib import Path


class InsiderThreatAgent:
    """Analyzes user behavior for insider threat investigation."""

    def __init__(self, case_id, output_dir):
        self.case_id = case_id
        self.output_dir = Path(output_dir)
        self.output_dir.mkdir(parents=True, exist_ok=True)
        self.events = []
        self.baseline = {}

    def load_events_csv(self, csv_path, timestamp_col="timestamp",
                        user_col="user", action_col="action"):
        """Load user activity events from a CSV file."""
        with open(csv_path, "r") as f:
            reader = csv.DictReader(f)
            for row in reader:
                self.events.append({
                    "timestamp": row.get(timestamp_col, ""),
                    "user": row.get(user_col, ""),
                    "action": row.get(action_col, ""),
                    "source": row.get("source", "unknown"),
                    "details": row.get("details", ""),
                    "destination": row.get("destination", ""),
                    "bytes": int(row.get("bytes", 0) or 0),
                })

    def set_baseline(self, avg_files_per_day=20, avg_emails_per_day=50,
                     avg_data_mb_per_day=50, normal_hours=(8, 18),
                     usb_usage=False):
        """Set behavioral baseline for comparison."""
        self.baseline = {
            "avg_files_per_day": avg_files_per_day,
            "avg_emails_per_day": avg_emails_per_day,
            "avg_data_mb_per_day": avg_data_mb_per_day,
            "normal_hours_start": normal_hours[0],
            "normal_hours_end": normal_hours[1],
            "usb_usage": usb_usage,
        }

    def filter_events_by_user(self, username):
        """Filter events for a specific user."""
        return [e for e in self.events if e["user"] == username]

    def detect_after_hours_activity(self, username):
        """Detect activity outside normal business hours."""
        user_events = self.filter_events_by_user(username)
        after_hours = []
        start = self.baseline.get("normal_hours_start", 8)
        end = self.baseline.get("normal_hours_end", 18)

        for event in user_events:
            try:
                ts = datetime.fromisoformat(event["timestamp"].replace("Z", "+00:00"))
                hour = ts.hour
                if hour < start or hour >= end:
                    after_hours.append(event)
            except (ValueError, AttributeError):
                continue
        return {
            "total_events": len(user_events),
            "after_hours_events": len(after_hours),
            "after_hours_pct": round(len(after_hours) / max(len(user_events), 1) * 100, 1),
            "events": after_hours[:50],
        }

    def detect_data_exfiltration_indicators(self, username):
        """Detect potential data exfiltration patterns."""
        user_events = self.filter_events_by_user(username)
        indicators = {
            "usb_connections": [],
            "large_transfers": [],
            "email_forwarding": [],
            "cloud_uploads": [],
            "print_jobs": [],
        }

        exfil_keywords = {
            "usb_connections": ["usb", "removable", "mass_storage"],
            "large_transfers": ["transfer", "copy", "download"],
            "email_forwarding": ["forward", "auto-forward", "gmail", "yahoo", "hotmail"],
            "cloud_uploads": ["dropbox", "gdrive", "onedrive", "mega", "wetransfer"],
            "print_jobs": ["print", "printer"],
        }

        for event in user_events:
            action_lower = event["action"].lower()
            details_lower = event.get("details", "").lower()
            dest_lower = event.get("destination", "").lower()
            combined = f"{action_lower} {details_lower} {dest_lower}"

            for category, keywords in exfil_keywords.items():
                if any(kw in combined for kw in keywords):
                    indicators[category].append(event)

            if event.get("bytes", 0) > 100_000_000:
                indicators["large_transfers"].append(event)

        return indicators

    def build_activity_timeline(self, username):
        """Build a chronological activity timeline for the subject."""
        user_events = self.filter_events_by_user(username)
        sorted_events = sorted(user_events, key=lambda e: e.get("timestamp", ""))

        daily_summary = defaultdict(lambda: {
            "event_count": 0, "total_bytes": 0, "actions": defaultdict(int),
        })

        for event in sorted_events:
            try:
                ts = datetime.fromisoformat(event["timestamp"].replace("Z", "+00:00"))
                day = ts.strftime("%Y-%m-%d")
            except (ValueError, AttributeError):
                day = "unknown"
            daily_summary[day]["event_count"] += 1
            daily_summary[day]["total_bytes"] += event.get("bytes", 0)
            daily_summary[day]["actions"][event["action"]] += 1

        return {
            "user": username,
            "total_events": len(sorted_events),
            "date_range": {
                "start": sorted_events[0]["timestamp"] if sorted_events else None,
                "end": sorted_events[-1]["timestamp"] if sorted_events else None,
            },
            "daily_summary": {
                day: {
                    "event_count": s["event_count"],
                    "total_bytes": s["total_bytes"],
                    "total_mb": round(s["total_bytes"] / 1_048_576, 1),
                    "top_actions": dict(sorted(
                        s["actions"].items(), key=lambda x: x[1], reverse=True
                    )[:5]),
                }
                for day, s in sorted(daily_summary.items())
            },
        }

    def calculate_anomaly_score(self, username):
        """Calculate a composite behavioral anomaly score (0-100)."""
        score = 0
        after_hours = self.detect_after_hours_activity(username)
        exfil = self.detect_data_exfiltration_indicators(username)
        timeline = self.build_activity_timeline(username)

        if after_hours["after_hours_pct"] > 30:
            score += 25
        elif after_hours["after_hours_pct"] > 15:
            score += 10

        if len(exfil["usb_connections"]) > 0:
            score += 20
        if len(exfil["cloud_uploads"]) > 0:
            score += 15
        if len(exfil["email_forwarding"]) > 0:
            score += 15
        if len(exfil["large_transfers"]) > 3:
            score += 15

        daily_data = timeline.get("daily_summary", {})
        for day, summary in daily_data.items():
            if summary["total_mb"] > self.baseline.get("avg_data_mb_per_day", 50) * 5:
                score += 10
                break

        return min(score, 100)

    def generate_investigation_report(self, username):
        """Generate a comprehensive insider threat investigation report."""
        report = {
            "case_id": self.case_id,
            "subject": username,
            "report_date": datetime.utcnow().isoformat(),
            "anomaly_score": self.calculate_anomaly_score(username),
            "after_hours_analysis": self.detect_after_hours_activity(username),
            "exfiltration_indicators": {
                k: len(v) for k, v in
                self.detect_data_exfiltration_indicators(username).items()
            },
            "activity_timeline": self.build_activity_timeline(username),
        }

        score = report["anomaly_score"]
        if score >= 70:
            report["risk_level"] = "CRITICAL"
        elif score >= 40:
            report["risk_level"] = "HIGH"
        elif score >= 20:
            report["risk_level"] = "MEDIUM"
        else:
            report["risk_level"] = "LOW"

        report_path = self.output_dir / f"{self.case_id}_report.json"
        with open(report_path, "w") as f:
            json.dump(report, f, indent=2, default=str)

        print(json.dumps(report, indent=2, default=str))
        return report


def main():
    if len(sys.argv) < 4:
        print("Usage: agent.py <case_id> <events_csv> <username> [output_dir]")
        sys.exit(1)

    case_id = sys.argv[1]
    events_csv = sys.argv[2]
    username = sys.argv[3]
    output_dir = sys.argv[4] if len(sys.argv) > 4 else "./investigation_output"

    agent = InsiderThreatAgent(case_id, output_dir)
    agent.load_events_csv(events_csv)
    agent.set_baseline()
    agent.generate_investigation_report(username)


if __name__ == "__main__":
    main()
Keep exploring