# Deployment

The tool has no installer. Deployment is a copy, and proof of deployment is a verdict from a host
that answers. This page covers the delivery, the paths involved, and the first run on a host.

## Requirements

| Requirement | Detail |
|---|---|
| Target OS | Debian 12, Ubuntu 24.04, Ubuntu 26.04 |
| Access | `root` over an SSH key, non-interactive (`BatchMode`) |
| Packages on target | `bash` 5.x, `dpkg`, `apt-get`, `systemd` |
| Optional on target | `curl` and `brotli` — they widen the functional round-trip only |
| Local tools | `ssh`, `scp`; a `Host` entry in `~/.ssh/config` per target |
| Network | package mirrors only; the scripts call nothing else |

## Deliver

```bash
scp src/common.sh src/detect.sh src/remediate.sh src/verify.sh <host>:/root/cve-2026-111497/
```

The four files must land in the same directory: `detect.sh`, `remediate.sh` and `verify.sh` source
`common.sh` from their own location, so a partial copy fails on the first run.

Syntax check on the target, not only locally:

```bash
ssh <host> 'cd /root/cve-2026-111497 && bash -n *.sh && echo "syntax OK"'
```

## Paths the tool writes

| Path | Owner | Content | Lifetime |
|---|---|---|---|
| `/var/lib/cve-2026-111497/report.json` | root | machine-readable audit result | overwritten per run |
| `/var/lib/cve-2026-111497/state.before` | root | versions, candidate, three inodes | written by `detect.sh`, read by the other two |
| `/var/lib/cve-2026-111497/state.after` | root | version after install, backup path | written by `remediate.sh` |
| `/root/cve-2026-111497-fix-<timestamp>/` | root | old `.deb`, current `.so`, `dpkg` snapshot | kept; the rollback source |

Override the state directory with `CVE_OUT_DIR` when the host keeps `/var/lib` read-only or on a
separate volume:

```bash
CVE_OUT_DIR=/root/cve-state bash /root/cve-2026-111497/detect.sh
```

The backup path is not configurable on purpose: a rollback has to be findable by a human under
pressure.

## First run

```bash
ssh <host> 'bash /root/cve-2026-111497/detect.sh'; echo "exit=$?"
```

Expected output on a vulnerable host — seven lines, the last one being the verdict:

```text
[2026-10-27T09:14:02+0300] INFO  detector started (read-only)
detect: host=<host> os=Debian GNU/Linux 12 (bookworm)
detect: libbrotli1 installed=1.0.9-2+b6 upstream=1.0.9 vulnerable=1 backported=0
detect: apt candidate=1.0.9-2+deb12u1
detect: consumers(libbrotlidec)=php-fpm8.2:7 apache2:3 zabbix_agentd:1
detect: curl=brotli/1.0.9 node=v22.22.1 py_brotli_pkgs=0 php_brotli_ext=0 nginx_brotli=none apache_brotli=none
detect: php_curlopt_encoding_files=164
report: /var/lib/cve-2026-111497/report.json
VERDICT: VULNERABLE
```

Read the verdict, not the wall: `vulnerable=1` with `backported=0` and a candidate newer than the
installed version is the only combination that justifies remediation.

## Proof of deployment

Deployment is finished when the contract answers on the host:

| Check | Expected |
|---|---|
| `detect.sh` on a patched host | exit `0`, `VERDICT: SAFE` |
| `detect.sh` on a host without `libbrotli1` | exit `3`, `VERDICT: NOT_INSTALLED` |
| `remediate.sh` without a prior `detect.sh` | exit `10`, message naming `state.before` |
| `verify.sh` without a prior `remediate.sh` | exit `10`, message naming `state.after` |

The last two are the important ones: a tool that cannot refuse is a tool that will one day install
on a host nobody audited.

## Removal

```bash
ssh <host> 'rm -rf /root/cve-2026-111497 /var/lib/cve-2026-111497'
```

Keep `/root/cve-2026-111497-fix-*` until the change is closed: it is the only copy of the previous
library state.

Next: [Repository contract](03-Repository-Contract) — what the scripts guarantee.
