/

Custom Action

Action Type: Custom

Execute custom logic when a threat is detected. Full control over response behavior.

Available for: All platforms (Desktop, Mobile, Web)


How It Works

The Custom action executes your async delegate when a threat is detected.

Behavior:

  • Executes your custom async function
  • Complete control over response logic
  • Can combine multiple actions (log + close, notify + block, etc.)
  • Can make external API calls
  • Can implement complex workflows

When to Use

Recommended for:

  • Enterprise Integrations - SIEM, SOC, ticketing systems
  • Multi-step Workflows - Notify → Confirm → Block → Log
  • Notification Systems - Email, Slack, SMS, PagerDuty
  • Complex Business Logic - Approval workflows, escalation
  • Data Erasure - Secure deletion before shutdown
  • Graceful Shutdown - Save state before terminating
  • User Interaction - Alerts, confirmation dialogs

Configuration Methods

Method 1: Register and Use in Code

C#
await Payload.ConfigureAsync(config =>
{
    // 1. Register the custom action
    config.RegisterCustomAction("my-action", async (threat) =>
    {
        // Your custom logic here
        await MySecurityHandler.ProcessAsync(threat);
    });

    // 2. Assign to protection
    config.AddProtection(ProtectionModuleType.DebuggerDetection, "my-action");
});

Method 2: Register in Code, Use in JSON

Register your custom actions at application startup:

C#
// Program.cs or Startup
public static async Task Main(string[] args)
{
    await Payload.ConfigureAsync(config =>
    {
        // Register custom actions
        config.RegisterCustomAction("notify-security-team", async (threat) =>
        {
            await emailService.SendAsync("security@company.com",
                $"Threat: {threat.Description}");
            Environment.Exit(-1);
        });

        config.RegisterCustomAction("slack-alert", async (threat) =>
        {
            await slackClient.PostAsync("#security",
                $"🚨 {threat.ModuleType}: {threat.Description}");
            Environment.Exit(-1);
        });

        config.RegisterCustomAction("siem-integration", async (threat) =>
        {
            await siemClient.LogAsync(threat);
            Environment.Exit(-1);
        });
    });

    // Application continues...
}

Then reference them in your JSON configuration:

JSON
{
  "protections": {
    "DebuggerDetection": {
      "enabled": true,
      "action": "custom",
      "customActionName": "notify-security-team"
    },
    "TamperingDetection": {
      "enabled": true,
      "action": "custom",
      "customActionName": "siem-integration"
    },
    "JailbreakDetection": {
      "enabled": true,
      "action": "custom",
      "customActionName": "slack-alert"
    }
  }
}

Method 3: Hybrid Approach

Register some actions in code, configure others in JSON:

C#
// Startup - Register reusable custom actions
await Payload.ConfigureAsync(config =>
{
    config.RegisterCustomAction("email-alert", async (threat) =>
    {
        await EmailService.SendAlertAsync(threat);
    });

    config.RegisterCustomAction("pagerduty-alert", async (threat) =>
    {
        await PagerDutyService.TriggerAsync(threat);
    });
});

// Load JSON configuration
await Payload.LoadConfigurationAsync("monitor-config.json");

monitor-config.json:

JSON
{
  "protections": {
    "DebuggerDetection": {
      "enabled": true,
      "action": "custom",
      "customActionName": "email-alert"
    },
    "MemoryDumpDetection": {
      "enabled": true,
      "action": "custom",
      "customActionName": "pagerduty-alert"
    }
  }
}

Code Examples

Email Notification

C#
config.RegisterCustomAction("email-security-team", async (threat) =>
{
    await emailService.SendAsync(new Email
    {
        To = "security@company.com",
        Subject = $"Security Alert: {threat.ModuleType}",
        Body = $@"
            Threat Detected: {threat.Description}
            Incident ID: {threat.ThreatId}
            Time: {DateTime.UtcNow}

            Metadata:
            {JsonSerializer.Serialize(threat.Metadata, new JsonSerializerOptions { WriteIndented = true })}
        "
    });

    // Then close application
    Environment.Exit(-1);
});

SIEM Integration

C#
config.RegisterCustomAction("siem-integration", async (threat) =>
{
    // Send to Splunk/ELK/QRadar
    await siemClient.SendEventAsync(new SecurityEvent
    {
        Severity = "Critical",
        Type = threat.ModuleType.ToString(),
        Description = threat.Description,
        ThreatId = threat.ThreatId,
        Timestamp = DateTime.UtcNow,
        Metadata = threat.Metadata,
        HostName = Environment.MachineName,
        UserName = Environment.UserName
    });

    // Log locally
    await File.AppendAllTextAsync("logs/security.log",
        $"[{DateTime.UtcNow}] {threat.ModuleType}: {threat.Description}\n"
    );

    // Terminate
    Environment.Exit(-1);
});

Slack Notification

C#
config.RegisterCustomAction("slack-alert", async (threat) =>
{
    var slackMessage = new
    {
        channel = "#security-alerts",
        username = "ByteHide Monitor",
        icon_emoji = ":shield:",
        attachments = new[]
        {
            new
            {
                color = "danger",
                title = $"Security Threat: {threat.ModuleType}",
                text = threat.Description,
                fields = new[]
                {
                    new { title = "Incident ID", value = threat.ThreatId, @short = true },
                    new { title = "Timestamp", value = DateTime.UtcNow.ToString(), @short = true },
                    new { title = "Machine", value = Environment.MachineName, @short = true },
                    new { title = "User", value = Environment.UserName, @short = true }
                }
            }
        }
    };

    await httpClient.PostAsJsonAsync(slackWebhookUrl, slackMessage);

    Environment.Exit(-1);
});

Mobile Alert Dialog

C#
config.RegisterCustomAction("mobile-alert", async (threat) =>
{
    // Show alert to user
    await Application.Current.MainPage.DisplayAlert(
        "Security Warning",
        $"Threat detected: {threat.Description}\n\nThe application will now close.",
        "OK"
    );

    // Wait for user acknowledgment
    await Task.Delay(3000);

    // Terminate
    Environment.Exit(-1);
});

Conditional Response

C#
config.RegisterCustomAction("conditional-response", async (threat) =>
{
    // Different actions based on threat type
    switch (threat.ModuleType)
    {
        case ProtectionModuleType.DebuggerDetection:
            // Critical: Close immediately
            Environment.Exit(-1);
            break;

        case ProtectionModuleType.VirtualMachineDetection:
            // Medium: Just log
            await Logger.LogWarningAsync($"VM detected: {threat.Description}");
            break;

        case ProtectionModuleType.ClockTampering:
            // Low: Show warning but continue
            await ShowWarningAsync("System time appears incorrect");
            break;
    }
});

Grace Period Implementation

C#
config.RegisterCustomAction("grace-period", async (threat) =>
{
    var gracePeriodKey = $"grace_{threat.ModuleType}";
    var lastDetection = await SecureStorage.GetAsync(gracePeriodKey);

    if (DateTime.TryParse(lastDetection, out var lastTime))
    {
        var daysSince = (DateTime.UtcNow - lastTime).TotalDays;

        if (daysSince < 7)
        {
            var daysRemaining = 7 - (int)daysSince;
            await ShowWarningAsync(
                "Security Warning",
                $"Please address this security issue within {daysRemaining} days."
            );
            return; // Don't close yet
        }
    }

    // Grace period expired or first detection
    await SecureStorage.SetAsync(gracePeriodKey, DateTime.UtcNow.ToString());

    await ShowMessageAsync(
        "Security Violation",
        "The grace period has expired. The application will now close."
    );

    Environment.Exit(-1);
});

User Confirmation

C#
config.RegisterCustomAction("confirm-close", async (threat) =>
{
    var result = await Application.Current.MainPage.DisplayAlert(
        "Security Threat Detected",
        $"{threat.Description}\n\nClose the application?",
        "Yes, Close",
        "No, Continue"
    );

    if (result)
    {
        await Logger.LogAsync($"User confirmed close for {threat.ModuleType}");
        Environment.Exit(-1);
    }
    else
    {
        await Logger.LogAsync($"User chose to continue despite {threat.ModuleType}");
    }
});

Enterprise Workflow

C#
config.RegisterCustomAction("enterprise-workflow", async (threat) =>
{
    // 1. Log to database
    await dbContext.SecurityIncidents.AddAsync(new SecurityIncident
    {
        ThreatId = threat.ThreatId,
        Type = threat.ModuleType.ToString(),
        Description = threat.Description,
        Metadata = JsonSerializer.Serialize(threat.Metadata),
        DetectedAt = DateTime.UtcNow,
        MachineName = Environment.MachineName,
        UserName = Environment.UserName
    });
    await dbContext.SaveChangesAsync();

    // 2. Create ticket in ServiceNow
    var ticket = await serviceNowClient.CreateIncidentAsync(new
    {
        short_description = $"Security Threat: {threat.ModuleType}",
        description = threat.Description,
        severity = "1 - Critical",
        assignment_group = "security-operations"
    });

    // 3. Send to PagerDuty
    await pagerDutyClient.TriggerIncidentAsync(new
    {
        routing_key = pagerDutyKey,
        event_action = "trigger",
        payload = new
        {
            summary = $"Security Threat: {threat.ModuleType}",
            severity = "critical",
            source = Environment.MachineName,
            custom_details = threat.Metadata
        }
    });

    // 4. Notify Slack
    await slackClient.PostMessageAsync("#security",
        $"🚨 Security incident {ticket.Number} created: {threat.Description}"
    );

    // 5. Log to SIEM
    await siemLogger.LogCriticalAsync(threat);

    // 6. Terminate application
    Environment.Exit(-1);
});

ASP.NET Core Web Example

C#
builder.Services.AddByteHideMonitor(options =>
{
    options.OnThreatDetected = async (httpContext, threat) =>
    {
        // Log attack details
        var attackInfo = new
        {
            ThreatType = threat.ModuleType.ToString(),
            Description = threat.Description,
            IpAddress = httpContext.Connection.RemoteIpAddress?.ToString(),
            UserAgent = httpContext.Request.Headers["User-Agent"].ToString(),
            Path = httpContext.Request.Path,
            Method = httpContext.Request.Method,
            Timestamp = DateTime.UtcNow
        };

        await attackLogger.LogAsync(attackInfo);

        // Send to security team
        await emailService.SendAsync(
            "security@company.com",
            "Web Attack Blocked",
            JsonSerializer.Serialize(attackInfo, new JsonSerializerOptions { WriteIndented = true })
        );

        // Return custom 403 response
        httpContext.Response.StatusCode = 403;
        httpContext.Response.Headers["X-Incident-Id"] = threat.ThreatId;

        await httpContext.Response.WriteAsJsonAsync(new
        {
            error = "Security violation detected",
            incidentId = threat.ThreatId,
            support = "security@company.com"
        });
    };
});

Threat Object Properties

C#
config.RegisterCustomAction("inspect-threat", async (threat) =>
{
    // Available properties:
    var threatId = threat.ThreatId;              // "DBG-2025-12-28-1234"
    var moduleType = threat.ModuleType;          // ProtectionModuleType.DebuggerDetection
    var description = threat.Description;        // "Debugger detected"
    var confidence = threat.Confidence;          // 0.95
    var detectedAt = threat.DetectedAt;          // DateTime.UtcNow
    var metadata = threat.Metadata;              // Dictionary<string, object>

    // Metadata examples:
    var debuggerName = threat.Metadata["debuggerName"];  // "Visual Studio"
    var processId = threat.Metadata["processId"];        // 12345
});

Best Practices

1. Always Handle Exceptions

C#
config.RegisterCustomAction("safe-handler", async (threat) =>
{
    try
    {
        await externalService.NotifyAsync(threat);
    }
    catch (Exception ex)
    {
        // Log error but still take security action
        await Logger.LogErrorAsync(ex);
    }
    finally
    {
        // Always close on critical threats
        Environment.Exit(-1);
    }
});

2. Set Timeouts for External Calls

C#
config.RegisterCustomAction("timeout-handler", async (threat) =>
{
    using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));

    try
    {
        await emailService.SendAsync(threat, cts.Token);
    }
    catch (OperationCanceledException)
    {
        // Timeout - close anyway
        await Logger.LogAsync("Email notification timed out");
    }

    Environment.Exit(-1);
});

3. Don't Block on UI Thread

C#
// Mobile applications
config.RegisterCustomAction("ui-safe", async (threat) =>
{
    await Device.InvokeOnMainThreadAsync(async () =>
    {
        await DisplayAlert("Security Alert", threat.Description, "OK");
    });
});

Enterprise Startup Configuration

Register multiple custom actions at startup for use across JSON configurations:

C#
public class Program
{
    public static async Task Main(string[] args)
    {
        // Register all custom actions at startup
        await ConfigureMonitorActionsAsync();

        var builder = WebApplication.CreateBuilder(args);
        // ... rest of app configuration
    }

    private static async Task ConfigureMonitorActionsAsync()
    {
        await Payload.ConfigureAsync(config =>
        {
            // Email notification action
            config.RegisterCustomAction("email-security", async (threat) =>
            {
                await EmailService.SendAsync(new
                {
                    To = "security@company.com",
                    Subject = $"Security Alert: {threat.ModuleType}",
                    Body = threat.Description,
                    Metadata = threat.Metadata
                });
                Environment.Exit(-1);
            });

            // Slack notification action
            config.RegisterCustomAction("slack-security", async (threat) =>
            {
                await SlackService.PostAsync("#security-alerts", new
                {
                    text = $"🚨 *{threat.ModuleType}*: {threat.Description}",
                    incident_id = threat.ThreatId
                });
                Environment.Exit(-1);
            });

            // PagerDuty critical alert
            config.RegisterCustomAction("pagerduty-critical", async (threat) =>
            {
                await PagerDutyService.TriggerIncidentAsync(new
                {
                    severity = "critical",
                    summary = $"Security: {threat.ModuleType}",
                    details = threat.Metadata
                });
                Environment.Exit(-1);
            });

            // SIEM logging action
            config.RegisterCustomAction("siem-log", async (threat) =>
            {
                await SiemService.LogSecurityEventAsync(new
                {
                    event_type = "SecurityThreat",
                    threat_type = threat.ModuleType.ToString(),
                    description = threat.Description,
                    metadata = threat.Metadata,
                    timestamp = DateTime.UtcNow
                });
                Environment.Exit(-1);
            });

            // User notification (mobile)
            config.RegisterCustomAction("user-notify", async (threat) =>
            {
                await Application.Current.MainPage.DisplayAlert(
                    "Security Warning",
                    threat.Description,
                    "OK"
                );
                await Task.Delay(2000);
                Environment.Exit(-1);
            });

            // Analytics only (no shutdown)
            config.RegisterCustomAction("analytics-track", async (threat) =>
            {
                await AnalyticsService.TrackEventAsync("SecurityThreat", new
                {
                    type = threat.ModuleType.ToString(),
                    confidence = threat.Confidence,
                    metadata = threat.Metadata
                });
                // Don't close - just track
            });
        });
    }
}

Then use in JSON:

JSON
{
  "protections": {
    "DebuggerDetection": {
      "enabled": true,
      "action": "custom",
      "customActionName": "pagerduty-critical"
    },
    "SqlInjection": {
      "enabled": true,
      "action": "custom",
      "customActionName": "siem-log"
    },
    "VirtualMachineDetection": {
      "enabled": true,
      "action": "custom",
      "customActionName": "analytics-track"
    },
    "JailbreakDetection": {
      "enabled": true,
      "action": "custom",
      "customActionName": "user-notify"
    }
  }
}

Benefits of Register-in-Code + JSON Configuration

  1. Separation of Concerns: Business logic in code, configuration in JSON
  2. Environment-Specific Config: Different JSON files per environment
  3. Non-Developer Changes: Ops team can adjust without code changes
  4. Reusable Actions: Register once, use across multiple protections
  5. Type Safety: C# type checking for action implementation
  6. Easy Testing: Test custom actions independently

  • Close - Simple termination
  • Erase - Secure data deletion
  • Log - Simple logging
  • Block - Web request blocking

All Actions

View all action types

Custom Actions Guide

Advanced examples

Previous
Erase