What Warnings Does witr Generate for Suspicious Process Behavior? Full Detection Guide
witr generates 14 categories of warnings for suspicious process behavior, covering service instability, dangerous process states, resource exhaustion, privilege escalation, network exposure, and tampering indicators.
witr is an open-source process inspection tool that analyzes process ancestry and flags anomalous or high-risk characteristics. Its warning system, implemented in internal/source/detect.go, evaluates runtime signals to surface security-relevant conditions that administrators might otherwise miss.
How witr Detects Suspicious Process Behavior
The core detection logic resides in the Warnings() function at internal/source/detect.go. This function accepts a slice of model.Process structs, a restart count, and a source type, then returns a []string of human-readable warnings.
Each warning corresponds to a specific condition checked against process metadata fields defined in pkg/model/process.go, including Health, Sockets, User, Capabilities, WorkingDir, ContainerHealthcheck, Service, Command, ExeDeleted, and Env.
Service Instability Warnings
Excessive Service Restarts
witr flags services that have restarted more than 5 times. This indicates potential crash loops, resource contention, or unstable deployments.
- Warning:
Service has restarted <n> times - Location:
detect.golines 60-61
// Example: Triggering the restart warning
warnings := source.Warnings(ancestry, 7) // 7 restarts
// Output includes: "Service has restarted 7 times"
Missing Service Supervisor
On non-Windows systems, witr warns when no recognized service manager (systemd, upstart, sysvinit, launchd, etc.) supervises the process. This suggests ad-hoc execution or potential persistence mechanisms.
- Warning:
No known supervisor or service manager detected - Location:
detect.golines 99-105
Service/Binary Name Mismatch
When the declared service name differs from the actual process executable name, witr raises a correlation warning. This can indicate masquerading or misconfigured services.
- Warning:
Service name and process name do not match - Location:
detect.golines 124-140
Process State Warnings
Zombie Processes
Defunct processes that have terminated but remain in the process table consume PID space and may indicate parent process bugs or resource leaks.
- Warning:
Process is a zombie (defunct) - Location:
detect.golines 65-67
Stopped Processes
Processes in the stopped state (T state) are suspended, often via SIGSTOP, which can indicate debugging activity or manipulation attempts.
- Warning:
Process is stopped (T state) - Location:
detect.golines 68-70
Resource Exhaustion Warnings
High CPU Utilization
witr warns when a process has accumulated more than 2 hours of total CPU time, flagging potentially runaway computation or cryptomining activity.
- Warning:
Process is using high CPU (>2h total) - Location:
detect.golines 70-72
High Memory Consumption
RSS (Resident Set Size) exceeding 1 GB triggers a memory warning, helping identify memory leaks or unexpectedly resource-intensive processes.
- Warning:
Process is using high memory (>1GB RSS) - Location:
detect.golines 72-74
Extended Uptime
Processes running longer than 90 days may indicate neglected services, missed security patches, or stale deployments.
- Warning:
Process has been running for over 90 days - Location:
detect.golines 107-112
Privilege and Security Warnings
Root Execution
witr explicitly warns when processes run as root, highlighting increased blast radius from potential compromises.
- Warning:
Process is running as root - Location:
detect.golines 79-81
Dangerous Capabilities
Linux capabilities beyond standard sets (CAP_SYS_ADMIN, CAP_NET_RAW, etc.) are flagged with the specific capability list attached.
- Warning:
Process has dangerous capabilities: <list> - Location:
detect.golines 82-90
Network Exposure Warnings
Public Interface Binding
Processes listening on public network interfaces (0.0.0.0, ::, or external IPs) rather than localhost receive network exposure warnings.
- Warning:
Process is listening on a public interface - Location:
detect.golines 75-77
Execution Environment Warnings
Suspicious Working Directory
witr checks if the working directory is /, /tmp, or /var/tmp—common staging directories for exploits and temporary payloads.
- Warning:
Process is running from a suspicious working directory: <dir> - Location:
detect.golines 114-117
Deleted Binary Execution
When /proc/<pid>/exe points to a deleted file (indicated by (deleted) suffix), witr warns of potential library injection or in-flight updates without replacement.
- Warning:
Process is running from a deleted binary (potential library injection or pending update) - Location:
detect.golines 142-145
Missing Container Healthcheck
Container environments without configured healthchecks receive operational warnings, as this limits runtime visibility into service health.
- Warning:
Container has no healthcheck configured - Location:
detect.golines 119-122
Dynamic Library Injection Warnings
The envSuspiciousWarnings() helper (lines 38-50 and 93-45 in detect.go) inspects environment variables for injection vectors:
| Variable Pattern | Warning |
|---|---|
LD_PRELOAD |
Process sets LD_PRELOAD (potential library injection) |
DYLD_* |
Process sets DYLD_* variables (potential library injection): <keys> |
These checks target Unix preload mechanisms and macOS dynamic link editor variables used in supply chain attacks and runtime tampering.
// Environment warning inspection
envWarns := source.Warnings([]model.Process{proc}, 0)
for _, w := range envWarns {
if strings.Contains(w, "LD_PRELOAD") || strings.Contains(w, "DYLD") {
// Handle injection indicator
}
}
Using witr Warnings Programmatically
The Warnings() function signature in internal/source/detect.go:
func Warnings(p []model.Process, restartCount int, srcType model.SourceType) []string
Parameters:
p: Ancestry slice from oldest parent to target processrestartCount: Service manager restart countersrcType: Enum indicating detection source (systemd, docker, etc.)
Return: Ordered slice of warning strings; empty if no conditions match.
Test Coverage and Verification
Unit tests in internal/source/warnings_test.go validate each warning condition against controlled model.Process inputs. Output formatting for CLI display is handled by internal/output/standard.go.
Summary
witr's warning system provides comprehensive coverage of suspicious process behavior:
- Service health: Restart storms, missing supervisors, name mismatches
- Process states: Zombies, stopped processes, extreme uptime
- Resource abuse: CPU >2h, memory >1GB RSS
- Privilege risks: Root execution, dangerous capabilities
- Network exposure: Public interface binding
- Execution anomalies: Suspicious working directories, deleted binaries
- Container gaps: Missing healthchecks
- Injection vectors: LD_PRELOAD and DYLD environment variables
All warnings source from internal/source/detect.go and operate on the model.Process struct defined in pkg/model/process.go.
Frequently Asked Questions
How does witr detect deleted binary execution?
witr examines the ExeDeleted boolean field in the model.Process struct, populated by checking if /proc/<pid>/exe resolves to a path marked (deleted). This addresses attacks where malware executes from unlinked files to evade disk forensics.
Can witr warnings be customized or suppressed?
The current implementation in detect.go uses fixed thresholds (5 restarts, 2h CPU, 1GB memory, 90 days uptime). Customization requires modifying source constants; runtime configuration is not yet exposed. The []string return format allows downstream filtering by consumers.
What triggers the DYLD warning specifically?
Any environment variable starting with DYLD_ (macOS dynamic linker prefixes) triggers the warning, including DYLD_INSERT_LIBRARIES, DYLD_LIBRARY_PATH, and DYLD_FRAMEWORK_PATH. The warning lists all matching keys found in the process environment.
Does witr run on Windows?
Most warnings apply to Linux and Unix-like systems. The "no known supervisor" warning explicitly excludes Windows (srcType != model.SourceWindows), as Windows service detection follows different patterns not covered by the current warning set.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →