Security & Compliance Whitepaper
Everything a CISO, security engineer, or IT decision-maker needs to evaluate ET Ducky for deployment in enterprise and managed-service environments.
Executive Summary
ET Ducky is a cross-platform endpoint monitoring and behavioral-security platform with first-class agent support for Windows and Linux. The Windows agent uses Event Tracing for Windows (ETW); the Linux agent uses eBPF programs attached to scheduler and syscall tracepoints. Both feed identical event shapes into the same correlation pipeline and the same AI-powered root cause analysis, providing deep visibility into system health, performance, and security events. The platform is designed for SMBs and Managed Service Providers (MSPs) as an alternative to full-stack RMM solutions. Every architectural property described in this document applies to both operating systems unless explicitly noted.
Per-Agent Bearer Tokens
256-bit cryptographic tokens with SHA-256 hashed server-side storage. No shared secrets.
Zero-Trust Multi-Tenancy
Complete organization isolation via Clerk-managed identities and row-level data separation.
TLS Everywhere
All agent-to-cloud, user-to-API, and WebSocket communications enforced over TLS 1.2+.
Behavioral Security Monitoring
An always-on ETW behavioral monitor on Windows detects encryption sweeps, shadow-copy deletion, and backup sabotage with automatic host isolation on high-confidence detections. A cross-platform rule engine on both Windows and Linux watches the kernel-event stream for suspicious exec chains, mass file access, reverse-shell heuristics, non-interactive privilege escalation, and unusual outbound traffic.
Least-Privilege Linux Agent
The Linux agent runs as the unprivileged etducky user under a hardened systemd unit. Privileged actions follow an operator-driven elevation model: each sudo command requires an operator password at the moment of the action, captured in an immutable audit row.
This document covers the platform's security architecture, authentication model, data handling practices, infrastructure hardening, and compliance posture. It is intended to provide the technical detail required for security review and organizational approval.
Architecture Overview
ET Ducky operates as a three-tier SaaS platform consisting of a cross-platform agent (Windows and Linux), a cloud API, and a web-based management dashboard.
Windows Agent
.NET 10 Windows Service running as LocalSystem. Collects ETW events and health metrics. Ships data to cloud API over HTTPS.
Linux Agent
.NET 10 systemd unit running as the unprivileged etducky user with hardened sandbox settings. Collects eBPF kernel events, /proc and /sys metrics, and SMART data. Same wire format and authentication as the Windows agent.
Cloud API
ASP.NET Core 10 application running in Docker on DigitalOcean. Handles agent registration, data ingestion, real-time communications, and AI analysis.
Web Dashboard
React SPA served via static hosting. Communicates exclusively with the Cloud API. Clerk-authenticated.
Database
DigitalOcean Managed PostgreSQL with TimescaleDB extension for time-series telemetry data. Encrypted at rest.
Data Flow
Data Flow Summary
Agent → Cloud API: Health metrics (CPU, memory, disk, network), ETW events, heartbeats. All POST/GET over HTTPS with bearer token authentication.
Cloud API → Agent: Configuration updates, ETW collection commands, shell/file/query session requests. Delivered via Server-Sent Events (SSE) over HTTPS.
Dashboard → Cloud API: User actions (view data, manage agents, configure alerts). Authenticated via Clerk JWT tokens over HTTPS.
Cloud API → Anthropic: Telemetry summaries sent for AI analysis. No PII or credentials included. See AI Integration section.
Authentication & Access Control
Agent Authentication
Agents authenticate to the cloud API using per-agent bearer tokens, a system designed to eliminate shared secrets and ensure each agent has a unique, revocable credential.
| Property | Detail |
|---|---|
| Token Format | Opaque prefixed string with 32 random bytes (256-bit entropy) |
| Generation | Server-side via RandomNumberGenerator.GetBytes(32) (CSPRNG) |
| Server Storage | Only the SHA-256 hash is stored in the database. Plaintext is never persisted server-side. |
| Agent Storage | Bearer token stored in the agent configuration under C:\ProgramData\ETDucky\Agent\AgentConfig.json. On disk it is persisted as a DPAPI-encrypted value bound to the local machine account; the plaintext token is held only in memory after decryption. NTFS ACLs restrict file read access to SYSTEM and local Administrators. |
| Issuance | Returned once during agent registration. Never retrievable again. |
| Transport | Authorization: Bearer <token> header on all HTTPS requests and WebSocket upgrade requests. WebSocket URLs never include the token as a query parameter. |
| Validation | Server hashes incoming token with SHA-256, performs database lookup against stored hash, resolves agent identity. |
| Revocation | Revoke via the admin dashboard or API. Invalidation takes effect immediately on the next request — no grace period or cached sessions. |
Registration Token Flow (Initial Onboarding)
New agents are onboarded using short-lived registration tokens created by organization administrators in the dashboard. These are distinct from bearer tokens:
- Registration tokens are AES-256-GCM encrypted, may have expiration dates and max-use limits, and are used only during the initial
POST /api/agents/register-with-tokencall. - Upon successful registration, the server issues a permanent bearer token to the agent and the registration token is consumed.
- Registration tokens can be revoked at any time via the dashboard.
User Authentication (Dashboard)
User authentication is handled entirely by Clerk, a third-party identity provider. ET Ducky does not store passwords, manage sessions, or handle MFA directly.
| Feature | Implementation |
|---|---|
| Identity Provider | Clerk (clerk.com) — SOC 2 Type II certified |
| Authentication | JWT tokens issued by Clerk, validated server-side on every API request |
| MFA Support | Configurable via Clerk dashboard (TOTP, SMS, passkeys) |
| Session Management | Managed by Clerk; configurable session lifetime and idle timeout |
| SSO | Clerk supports SAML and OIDC enterprise SSO (available on Clerk Enterprise plan) |
| Webhook Verification | All Clerk webhooks verified via HMAC-SHA256 signature (svix-signature header) |
Multi-Tenancy & Role-Based Access
ET Ducky is a multi-tenant platform with a two-level isolation model and defense-in-depth at both the application and database layers.
Workspaces (subdomains) and organizations
- Workspace — the outer isolation boundary, materialized as a subdomain on
etducky.com(e.g.acme.etducky.com). The terms “workspace” and “subdomain” refer to the same entity from the user-facing and infrastructure-facing perspectives respectively; the database column isSubdomainIdand the user-facing label is “Workspace.” Workspaces are auto-provisioned at sign-up with a random readable slug (e.g.etd-x7q3p2) and can be renamed by their owner from Settings → Workspace. Renames are FK'd bySubdomainId, not slug, so every binding (org membership, agent registration, integration config) is preserved; the previous slug remains active as a grace-period alias for a configurable window so in-flight bookmarks, invite links, and agent SSE connections continue to function during the cutover. The*.etducky.comwildcard certificate is centrally managed; customers do not configure DNS or TLS for the default URL. - Clerk Organizations — the inner isolation boundary. One workspace can host multiple Clerk organizations (typical for MSPs managing several client tenants). Agents, events, alerts, scripts, tickets, and integrations are scoped per Clerk organization within a shared workspace. The dashboard's organization picker switches the active scope; the URL stays the same.
- Custom domains — optionally, a customer can map their own domain (e.g.
app.acme.com) to their workspace. Verification is via DNS TXT record; certificates are issued automatically from Let's Encrypt and renewed on a 90-day rotation.
Workspace membership cascade
To prevent inconsistencies between “the user belongs to my workspace” and “the user can actually see anything in it,” ET Ducky enforces a server-side membership cascade between the two layers:
- User joins a workspace — the
WorkspaceMembershipFanoutServiceadds the user to every Clerk organization that already lives in the workspace. The fan-out is invoked from the workspace invite acceptance path, the Clerk webhook handler for org membership creation, and the org-binding admin endpoint, so every code path that creates a workspace membership ends in the same fan-out. - New organization is created in the workspace — all existing workspace members are added as members of the new organization. This means an MSP onboarding a new client doesn't have to re-invite each of their own analysts to the new client org.
- User is removed from a workspace — the cascade reverses, removing them from every Clerk organization in the workspace. A user cannot retain access to organizations in a workspace they no longer belong to.
Per-organization invites at the organization's URL (rather than at the workspace URL) bypass the cascade by design: this is the path used for granting client-only access (e.g. a customer's IT contact who should see their own organization but not other clients in the MSP's workspace).
Cross-workspace enumeration safety
A user can be a member of multiple workspaces. To prevent organization names or membership lists from one workspace leaking into another's UI, every organization picker in the dashboard sources its options from a single server-side endpoint, GET /api/organizations/in-current-subdomain, which returns the organizations belonging to the workspace identified by the request's host header.
- Server is the source of truth. The dashboard does not enumerate organizations from the user's Clerk session (which holds memberships across all workspaces). All dropdown options come from the workspace-scoped endpoint.
- RLS bypass is explicit and bounded. The endpoint runs inside
RootTenantContext.UseAsyncfor the lookup of organizations bound to the current subdomain — necessary because the Organizations RLS policy is scoped to the active organization, not the active workspace. The result set is then re-filtered against the workspace'sSubdomainIdin code before being returned. - Active-org recovery. If the dashboard detects that the user's Clerk-active organization is not in the current workspace's org list (a common case after switching workspaces), it intersects the user's Clerk memberships with the workspace org list, calls
Clerk.setActive()with a valid org, and reloads — rather than letting the user issue requests that would 403 against the workspace.
Database-layer isolation
- PostgreSQL Row-Level Security (RLS) — every tenant-scoped table has a policy of the form
bypass_rls = 'on' OR Id = app_current_org(). Per-request GUCs (app.bypass_rls,app.current_org,app.current_subdomain) are emitted by an EF Core command interceptor before every database command. Policies are enforced by the database itself, independent of application code — a query that omits the tenant filter or runs with the wrong context returns zero rows. - Application-layer filters — EF Core
HasQueryFilterapplies on the same tenant-scoped entities as a second line of defense. A query that escapes EF's filter is still rejected by the database's RLS policy. - Bypass scopes are explicit — only background services, webhook handlers, and bootstrap auth lookups (e.g. validating an agent bearer token before tenant context is set) run inside
RootTenantContext.UseAsync. These call sites are static-analyzed by an in-tree Roslyn analyzer that flags any DbSet read missing a documented bypass justification.
Subscription & quota
- User-scoped licenses (Option B) — a Clerk user holds a single License row carrying their tier and Stripe subscription metadata. Subscriptions and seats follow the user across whatever organizations they belong to.
- Org-pooled quotas at runtime — AI query quota for an organization is the sum of its members' active license quotas. This makes seat-stacking work for teams (your members' subscriptions add up) without coupling subscription ownership to a specific tenant.
What we do NOT do
- No global admin view across customers. Anthropic / ET Ducky staff have no in-product way to see one customer's data while logged in. Admin endpoints are restricted to localhost on the API server (no exposed paths) and gated by an additional shared secret.
- No SQL access path that bypasses RLS by accident. The interceptor emits
bypass_rls='off'by default; explicit opt-in viaRootTenantContextis required. Misconfigured PgBouncer (transaction pooling instead of session pooling) would break GUC propagation, so we run PgBouncer in session-pool mode and the connection string explicitly points at the session-mode listener.
Encryption
| Layer | Standard | Detail |
|---|---|---|
| In Transit | TLS 1.2+ | All agent→API, dashboard→API, and WebSocket connections enforced over HTTPS/WSS. TLS is terminated at Cloudflare's edge (DDoS + WAF); the origin connection from Cloudflare to the DigitalOcean load balancer is re-encrypted, and the load balancer terminates that second hop with managed certificates. |
| At Rest (Database) | AES-256 | DigitalOcean Managed PostgreSQL encrypts all data at rest. Automated daily backups are also encrypted. |
| Registration Tokens | AES-256-GCM | Registration tokens are encrypted with AES-256-GCM before storage. The encryption key is managed as an environment variable, never in source code. |
| Bearer Tokens | SHA-256 | Only SHA-256 hashes are stored server-side. Plaintext tokens exist only in agent config files and in memory during validation. |
| File Integrity | SHA-256 | File hashes for agent update packages and uploaded files computed using SHA-256. |
| Agent Installer | AES-256-GCM | Self-extracting installer packages use AES-256-GCM encryption with a .NET launcher stub for secure deployment. |
Data Collection Scope
ET Ducky collects system telemetry only. The platform is not designed to and does not collect personal user data, browsing history, keystrokes, file contents, or employee activity.
What Is Collected
- Health Metrics: CPU utilization, memory usage, disk space, network I/O, uptime
- ETW Events: Windows kernel and user-mode trace events (process creation, file I/O, network connections, registry activity, service state changes) — configurable per-agent. During AI-driven dynamic diagnostic sessions (see Dynamic ETW Diagnostic Sessions), additional providers may be enabled on a per-investigation basis; events from those providers are counted on the host and the counts-only summary is uploaded — raw event payloads from diagnostic sessions never leave the endpoint.
- System Identity: Hostname, OS version, agent version, IP address at time of connection
- Event Log Summaries: Recent error counts from Windows Event Log (configurable lookback window)
What Is NOT Collected
- User credentials, passwords, or authentication tokens from monitored systems
- File contents, email content, or application-layer data
- Keystrokes, screen captures, or user behavior tracking
- Personal Identifiable Information (PII) beyond machine hostname
- Browser history, cookies, or session data
Data Retention
ET Ducky offers configurable per-agent data retention with automatic purging enforced by a background service.
| Tier | Retention Period | Price | Purge Method |
|---|---|---|---|
| Default | 14 days | $0 | Automatic background service |
| Extended | 90 days | $0.50/agent/month | Automatic background service |
| Annual | 365 days | $1.50/agent/month | Automatic background service |
| Maximum | 730 days | $2.50/agent/month | Automatic background service |
Data purging runs as a scheduled background task that deletes telemetry older than the configured retention window. Purged data is permanently deleted from the database; no archival copies are maintained unless configured by the customer at the infrastructure level.
Data Residency
All ET Ducky infrastructure is currently hosted in DigitalOcean's US regions. Data does not leave the United States for storage or processing, with one exception: AI analysis requests are sent to Anthropic's API (see AI Integration).
Hosting & Infrastructure
| Component | Provider | Detail |
|---|---|---|
| Application Server | DigitalOcean Droplet | Docker containerized ASP.NET Core 10 application |
| Database | DigitalOcean Managed PostgreSQL | TimescaleDB extension, encrypted at rest, automated backups, private VPC networking |
| DNS / CDN | Cloudflare | DDoS protection, TLS termination, WAF rules |
| Frontend Hosting | Static / CDN | React SPA served via Cloudflare-proxied static hosting |
| Container Runtime | Docker Compose | Single-container deployment with health checks and restart policies |
Network Security
- AllowedHosts: API configured to only accept requests with
Host: etducky.comheader, preventing host header injection attacks. - CORS Policy: Strictly limited to
https://etducky.com. No localhost or wildcard origins permitted in production. - Database Access: PostgreSQL accessible only via DigitalOcean's private VPC network and trusted IP sources. No public internet exposure.
- SSH Access: Hardened SSH configuration with key-only authentication and password login disabled.
- Docker Networking: API container ports bound to localhost only; external traffic routed through reverse proxy with TLS.
- Admin Endpoints: Administrative API endpoints restricted to localhost-only access (127.0.0.1/::1), not reachable from the internet.
Secrets Management
All sensitive credentials are managed via environment variables injected at runtime through Docker Compose and .env files with restricted permissions (chmod 600). No secrets are stored in application configuration files, source code, or container images. Migration to Docker Secrets (file-based injection via /run/secrets/) is planned to eliminate secrets from process environment visibility.
| Secret | Purpose | Rotation |
|---|---|---|
| PostgreSQL credentials | Database authentication | Rotatable via DigitalOcean dashboard |
| Clerk API keys | User identity management | Rotatable via Clerk dashboard |
| Stripe API keys | Billing / subscriptions | Rollable via Stripe dashboard |
| Anthropic API key | AI analysis engine | Rotatable via Anthropic console |
| SendGrid API key | Transactional email | Rotatable via SendGrid dashboard |
| SSL.com eSigner credentials | EV code signing (installer signing) | Rotatable via SSL.com dashboard; TOTP secret regenerated on rotation |
| AES-256 encryption key | Registration token encryption | Rotatable (invalidates active registration tokens only) |
| Admin secret | Localhost-only admin API access | Rotatable via openssl rand |
Agent Installation & Deployment
Windows Agent
The Windows agent is deployed as a Windows Service installable via a self-extracting installer or MSI package.
| Property | Detail |
|---|---|
| Runtime | .NET 10 (self-contained, no external runtime required) |
| Service Account | LocalSystem, required for ETW kernel-level trace access |
| Installation Path | C:\Program Files\ETDucky\ |
| Data Path | C:\ProgramData\ETDucky\Agent\ |
| Silent Install | Supported via /S flag for mass deployment (SCCM/Intune compatible) |
| Installer Security | AES-256-GCM encrypted self-extracting archive with .NET launcher stub |
| Auto-Update | Agent checks for updates every 6 hours and downloads verified packages from API |
| At-Rest Token Protection | The bearer token in AgentConfig.json is wrapped with DPAPI bound to the LocalSystem account, so a copy of the file off-host is useless. |
Linux Agent
The Linux agent is deployed as a systemd unit via .deb, .rpm, or universal .run packages, or via the install.sh one-liner enrollment flow.
| Property | Detail |
|---|---|
| Runtime | .NET 10 (self-contained, no external runtime required) |
| Service Account | Unprivileged etducky:etducky user. Privileged operations route through the operator elevation flow described below. |
| Capture Backend | libbpf-based eBPF programs attached to scheduler and syscall tracepoints (sched_process_exec, sys_enter_openat, sys_enter_connect, sys_exit_accept4). CO-RE relocations with BTFHub fallback. Requires kernel 5.4 or later; earlier kernels run in a graceful no-op mode that still ships health metrics. |
| journald Capture opt-in | Optional reader that tails journalctl --output=json --follow and emits each entry as a normalised SystemEvent on the same pipeline as eBPF. Surfaces failed service starts, OOM kills, sudo/su sessions, SSH login chains, kernel WARN_ON dumps. Default priority floor is warning; throttled to 1000 lines/minute with a synthetic marker emitted when lines are dropped so downstream consumers can detect signal loss. Cursor (__CURSOR) is persisted to /var/lib/etducky/journald.cursor so restarts don't replay history. Disabled by default. |
| auditd Capture opt-in | Optional reader that polls ausearch --raw --start checkpoint --interpret on a 30-second cadence (kernel-side cursor — no manual state file). Surfaces file-watch hits, capability use (CAP_SYS_ADMIN etc.), SELinux/AppArmor AVC denials, USER_LOGIN/USER_END records. The systemd unit grants AmbientCapabilities=CAP_AUDIT_READ so ausearch works without root; the optional auditctl rule install needs CAP_AUDIT_CONTROL. Disabled by default; on hosts without auditd the reader logs a single warning and exits cleanly. |
| Installation Path | /opt/etducky/agent/ |
| Data Path | /var/lib/etducky/ (mode 0750, owned by etducky) |
| Config Path | /etc/etducky/agent/AgentConfig.json (mode 0600, owned by etducky). Agent refuses to start if the config file has weaker permissions. |
| systemd Hardening | ProtectSystem=strict, ProtectHome=read-only, PrivateTmp=yes, ProtectKernelTunables=yes, ProtectControlGroups=yes, RestrictNamespaces=yes. Capability bounding set is restricted to what eBPF and operator-elevated commands require. |
| Resource Bounds | MemoryMax=512M, CPUQuota=50%, TasksMax=256. A runaway agent process cannot starve the host. |
| Silent Install | Supported via install.sh with environment variables for unattended enrollment. |
| Auto-Update | Agent polls the API on the heartbeat cadence and self-installs verified packages via apt/dnf or the universal extractor. |
Operator-Driven Privilege Elevation (Linux)
The Linux agent does not run with standing root authority. When an AI live session generates a privileged command (sudo apt install, sudo systemctl ..., etc.), the agent does not execute it directly. Instead, it posts an elevation request to the cloud API; the dashboard pops a modal for the responsible operator with the command summary; the operator types the host's sudo password; the cloud API forwards the password to the agent over the same authenticated SSE channel that delivers commands; and the agent runs the command via sudo -S with the password fed in over stdin. Each elevation produces an immutable audit row capturing:
- The Clerk user id of the authenticating operator
- The source IP and user agent of the dashboard request
- The command summary and the full command text
- The full lifecycle timestamps (pending, granted, executed, completed)
- Exit code and any error summary
Passwords are never stored. They cross the wire as part of the SSE grant payload encrypted in transit, are zeroed in agent memory after use, and never appear in any log. A narrowed /etc/sudoers.d/etducky-rmm drop-in grants NOPASSWD only for read-only diagnostics (smartctl, dmidecode, lshw, journalctl, dmesg) and the systemctl restart etducky-agent self-management command. Everything else routes through the operator-elevation flow.
The result is that compromise of the agent does not equal compromise of root. An attacker who pivots into the etducky service account can exfiltrate the agent's bearer token (which only authenticates to one specific organization on the cloud API) but cannot run privileged commands without convincing a real operator to type a password into the dashboard.
Agent Resource Footprint
The agent is designed for minimal system impact:
- Health-Only Mode (default): Collects only system health metrics (CPU, memory, disk, network) with negligible overhead. ETW event tracing is disabled by default and enabled on-demand from the dashboard.
- Bandwidth Optimization: A correlation engine aggregates and summarizes ETW events before transmission, achieving approximately 99.95% bandwidth reduction compared to raw event forwarding.
- Memory Optimization: On-demand ETW collection control reduces memory usage by approximately 98.9% when ETW is not actively needed.
- Local Buffering: Events are buffered in a local SQLite database (
events.db) to survive network interruptions. Buffer is capped at a configurable max size (default: 10,000 events) with automatic cleanup. - Configurable Intervals: Collection and transmission intervals are tunable (default: 60 seconds each).
Agent Communications
Communication Channels
- HTTPS REST API — Registration, heartbeats, data upload, configuration polling. All requests use
Authorization: Bearerheader. - Server-Sent Events (SSE) — Real-time command channel from server to agent. Agent maintains persistent HTTPS connection. Used for ETW start/stop commands, configuration pushes, script execution, session requests, and isolation management (
agent.unisolatefor remote network isolation lift). All dispatched commands are risk-scored and logged before delivery. Commands that include configuration JSON are filtered on both the server and agent to strip protected keys (e.g., bearer tokens, API endpoint, agent ID) before persistence. - WebSocket (WSS) — Used only for remote desktop relay sessions. Authenticated via
Authorization: Bearerheader during the WebSocket upgrade; tokens are never transmitted in the URL or query string. Sessions are ephemeral and initiated only by authenticated dashboard users.
The agent never opens inbound ports or listens for incoming connections. All communication is initiated outbound by the agent to https://etducky.com.
TLS Certificate Pinning: The agent validates the server's TLS certificate against a set of SPKI SHA-256 pin hashes compiled into the binary, in addition to standard OS certificate chain validation. This prevents MITM attacks even if a rogue certificate authority is trusted at the OS level. A two-slot rolling pin rotation is supported: the server pushes a "next" pin via the heartbeat response so pins can be rotated without an agent update.
File transfer path policy (agent-enforced)
Bidirectional file transfers between the dashboard and the agent are constrained by a hardcoded path allow-list inside the agent itself, not negotiated server-side:
- Push (dashboard → agent): the agent always writes pushed files to
C:\ProgramData\ETDucky\Agent\Downloads\<filename>. ThedestinationPathfield in the API request is intentionally ignored on the agent side — a comment inFileTransferService.csdocuments this: "server-provided destinationPath is intentionally ignored to prevent arbitrary writes." A compromised dashboard or stolen Clerk session cannot land files in arbitrary locations on the agent host. - Pull (agent → dashboard): source paths must resolve to a location under
C:\ProgramData\ETDucky\Agent\. Anything else is rejected with the literal string "Source path not allowed by agent policy." The agent treats the dashboard request as an untrusted hint and applies its own allow-list before opening any file. - Chunk integrity: all transfers happen in 1 MB chunks. Chunks are transmitted as base64 over HTTPS, with SHA-256 file-level integrity verification once reassembly completes.
The effect is that the agent treats the dashboard as a directing authority, not a trusted commander. Even if our cloud were fully compromised, the agent cannot be coerced into reading or writing outside its own data directory.
Behavioral Security Monitoring
ET Ducky's behavioral security layer has two parts. On Windows, an always-on ETW behavioral monitor runs a dedicated kernel session and triggers automatic network isolation on high-confidence detections (described first below). On both Windows and Linux, a cross-platform rule engine subscribes to the same kernel-event stream the diagnostic pipeline uses and fires named-rule detections that surface in the dashboard with the actual triggering events attached as evidence (described second).
Windows ETW Security Monitor
The Windows agent runs a dedicated ETW kernel session (ETDucky_Security) entirely independent of the on-demand diagnostic session. The monitor observes a narrow slice of system activity, file renames, process spawning, and registry writes, and feeds it through four specialized detectors. No events are ever persisted to disk by this subsystem; data is evaluated in-memory and discarded.
| Detector | What It Watches | Confidence Model |
|---|---|---|
| File Encryption Tracker | Per-process file rename rate with extension changes within a rolling 30-second window (default threshold: 20 renames). Recognises ~40 known ransomware extensions (.locked, .ryuk, .lockbit, .wncry, etc.). | Critical if ≥50% renames match known extensions; High if all renames converge on a single unknown extension; Medium otherwise. |
| Shadow Copy Deletion | Process command lines matching vssadmin delete shadows, wmic shadowcopy delete, bcdedit /set recoveryenabled No, wbadmin delete catalog/backup, and PowerShell-wrapped variants. | Always Critical — these commands have no routine administrative purpose. |
| Backup Sabotage | sc.exe / net.exe / PowerShell commands that stop or disable VSS, Windows Backup, or common third-party backup agents (Veeam, Acronis, Backup Exec). Also watches for direct registry writes that set backup service start type to Disabled (value 4). | Always Critical. |
| Process Ancestry | Suspicious parent→child spawn chains: Office apps, browsers, PDF readers, and script hosts spawning cmd.exe, PowerShell, certutil, bitsadmin, regsvr32, rundll32, schtasks, etc. | High if child launched from a staging path (\temp\, \appdata\, \public\, etc.); Medium otherwise. |
A per-detection-type cooldown (default: 60 seconds) suppresses alert floods during a single attack burst. Each alert includes a human-readable evidence summary and full raw evidence in the ticket body.
Automatic Network Isolation
When a detection meets or exceeds the configured minimum confidence (default: High), the agent automatically applies network isolation by setting the Windows Firewall default outbound action to Block across every profile (Domain, Private, Public) and adding explicit Allow rules prefixed ETDucky-Isolation-. The combined effect is that all outbound traffic is denied except:
- The ET Ducky agent process — a
program=allow rule on the agent executable so the agent keeps reaching the cloud regardless of cloud-side IP rotation - The ET Ducky API endpoint (
etducky.com) — a backup IP-based allow rule using addresses resolved at isolation time - DNS resolution — UDP/TCP port 53 from the Windows DNS Client service (
svchost.exe), required because hostname resolution on Windows happens in a separate process from the calling agent - Loopback (127.0.0.0/8). IPv6 loopback is permitted implicitly by Windows Firewall's default loopback handling.
- Operator-configured vendor allowlist (CrowdStrike, SentinelOne, Microsoft Defender for Endpoint, etc.) via
SecurityMonitoring.IsolationAllowedHosts
Isolation is idempotent. The agent persists its isolation state to %ProgramData%\ETDucky\isolation.state on every transition; on startup it reconciles persisted state against rules-on-disk so legitimate isolation survives reboots, accidental leftovers from a crashed prior run are cleaned up, and a stuck default-block with no rules is restored to the operator's pre-isolation outbound policy. A ticket is submitted to the organisation's connected ticketing system with the full alert details, including a note that isolation was applied.
Why profile-default-block rather than an explicit Block-Outbound rule. Windows Firewall evaluates rules in the order [authenticated bypass → block → allow → default action]. A block rule with program=Any wins against any allow rule regardless of specificity, so the seemingly natural "block everything, allow the agent" pattern can never let the agent through. Setting the profile-level default to Block and relying on Allow rules to punch through is the Microsoft-documented quarantine pattern and the only model that lets specific-program allows function correctly.
Hardening: Restricted Operations While Isolated
When an agent is in any non-normal isolation state (isolating, isolated, or unisolating), the cloud refuses admin-initiated commands that could be used to bypass the dual-party lift flow. This is the primary defense against a compromised dashboard admin account using ET Ducky's legitimate command surface to push system-level activity onto a quarantined endpoint. The agent itself also refuses the same set of events (defense-in-depth) when NetworkIsolationService.IsIsolated == true.
Blocked while isolated: shell command execution (interactive sessions and ad-hoc), script execution (single-agent and multi-agent — isolated targets skipped from a fleet run with a per-agent error), live troubleshooting sessions (single and multi-agent), live-session query submission, remote desktop sessions, file push to agent, file pull from agent, ETW collection start (collection stop remains allowed for cleanup), configuration push, remote agent restart, configuration reset to defaults, and agent uninstall.
Still allowed: heartbeats and reporting, isolation lift commands themselves (the dual-party flow), session/transfer cleanup operations, isolation-state reads by the dashboard. The agent remains visible, reachable, and recoverable; only the system-level command surfaces a compromised admin would need to undermine isolation are gated.
Isolation Lift
Isolation removal uses a dual-approval model: an authenticated request from the dashboard is necessary but not sufficient — a user physically present at the device must independently approve the request before firewall rules come down. This design ensures that a compromised dashboard account, stolen session cookie, or malicious insider with valid credentials cannot silently de-isolate a device. The on-device operator is always notified and must consent.
Two paths satisfy the dual-approval requirement:
- Local lift (HMAC-TOTP code): an org admin generates a one-time code in the dashboard and a user with physical access to the device enters it in
LiftIsolationForm. The code is HMAC-TOTP-signed against a hash of the agent's bearer token, valid within a 10-minute TOTP window (the agent accepts the current window ± 1, giving up to ~20 minutes of effective validity to absorb clock skew), single-use, and verified entirely on-device. Possession of either factor alone does nothing — the dashboard can't lift without the user, and the user can't lift without a freshly-issued code. - Remote lift (dashboard-initiated, on-device approval): an authenticated dashboard operator pushes an
agent.unisolatecommand via the SSE channel. The agent generates a single-use nonce, spawnsUnisolateApprovalFormin the active console session via session-0 cross-session launch, and waits up to 5 minutes for the user to click Approve. Only after explicit on-device approval does the firewall rule come down. If no console session exists, the form fails to launch, the user clicks Deny, or the 5-minute timer expires — the lift is denied and the host stays isolated.
Every lift event — approved, denied, or timed out — is recorded in the per-tenant audit log with the requesting dashboard user, the on-device approver (if any), timestamp, and source IP, so security teams can reconstruct any incident's full chain of authorization.
Three paths exist depending on the device state:
- Remote lift with device approval (primary path): An authenticated administrator sends an
agent.unisolatecommand via the SSE channel. The agent spawns an approval dialog on the active interactive desktop (the logged-in user's visible screen) usingWTSQueryUserToken+CreateProcessAsUserto cross the Session 0 isolation boundary. The dialog displays a security alert, a 5-minute countdown, and ET Ducky support contact details. The user must explicitly click Approve; closing the window or timeout auto-denies. Only on approval does the agent remove allETDucky-Isolation-*firewall rules. - No interactive session (permanent rejection): If no user is logged in when the command arrives, the agent permanently rejects the request. It reports back to the cloud via
POST /api/agents/{id}/isolation/unisolate-rejected, which broadcasts anagent.unisolate.rejectedSSE alert to all org dashboard connections. The only resolution is to delete the agent from the org dashboard and re-install it after physical access to the device is restored. - Local lift code (offline endpoints): If the endpoint cannot reach
etducky.com, a technician physically present at the machine can enter a one-time code generated from the dashboard. The code is an 8-character Crockford Base32 string derived as follows:
Lift Code Algorithm
window = unix_time() / 600 # 10-minute TOTP-style window
key = SHA-256(bearer_token) # server stores this; agent derives it at runtime
data = "etducky-isolation-lift-v1:{window}"
hmac = HMAC-SHA256(key=key, data=data)
code = CrockfordBase32(hmac)[0:8]
- Key derivation: The HMAC key is
SHA-256(bearer_token), not the raw token. The server stores only this hash (BearerTokenHash) and uses it directly; the agent hashes the plaintext it holds in memory. Neither side ever transmits or stores the raw token beyond the initial registration response. - The agent accepts codes from the current window ± 1 window (up to ~20-minute effective validity) to absorb clock skew.
- Each code is single-use: the agent records accepted codes and rejects replays.
- Constant-time comparison is used to prevent timing-based oracle attacks.
- The Crockford Base32 alphabet (no I, L, O, U) reduces transcription errors.
Isolation Threat Model
The isolation feature is designed against a specific set of threats with explicit defenses, and explicitly acknowledges one residual gap that no endpoint security product can fully close. The honest disclosure here helps customers reason about what the feature can and cannot do.
| Threat | Can lift isolation locally? | Can mark agent as normal cloud-side? |
|---|---|---|
| Compromised dashboard admin only (phished session, stolen cookie, malicious insider with valid credentials) | No — requires on-device user consent | No |
| Compromised local Windows user (non-SYSTEM) | No — cloud must initiate the lift | No |
| Compromised local Windows SYSTEM / Administrator on the host | Yes — can directly modify Windows Firewall rules and profile defaults via netsh / Set-NetFirewallProfile |
No — cloud state still reflects "isolated" until an authenticated lift POST arrives; the discrepancy is visible to operators |
| Both compromised cloud admin + compromised on-device user (intended dual-party path) | Yes — this is the legitimate lift flow by design | Yes |
The local-SYSTEM row is the residual gap that no Windows-based endpoint security tool can fully close: an attacker who has already escalated to SYSTEM owns the firewall stack and can disable any rule it wants. ET Ducky's design property is that the cloud-side state cannot be modified by a local SYSTEM attacker — isolation status in the dashboard remains accurate even if local enforcement has been bypassed. An operator reviewing the dashboard against ground truth on the host will see the discrepancy. This is consistent with the security model of every comparable product (CrowdStrike, SentinelOne, Microsoft Defender for Endpoint, etc.) — once SYSTEM is conceded, local controls are advisory; only the cloud's record of isolation status is authoritative.
The hardening described in §Restricted Operations While Isolated additionally ensures that even a compromised dashboard admin cannot use ET Ducky's command surface (shell, scripts, sessions, remote desktop, file transfer, config push, uninstall) to drive a compromised-SYSTEM-on-host into a "both factors compromised" state without independent consent from the on-device user.
Kill Switch
The security monitor can be disabled entirely by setting SecurityMonitoring.Enabled = false in AgentConfig.json. This is a graceful kill switch that stops the ETW session without requiring an agent restart. The setting is also configurable remotely via the standard config.change SSE command.
Cross-Platform Rule Engine
In addition to the Windows-specific ETW security monitor, the agent runs a cross-platform behavioral rule engine that subscribes to the same kernel-event stream the diagnostic pipeline uses (ETW on Windows, eBPF on Linux). Rules are defined once and fire on either operating system from a single definition. Five rules ship today:
| Rule | What It Watches | Default Severity |
|---|---|---|
| Suspicious Exec Chain | A shell process executes a network downloader (curl, wget, certutil, bitsadmin), and the downloader's PID then spawns another shell within 30 seconds. The canonical pattern for piped-to-shell attacks. | High |
| Mass File Access | A single process touches 200+ distinct paths in 5 seconds, and the paths span at least 3 user-data root directories. Tuned to fire on commodity ransomware behaviour without flagging legitimate sweeps that stay within one tree. | High |
| Reverse-Shell Heuristic | A shell binary executes within 10 seconds of a network event on the same process tree. Heuristic by design; legitimate session daemons (sshd accepting and spawning bash) trigger the same pattern, so the rule's evidence panel includes the network endpoint so operators can verify. | High |
| Privilege Escalation From Non-Interactive Parent | sudo, pkexec, su, doas, or runas spawned from a parent that is not on the interactive-shell allowlist (bash/sh/zsh, sshd, login, terminal multiplexers). Suggests escalation in a daemon, cron job, or exploit context rather than a human shell. | Medium |
| Unusual Outbound From System Daemon | A whitelisted system daemon (sshd, chronyd, systemd-resolved, postgres) initiates an outbound connection to a port that is not on its expected list. Suggests credential-stuffing C2, exfiltration to a non-standard port, or a misconfigured upstream. | Medium |
Each detection is persisted to the per-organization AgentBehavioralDetections table with the rule id, severity, the process the rule pinned the match to, and the actual triggering events as evidence (capped at 10 entries per detection). Detections push to the org's dashboard within seconds of observation via Server-Sent Events. Acknowledgement is operator-attributed and idempotent. Rules are versioned with the agent today; database-backed rule definitions with hot-update are on the near-term roadmap.
The cross-platform rule engine and the Windows ETW security monitor coexist. The ETW monitor's automatic network isolation on encryption sweeps and shadow-copy deletion remains the highest-confidence Windows-only response; the cross-platform rules surface earlier-stage indicators before automatic isolation criteria are met.
Per-Process False-Positive Suppression
Several legitimate workloads pattern-match against the behavioral rules: AI coding assistants legitimately read many files for context analysis (trips Mass File Access); backup agents do the same; some build systems use curl | sh as an install bootstrap (trips Suspicious Exec Chain). To suppress these without disabling the rule for any other process, organization admins maintain a Behavioral Detection Allowlist — a per-organization list of (process name, rule id) tuples. The list is edited on the Integrations page and exposed at /api/organizations/{clerkOrgId}/behavioral-allowlist.
Enforcement happens server-side before a detection is persisted: the cloud API loads the allowlist into a hash set keyed by (process, rule), scans incoming detections, and drops matches. Suppressed counts are logged but never stored, so an attacker cannot use the allowlist UI to mask an attack and then have the suppression itself be audit evidence. Agents fetch their organization's copy from /api/agents/me/behavioral-allowlist at startup and on configuration polls; future agent versions self-filter so the suppressed bytes never leave the host.
Exemptions are scoped per-rule. Allowing claude.exe on Mass File Access does not exempt it from Suspicious Exec Chain or any other rule. Only organization admins can edit the list; member-role users can read it (so unprivileged agent fetches and dashboard reads still work). The recommendation is to keep entries narrow — broad exemptions weaken the protection model.
Data Minimisation & Event Upload Policy
ET Ducky agents do not continuously stream raw kernel events to the cloud. By default, only the following crosses the wire:
- Aggregate health metrics (CPU, memory, disk, network, hardware health) on the heartbeat cadence (default 60 seconds).
- Inflection-bracketed evidence: when a metric anomaly fires, the agent attaches the kernel events from the surrounding window so the cloud can show "what was happening when CPU spiked" without rejoining against an event store.
- Behavioral detections: each rule firing carries its hand-picked triggering events, capped at 10 per detection, as evidence.
Raw kernel events stay on the endpoint. They are kept in a bounded local buffer that ages out under a configurable retention policy (default 60 seconds for the in-process working set, longer for the on-disk SQLite buffer if events would have shipped but the network was down).
When an operator opens a live session or issues an explicit collection command from the dashboard, a reference-counted upload gate opens for the duration of that work. While the gate is open, the full kernel-event stream from that agent ships to the cloud. When the operator closes the session or the collection command's window expires, the gate closes and the agent returns to minimised upload mode. The result is that quiet hosts transmit very little; hosts under investigation transmit the full stream the operator asked for, and only those.
An on-agent significance filter further curates what flows even while the gate is open: shared library loads, locale catalog opens, /proc reads from system daemons, and other high-volume noise are dropped or deduplicated locally. This applies on both operating systems and means that "we have eBPF/ETW running" does not translate to "we ship 10k+ events per heartbeat" the way an unfiltered firehose would.
Dynamic ETW Diagnostic Sessions
When an operator opens a guided troubleshooting session, ET Ducky now runs an AI-driven diagnostic ETW session alongside the always-on baseline. Instead of either capturing the full firehose or asking the operator to pick providers manually, the AI picks the ETW providers for each round of the investigation, observes what arrives, and decides which providers to enable next. The architecture is the substantive product differentiator: nobody else (that we're aware of) is orchestrating the ETW session layer with an AI in the loop.
Two-Session Isolation
The diagnostic session is a separate TraceEventSession pair with a unique per-investigation name — never the baseline ETDucky_Kernel / ETDucky_User sessions. A bug or misconfiguration on the diagnostic side cannot drop, mute, or modify always-on telemetry. The two sessions share no state and tear down independently.
Each investigation creates its own engine instance on the agent. The AI plans a round at a time: it sees the host's tier-filtered provider catalog (Tier 1 well-known plus Tier 2 recently-active, roughly 200 providers out of the 1,500–2,500 the typical Windows host registers), the currently-enabled providers, the most recent evidence snapshot (counts only — see below), and the engine's remaining budget headroom. It returns a structured plan: which providers to enable, which to disable, how long to capture before the next round. The loop applies, captures for the bounded window, snapshots, and re-plans, until the AI concludes or the round cap fires (default 5, hard ceiling 10).
Raw events from diagnostic sessions stay on the host. The engine counts events into a per-(provider, event id, task, opcode) tally; only that counts-only summary travels back to the cloud. Tear-down at the end of the investigation purges the diagnostic session's event buffers and disposes both underlying TraceEventSession objects. The data-stays-local invariant the agent has always held for baseline telemetry continues to hold for AI-driven dynamic diagnostics: the conclusion travels (which providers fired, how often, what the AI concluded); the evidence stays on the endpoint.
One narrow addition to the round-summary payload: alongside the counts-only breakdown, the agent ships any pre-classified verdicts emitted by a local rule engine that runs against the round's events before tear-down. Each verdict is a fixed-vocabulary record — severity, a known rule identifier (e.g., AadConditionalAccess, TlsUntrustedRoot, KerberosSpnUnknown), the rule's pre-authored explanation text, and a pre-authored suggestion. No raw event payloads, file paths, IP addresses, hostnames, or process identifiers are included in the verdict. The rule engine reads the events; the verdict carries only the verdict. The local in-session sample the rules consulted (bounded at 1,000 events) is discarded with the rest of the diagnostic session's raw buffers in the tear-down step, so the data-stays-local invariant is preserved: derived findings travel, raw evidence does not.
The dashboard does not expose a manual provider picker for the diagnostic session. The live-session UX stays AI-orchestrated end-to-end — the operator describes the issue in natural language, the AI handles provider selection. Operators who want to think about ETW providers directly reach for the standalone ETDucky Provider Explorer (the OSS sister tool), not the production dashboard.
Engine-Enforced Budget Caps
The AI is constrained by the engine, not trusted to behave. Per-investigation budget caps are enforced inside the dynamic capture engine itself; the AI cannot bypass them, override them, or negotiate around them. A request that would exceed a cap is refused at the API boundary with a structured error the AI must re-plan around.
| Cap | Default | Enforcement Point |
|---|---|---|
| Concurrent providers per session | 16 | Admission check on EnableProviderAsync |
| Aggregate events/sec per session | 25,000/s | Admission check (projection) + rolling-window watchdog |
| Aggregate events/sec across all diagnostic sessions on the host | 50,000/s | Process-global accumulator; admission + watchdog |
| In-flight buffer memory per session | 64 MiB | Admission check |
| Hypothesis-loop rounds per investigation | 5 default / 10 hard ceiling | Loop guard — runaway loops self-terminate inside two minutes at defaults |
| Per-round capture window | 10–120 seconds | Loop guard |
When in-flight throughput exceeds a session cap (the cost catalog's estimate was wrong, or the host is busier than projected), the engine triggers emergency scale-back: the most-recently-enabled provider is automatically disabled and a structured event is raised so the AI can re-plan rather than retry blindly. Concurrent investigations per host are also capped (default 4) and any diagnostic session that goes 15 minutes without a command from the cloud is reaped by an on-agent sweeper, so a cloud orchestrator that loses track of an investigation cannot leave engines pinned indefinitely.
Remediation Script Handoff
When an investigation concludes with a known-fix pattern, the AI generates a remediation script (PowerShell on Windows, Bash on Linux) that is pushed through the existing Process Automations approval gate — the same org-admin review flow that protects recorder-generated scripts. The script row is created with ApprovalStatus = "pending_review" and an associated review ticket is filed in the org's ticketing system; no remediation runs until an organization administrator approves.
Two execution modes:
- Live guided-troubleshooting session, operator attending: the script is created with
auto_run_eligible = true. After approval, the operator can run it immediately in-session through the existing Process Automations execution path (which itself enforces command security policy). - Background / scheduled / dashboard-initiated investigation, no operator: the script is created with
auto_run_eligible = falseand stays as analysis-only. A human picks it up, reviews, and decides whether to run.
The product claim that ET Ducky does not take unauthorised actions on customer hosts remains intact: the approval gate, the per-command security policy, and the org-admin role-check apply equally to AI-generated remediation scripts and to scripts written by humans. AI-generated remediations are tagged with Origin = "process_automation" and a CreatedBy = "dynamic-etw:<jobId>" marker so the audit trail makes the source unambiguous.
AI Integration Security
ET Ducky uses Anthropic's Claude API for AI-powered root cause analysis, natural language querying, and smart reporting.
| Concern | Implementation |
|---|---|
| Data Sent to AI | Aggregated telemetry summaries only: CPU/memory trends, event correlation summaries, error patterns. No PII, credentials, file contents, or raw user data. |
| AI Provider | Anthropic (anthropic.com) — does not train on API data per their commercial terms. |
| Data Retention by AI | Anthropic API does not retain prompt/response data beyond the request lifecycle per their data policy. |
| Network Path | Server-side only. AI requests originate from the cloud API, never from the agent or browser. |
| Opt-Out | AI analysis features are user-initiated (not automatic). No telemetry is sent to AI providers unless a user explicitly triggers an analysis. |
| Sensitive Data Filtering | Prompts are constructed server-side with allowlisted query types. Raw database queries are parameterized and validated against an allowlist-based QueryEngine. |
Third-Party Service Dependencies
| Service | Purpose | Data Shared | Compliance |
|---|---|---|---|
| Clerk | User authentication & identity | Email, name, org membership | SOC 2 Type II |
| Stripe | Payment processing | Billing email, subscription status | PCI DSS Level 1 |
| Anthropic | AI analysis engine | Aggregated telemetry summaries | SOC 2 Type II |
| SendGrid | Transactional email (alerts) | Recipient email, alert content | SOC 2 Type II |
| DigitalOcean | Infrastructure hosting | All platform data | SOC 2 Type II, ISO 27001 |
| Cloudflare | DNS, CDN, DDoS protection | HTTP traffic metadata | SOC 2 Type II, ISO 27001 |
Supply Chain & Dependencies
- Agent (Windows): .NET 10 self-contained build with no runtime dependencies on the target system. Package dependencies sourced from NuGet with deterministic builds.
- Agent (Linux): .NET 10 self-contained build packaged as
.deb,.rpm, and universal.run. The eBPF kernel programs are compiled with Clang as part of the build pipeline; CO-RE relocations let the same binary run across distributions and kernel versions, with BTFHub providing the BTF data on older kernels that lack/sys/kernel/btf/vmlinux. - API Server: ASP.NET Core 10 running in official Microsoft Docker base image. NuGet packages for Clerk SDK, Stripe SDK, Npgsql (PostgreSQL driver).
- Frontend: React SPA built from npm packages. Static assets served via CDN.
Logging & Auditing
- Structured Logging: All API server logs use Serilog structured logging with timestamp, request path, response code, and timing data.
- Agent Connection Tracking: SSE connection/disconnection events are logged with agent ID, organization ID, and connection IDs.
- Authentication Events: All authentication attempts (bearer token and legacy) are logged. Failed authentication returns 401 with no information leakage about valid agent IDs.
- Webhook Audit: Clerk webhook events are signature-verified and logged for audit trail.
- Alert Rule Evaluation: Alert evaluations are logged per-agent with timestamps for compliance traceability.
- Script Audit: Every script creation and modification is logged with user identity, organization, timestamp, and SHA-256 content hash for tamper detection.
- Command Security Audit: Every command execution — both ad-hoc and script-based — is risk-scored and logged to
ShellCommandSecurityLogswith risk score, matched indicators, user identity, target agent, command hash, and execution decision. High-risk commands (score ≥60) generate elevated warning logs for security review.
Incident Response
Autonomous Ransomware / Compromise Detection
The always-on behavioral monitor detects and responds to ransomware and endpoint compromise automatically — before a human operator reviews the alert:
- The security ETW session (
ETDucky_Security) detects a behavioral indicator (file encryption sweep, shadow copy deletion, backup sabotage, or suspicious process spawn). - If confidence is High or Critical, Windows Firewall isolation is applied immediately — blocking all traffic except loopback and the ET Ducky API endpoint.
- A security ticket is submitted automatically to the organisation's connected ticketing system with a full markdown summary and raw evidence.
- After verifying the alert is a false positive or confirming remediation is complete, an administrator sends a remote
agent.unisolatecommand from the dashboard. The agent presents an approval popup to the logged-in device user, who must explicitly approve before firewall rules are removed. If no user is logged in, the request is permanently rejected and the org is alerted. Alternatively, a technician on-site can enter a dashboard-generated HMAC-TOTP lift code directly at the machine.
Agent Compromise Response
If an agent or its bearer token is suspected to be compromised:
- Revoke the agent's bearer token via the dashboard or admin API — immediately prevents all further API access.
- Mark the agent as inactive via the dashboard — prevents data submission.
- Investigate via the agent's historical telemetry for anomalous behavior prior to detection.
- Reinstall the agent with a fresh registration token to issue a new bearer token.
Platform Abuse Response
If the platform is being used to execute unauthorized scripts or deploy unauthorized software:
- Suspend the user account via the identity provider dashboard — revokes all JWT tokens and blocks API access.
- Revoke all registration tokens for the affected organization — prevents new agent deployments.
- Invalidate bearer tokens for affected agents — stops agent communication on next heartbeat.
- Deactivate compromised agents via the admin API — clears bearer tokens and marks agents inactive.
- Review automation rules for the organization — disable any rules referencing suspicious scripts.
- Audit the
ShellCo