> ## Documentation Index
> Fetch the complete documentation index at: https://filetrace.eorlov.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Detect sensitive files leaving a host

> Find whether files under a sensitive directory were sent off the machine, to which addresses and by which process, using filters, confidence levels, alerts and OTLP records.

**The question:** did any file under `/data/sensitive` leave this machine, and if so, who sent it and to where?

Filetrace is built for exactly this. A file is named at the moment its bytes reach a socket, so the answer includes the process, the destination and the method, not just a byte count.

## 1. Ask for the files

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
sudo filetrace files --path '/data/sensitive/*' --since 24h --sort bytes
```

`--path` matches the whole path, and `*` crosses `/`, so this covers the subdirectories too. The result is most-recently-active first; `--sort bytes` puts the largest first.

```text theme={"theme":{"light":"github-light","dark":"github-dark"}}
FILE                              PROCESS  DESTINATION    BYTES   METHOD      CONFIDENCE  SCRIPT
/data/sensitive/payroll-2026.xlsx python3  203.0.113.25   4.20 MB  read-write  INFERRED    /srv/etl/export.py
/data/sensitive/keys.pem          curl     198.51.100.7   1.65 KB  sendfile    EXACT       -
```

Read the rows:

* The **first** line is a Python process that read a spreadsheet and then sent it: `INFERRED`, with the script that did it. That is the shape of an application upload.
* The **second** line is `sendfile` and `EXACT`: the kernel handed the file to the socket directly. A command-line tool sent a private key.

## 2. Narrow with the filters that matter

| Filter | What it removes |
| - | - |
| `--user www-data` | Everything not owned by the service account |
| `--script '/srv/etl/*'` | Everything not run by the expected pipeline |
| `--remote 203.0.113.0/24` | Everything not going to a known network |
| `--min-size 1MB` | Small reads that are not the concern |
| `--deleted` | Only files that no longer have a directory entry, a common sign of a staged exfiltration |
| `--confidence exact` | Only transfers the kernel made itself |

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
# Only exact, kernel-performed sends of sensitive files
sudo filetrace files --path '/data/sensitive/*' --confidence exact --min-size 1MB
```

> [!NOTE]
>
> `--remote` selects a network to include; there is no negation. To find traffic *outside* a known network, list the transfers with `--remote` omitted and compare the DESTINATION column against the allow-list, or keep an alert on the file-egress rate in the metrics layer (below).

## 3. Follow a hit with `inspect`

When one file matters, ask about the file itself:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
sudo filetrace inspect file /data/sensitive/keys.pem
```

The report shows every process that sent it, every address it went to, the totals, the methods, and the confidence of each association. From a process, `inspect process <pid>` shows everything that process is sending now. From an address, `inspect ip 203.0.113.25 --since 24h` shows which processes talk to it and which files were sent there.

## 4. Watch for new sends

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
sudo filetrace watch --min-bytes 1MB --sort bytes
```

`watch` ranks transfers by current rate, so a large upload stands out while it is happening. Add `--file '/data/sensitive/*'` to see only the files you care about, or `--direction outbound` on a busy server.

## 5. Alert on it

The [observability recipes](https://filetrace.eorlov.org/integrations/observability-recipes.md) include ready-to-use rules. The two that fit here:

* **`FiletraceLargeFileTransfer`** fires when one process sends more than 1 GB in five minutes.
* **`FiletraceUnattributedEgress`** fires when most egress has no file behind it, which is worth checking when uploads are the concern.

```promql theme={"theme":{"light":"github-light","dark":"github-dark"}}
# File bytes sent per second, by process and confidence
sum by (process_executable_name, filetrace_transfer_confidence) (
  rate(filetrace_file_sent_bytes_total[5m])
)
```

## 6. Keep the record

For an audit trail that outlives the agent, export the `file_transfer` log records to a collector. Each record carries the path, the process, the script, the peer address and the bytes:

```toml theme={"theme":{"light":"github-light","dark":"github-dark"}}
[otlp]
enabled = true
endpoint = "127.0.0.1:4317"
events = ["file_transfer", "event_loss"]
file_paths = true
```

If the backend must not hold paths, set `file_paths = false`; the record keeps the device and inode, which still identify the file for an investigator with access to the host.

## Where the answer can mislead

* **`INFERRED` is not proof.** A thread read the file and then sent bytes on a socket; the bytes cannot be proven to come only from that file. Treat it as strong evidence and corroborate with the script and the destination.
* **Bytes counted are what the local socket accepted**, not what the remote end acknowledged. A send that fails mid-way still shows the bytes the kernel accepted.
* **Loss hides transfers.** Check `filetrace_events_dropped_total` and the `*` marker. With loss, a file can be missing from the list entirely.
* **History is in memory.** After an agent restart, past transfers are gone. Use OTLP or the metrics for anything that must persist.
* **Encrypted or generated payloads** read from memory have no file behind them and appear in `transfers` as `UNKNOWN`, not in `files`. Look at `filetrace transfers --include-unknown` too.

## Related pages

* [Transfers, including unattributed bytes](https://filetrace.eorlov.org/cli/transfers.md)
* [File attribution and confidence](https://filetrace.eorlov.org/concepts/attribution.md)
* [Observability recipes](https://filetrace.eorlov.org/integrations/observability-recipes.md)
* [Keep an audit trail](https://filetrace.eorlov.org/use-cases/compliance.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.