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

# Checks

> Runtime checks that evaluate what your workflow actually did — like unit tests for execution behavior.

Every monitored run is evaluated against a suite of **runtime checks**. Think of them like unit tests, but for execution behavior: each check defines an invariant that should hold for a healthy run. Expected behavior passes silently; a violation fails the check with exact evidence — the process, domain, ancestry chain, and timestamp.

Results appear in the [Run Profile](/run-profile) on your PR, the Run Profile summary, the [Garnet dashboard](https://app.garnet.ai), and any configured [webhooks](/reference/github-actions#outputs--integrations). A single failed check makes the Run Profile read as **Needs review**.

The layering is: a **detection signal** (a low-level Jibril event) composes into a **runtime check** (pass/fail), and the checks together set the [Run Profile state](/run-profile#the-state-ladder) shown on the PR.

***

## How checks work

<Steps>
  <Step title="Profile" icon="eye">
    [Jibril](/trust) profiles every process spawn, network connection, and file access during the workflow run via eBPF.
  </Step>

  <Step title="Evaluate" icon="list-check">
    The control plane evaluates the resulting Run Profile against each enabled check.
  </Step>

  <Step title="Result" icon="circle-check">
    Each check returns **pass** or **fail** with structured evidence — observed behavior for the reviewer, not a gate. Results are published to the Run Profile summary, the [Run Profile](/run-profile) comment, dashboard, and alerts.
  </Step>
</Steps>

<Note>
  The `no_*` checks shipping today are **Garnet-managed**. User-authored assertions — your own expected-egress or protected-path invariants — are on the roadmap, not configurable yet.
</Note>

***

## Current checks

### Known bad egress

|               |                                                                                                      |
| :------------ | :--------------------------------------------------------------------------------------------------- |
| **ID**        | `no_known_bad_egress`                                                                                |
| **Category**  | Network                                                                                              |
| **Invariant** | No contacted domain appears on Garnet's known-bad list.                                              |
| **Pass**      | No contacted domain matched the known-bad list.                                                      |
| **Fail**      | A contacted domain matched Garnet's known-bad list — the kind seen in past supply-chain compromises. |
| **Evidence**  | Domain, remote IP, protocol, full process ancestry chain.                                            |

This is the foundational check. In each of these supply-chain compromises — the [Trivy TeamPCP incident](https://www.garnet.ai/resources/garnet-saw-trivy-teampcp), the [Checkmarx KICS compromise](https://www.garnet.ai/resources/garnet-saw-checkmarx-kics), and the [Shai-Hulud npm campaign](https://www.garnet.ai/resources/garnet-saw-shai-hulud) — the Run Profile showed an outbound connection the diff never revealed, so the review came back **needs review** before merge.

**Example: what a needs-review check shows**

```
Check                          Result
─────────────────────────────  ──────────────
Known bad egress               FAIL

Evidence:
  Domain:    scan.aquasecurtiy[.]org
  Process:   curl
  Ancestry:  systemd → bash → entrypoint.sh → curl
  Protocol:  TCP
```

***

### Code injection via /proc memory

|               |                                                                              |
| :------------ | :--------------------------------------------------------------------------- |
| **ID**        | `no_code_injection_via_proc_memory`                                          |
| **Category**  | Defense evasion · Credential access                                          |
| **Invariant** | No process reads or modifies another process's memory via `/proc/<pid>/mem`. |
| **Pass**      | No process initiated code injection via `/proc/<pid>/mem` access.            |
| **Fail**      | A process read or modified another process's memory via `/proc/<pid>/mem`.   |
| **Evidence**  | Target PID, accessor process, full ancestry chain, accessed path.            |

Reading another process's memory via `/proc/<pid>/mem` is how CI runner secrets get scraped from memory, then encoded and sent out. It's invisible to static analysis and workflow logs — only the runtime lineage shows the access, which is exactly what the reviewer needs to see.

**Detection signals:**

* `code_modification_through_procfs` — process memory modified via procfs
* `environ_read_from_procfs` — environment variables read via `/proc/<pid>/environ`

**Real-world example — TanStack compromise (May 2026):**

The [TanStack supply-chain compromise](https://socket.dev/blog/tanstack-npm-packages-compromised-mini-shai-hulud-supply-chain-attack) injected obfuscated code into 84 `@tanstack/*` npm packages via a compromised CI release pipeline. When consumed in CI, `router_init.js` spawned a daemonized child process that read runner secrets from `/proc/<pid>/mem` — the same `/proc` technique seen in the TeamPCP and tj-actions incidents. The read is invisible in workflow logs, but the Run Profile captures it in the process lineage, so the reviewer sees it:

```
systemd
 └─ Runner.Worker
     └─ bash
         └─ node (npm install)
             └─ sh -c node router_init.js
                 └─ node router_init.js
                     └─ node (daemonized, detached stdio)
                         └─ cat /proc/<runner_worker_pid>/mem
```

The install completed normally. The `/proc` memory scrape ran in a detached child of the same tree. Only the runtime lineage shows both.

***

### Binary execution and deletion

|               |                                                                         |
| :------------ | :---------------------------------------------------------------------- |
| **ID**        | `no_binary_execution_and_deletion`                                      |
| **Category**  | Execution · Defense evasion                                             |
| **Invariant** | No process executes a binary and then deletes it from disk.             |
| **Pass**      | No program was executed and then deleted.                               |
| **Fail**      | A program was executed, and then its file was deleted.                  |
| **Evidence**  | Binary path, executor process, deletion timestamp, full ancestry chain. |

Drop-and-delete is a common evasion pattern: a binary is downloaded, run, then removed to avoid leaving a trace. The Run Profile records both the execution and the deletion in the eBPF trace, so neither is lost.

**Detection signals:**

* `binary_self_deletion` — executable deleted itself after running
* `hidden_elf_exec` — execution of a hidden (dot-prefixed) ELF binary
* `exec_from_unusual_dir` — process executed from a non-standard directory (e.g. `/tmp`, `/dev/shm`)

**Example:**

```
Check                          Result
─────────────────────────────  ──────────────
Binary execution and deletion  FAIL

Evidence:
  Binary:    /tmp/.payload
  Executor:  bash
  Ancestry:  systemd → Runner.Worker → bash → /tmp/.payload
  Deleted:   2.3s after execution
```

***

## Upcoming checks

The check suite is expanding. Checks below are in development and will roll out progressively — your runs will start receiving results as each ships, with no workflow changes required.

### Credential file access

|                    |                                                                                                                                                                                                                                                                                |
| :----------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **ID**             | `no_credential_access`                                                                                                                                                                                                                                                         |
| **Category**       | Credential access                                                                                                                                                                                                                                                              |
| **What it checks** | Whether processes accessed files containing stored credentials, SSH keys, SSL certificates, or authentication tokens outside of expected patterns.                                                                                                                             |
| **Detections**     | `credentials_files_access` — process accessed credential files. `ssl_certificate_access` — process accessed SSL/TLS certificate or key files. `passwd_usage` — process accessed the system password file. `auth_logs_tamper` — authentication logs modified (covering tracks). |

### Hidden binary execution

|                    |                                                                                                                                                                                   |
| :----------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **ID**             | `no_hidden_binary_execution`                                                                                                                                                      |
| **Category**       | Execution                                                                                                                                                                         |
| **What it checks** | Whether a hidden or dot-prefixed ELF binary was executed — a common evasion pattern for running tooling that shouldn't be there without appearing in standard directory listings. |
| **Detections**     | `hidden_elf_exec` — execution of a hidden (dot-prefixed) ELF binary. `exec_from_unusual_dir` — process executed from a non-standard directory (e.g. `/tmp`, `/dev/shm`).          |

***

## Detection signals

Checks are built on top of Jibril's detection engine, which identifies individual signals during a run. A single check may combine multiple detection signals into one pass/fail result. Below is the full detection taxonomy, grouped by behavior.

<AccordionGroup>
  <Accordion title="Network peers">
    | Detection                 | What it means                                                          |
    | :------------------------ | :--------------------------------------------------------------------- |
    | `flow`                    | Outbound network flow observed                                         |
    | `dropip` / `dropdomain`   | Connection matched Garnet's known-bad list (domain or IP)              |
    | `threat_domain_access`    | Connection to a domain on Garnet's known-bad list                      |
    | `plaintext_communication` | Sensitive data transmitted over an unencrypted channel                 |
    | `dyndns_domain_access`    | Connection to a dynamic DNS domain (often used to hide infrastructure) |
    | `vpnlike_domain_access`   | Connection to a VPN or proxy service                                   |
  </Accordion>

  <Accordion title="Execution">
    | Detection                   | What it means                                             |
    | :-------------------------- | :-------------------------------------------------------- |
    | `hidden_elf_exec`           | Hidden or dot-prefixed ELF binary executed                |
    | `exec_from_unusual_dir`     | Process executed from `/tmp`, `/dev/shm`, or similar      |
    | `interpreter_shell_spawn`   | Interpreter process launched an interactive shell         |
    | `binary_executed_by_loader` | Binary executed via dynamic loader (indirect execution)   |
    | `code_on_the_fly`           | Dynamic code generation and execution                     |
    | `crypto_miner_execution`    | Process matching known cryptocurrency mining software     |
    | `data_encoder_exec`         | Encoding tool executed (potential exfiltration staging)   |
    | `runc_suspicious_exec`      | Unexpected process execution within the container runtime |
  </Accordion>

  <Accordion title="Defense evasion">
    | Detection                          | What it means                                          |
    | :--------------------------------- | :----------------------------------------------------- |
    | `code_modification_through_procfs` | Process memory modified through the `/proc` filesystem |
    | `environ_read_from_procfs`         | Environment variables read via `/proc/<pid>/environ`   |
    | `binary_self_deletion`             | Executable deleted itself after running                |
  </Accordion>

  <Accordion title="Credential access">
    | Detection                  | What it means                                     |
    | :------------------------- | :------------------------------------------------ |
    | `credentials_files_access` | Process accessed stored credential files          |
    | `ssl_certificate_access`   | Process accessed SSL/TLS certificate or key files |
    | `passwd_usage`             | Process accessed the system password file         |
    | `auth_logs_tamper`         | Authentication logs modified                      |
  </Accordion>

  <Accordion title="Privilege escalation">
    | Detection                   | What it means                                      |
    | :-------------------------- | :------------------------------------------------- |
    | `sudoers_modification`      | Sudoers configuration modified                     |
    | `capabilities_modification` | Linux capabilities modified (privilege escalation) |
  </Accordion>

  <Accordion title="Persistence">
    | Detection                          | What it means                                      |
    | :--------------------------------- | :------------------------------------------------- |
    | `shell_config_modification`        | Shell startup files modified                       |
    | `package_repo_config_modification` | Package manager config altered (untrusted sources) |
    | `pam_config_modification`          | Pluggable authentication module config altered     |
    | `global_shlib_modification`        | Globally shared library modified (code injection)  |
  </Accordion>

  <Accordion title="Network tools">
    | Detection                  | What it means                        |
    | :------------------------- | :----------------------------------- |
    | `net_filecopy_tool_exec`   | File transfer utility executed       |
    | `net_scan_tool_exec`       | Network or port scanner executed     |
    | `net_sniff_tool_exec`      | Packet capture tool executed         |
    | `net_mitm_tool_exec`       | Traffic interception tool executed   |
    | `net_suspicious_tool_exec` | Network reconnaissance tool executed |
  </Accordion>
</AccordionGroup>

Full detection documentation with examples: [jibril.garnet.ai/detections](https://jibril.garnet.ai/detections/)

***

## Using check results

* **On the PR** — the [Run Profile](/run-profile) comment leads with the state and, on a failure, the exact evidence.
* **In the dashboard** — open any run at [app.garnet.ai](https://app.garnet.ai) for per-check results, the full process tree, and the egress summary.
* **In your workflow** — the action outputs `profile_result` (`pass` or `fail`). By default it does **not** fail the job; to gate a merge on it, see [Gate a merge](/reference/github-actions#gate-a-merge-optional).
* **Via Slack / webhooks** — configure under **Settings → Alerting**. See [Outputs & integrations](/reference/github-actions#outputs--integrations).
