# How witr Detects LD_PRELOAD by Inspecting Process Environment Variables

> Learn how witr detects LD_PRELOAD by inspecting process environment variables. Discover its detection rules and matching process in this technical deep dive.

- Repository: [Pranshu Parmar/witr](https://github.com/pranshuparmar/witr)
- Tags: internals
- Published: 2026-08-09

---

**witr detects LD_PRELOAD by iterating through detection rules defined in [`internal/source/detect.go`](https://github.com/pranshuparmar/witr/blob/main/internal/source/detect.go) and matching them against the environment variables of each discovered process.**

The open-source process inspector witr scans running processes for suspicious environment variables that indicate potential library injection attacks. By analyzing the `Env` slice populated from `/proc/<pid>/environ` on Linux, witr identifies when processes set `LD_PRELOAD` or similar dynamic linker variables. This detection mechanism helps security operators spot potential code injection attempts in real-time.

## Detection Rules in internal/source/detect.go

The core detection logic resides in [`internal/source/detect.go`](https://github.com/pranshuparmar/witr/blob/main/internal/source/detect.go), where a slice of rules maps environment variable patterns to warning messages. At line 40, the tool defines a specific rule for `LD_PRELOAD` that triggers when a process environment contains this variable.

### Pattern Definition for LD_PRELOAD

The detection rule structure contains a **pattern** string and a **warning** message. For `LD_PRELOAD`, the rule appears as:

```go
{ pattern: "LD_PRELOAD", warning: "Process sets LD_PRELOAD (potential library injection)" },

```

Similar rules exist for macOS-specific variables like `DYLD_INSERT_LIBRARIES` and `DYLD_LIBRARY_PATH`, as well as `LD_LIBRARY_PATH` for Linux systems.

### Matching Algorithm

The evaluation logic iterates over both the detection rules and the process environment slice. For each environment variable entry, witr checks whether the string starts with the rule's pattern followed by an equals sign (`=`), or matches the pattern exactly. When a match occurs, the associated warning string appends to the process findings.

## Capturing Process Environment Data

Before detection occurs, witr must collect environment variables from each running process. The platform-specific implementations in `internal/proc/process_*.go` handle this collection.

On Linux systems, [`internal/proc/process_linux.go`](https://github.com/pranshuparmar/witr/blob/main/internal/proc/process_linux.go) reads the `/proc/<pid>/environ` pseudo-file for each discovered PID. This file contains null-delimited environment variable strings, which the parser converts into the `Env []string` field of the `model.Process` struct defined in [`model/process.go`](https://github.com/pranshuparmar/witr/blob/main/model/process.go).

## Implementation Walkthrough

The following simplified example demonstrates how witr evaluates environment variables against detection rules:

```go
// Simplified detection logic from internal/source/detect.go
procEnv := []string{
    "PATH=/usr/bin",
    "LD_PRELOAD=/tmp/malicious.so",
    "HOME=/home/user",
}

warnings := []string{}
for _, rule := range detectRules {
    for _, env := range procEnv {
        if strings.HasPrefix(env, rule.pattern+"=") || env == rule.pattern {
            warnings = append(warnings, rule.warning)
        }
    }
}
// Result: warnings contains "Process sets LD_PRELOAD (potential library injection)"

```

When executed through the main entry point at [`cmd/witr/main.go`](https://github.com/pranshuparmar/witr/blob/main/cmd/witr/main.go), this logic surfaces warnings in the CLI output, displaying lines such as:

```

Process 1234 (myapp) – Process sets LD_PRELOAD (potential library injection)

```

## Validating Detection with Unit Tests

The detection behavior is verified in [`internal/source/detect_test.go`](https://github.com/pranshuparmar/witr/blob/main/internal/source/detect_test.go), which contains test cases ensuring that processes with `LD_PRELOAD` set generate the appropriate warnings while clean processes produce none. These tests validate both the presence and absence scenarios, confirming that the pattern matching correctly identifies injection attempts without false positives on legitimate environment variables.

## Summary

- witr defines detection patterns in [`internal/source/detect.go`](https://github.com/pranshuparmar/witr/blob/main/internal/source/detect.go) including specific rules for `LD_PRELOAD` at line 40
- Platform-specific collectors in `internal/proc/process_*.go` populate the `Env` field by reading `/proc/<pid>/environ` on Linux
- The matching algorithm checks if environment variables start with the pattern followed by `=` or match exactly
- Detected violations surface as warning strings in the process listing output
- Unit tests in [`internal/source/detect_test.go`](https://github.com/pranshuparmar/witr/blob/main/internal/source/detect_test.go) validate the detection accuracy

## Frequently Asked Questions

### What file contains the LD_PRELOAD detection rules in witr?

The detection rules reside in [`internal/source/detect.go`](https://github.com/pranshuparmar/witr/blob/main/internal/source/detect.go), where line 40 specifically defines the `LD_PRELOAD` pattern with its associated warning message for potential library injection.

### How does witr access environment variables from running processes?

On Linux, witr reads the `/proc/<pid>/environ` pseudo-file through the platform-specific implementation in [`internal/proc/process_linux.go`](https://github.com/pranshuparmar/witr/blob/main/internal/proc/process_linux.go), parsing the null-delimited contents into the `Env []string` field of the `model.Process` struct.

### Does witr detect other library injection methods besides LD_PRELOAD?

Yes, the detection rules also include patterns for `DYLD_INSERT_LIBRARIES` and `DYLD_LIBRARY_PATH` on macOS, as well as `LD_LIBRARY_PATH` on Linux, covering multiple dynamic linker injection vectors.

### Where are the detection tests located in the repository?

The unit tests validating the environment variable inspection logic are located in [`internal/source/detect_test.go`](https://github.com/pranshuparmar/witr/blob/main/internal/source/detect_test.go), ensuring that processes setting injection-related variables trigger appropriate warnings.