docs(readme): clear build guide for the HIDS/verifier side

Front-and-center, runnable steps to produce the baseline: clone
--recurse-submodules, run ./build-baseline.sh, use out/ as the vanilla_ref.
Documents prerequisites (no PHP/network; jmap.py is authoring-only), what out/
contains/excludes, the update workflow (submodule update --remote + rebuild),
and the current common_cadline_libraries/maintenance divergence.

Signed-off-by: LÁZÁR Imre <imre@illusion.hu>
Assisted-by: claude-code@claude-opus-4-8
This commit is contained in:
LÁZÁR Imre AI Agent 2026-07-16 13:57:47 +02:00
parent 1801f57702
commit d0d305b6ab

111
README.md
View File

@ -2,42 +2,101 @@
This repo produces the **clean code baseline** of the www.archline.hu docroot
(Cadline, Joomla 3.8.11, host `tanis.cadline.hu`) — the post-compromise, malware-free,
faithful reproduction of the live server's source files. The baseline is the **input**
to the operator's HIDS baseline-diff verifier (per-vhost known-good reference); the
verification itself runs there, not here.
faithful reproduction of the live server's source files.
## Model: constituents + a generator script (not a checked-out tree)
The baseline is the **input** to the HIDS baseline-diff verifier: a per-vhost,
known-good reference tree the verifier compares the live docroot against
(`baseline-match / data / malware / residual`). This repo only *produces* that tree;
the verification runs on the HIDS side.
A deployed Joomla docroot differs from any repo/source layout: extensions install their
files across many docroot paths (`administrator/…`, `components/…`, `media/…`,
`plugins/…`) via their manifest. So this repo stores the baseline **constituents** and a
script **assembles** the deployed baseline:
---
```
./build-baseline.sh # → out/ = the deployed CODE docroot (the baseline)
## Building the baseline (read this first)
The repo does **not** contain the deployed docroot — it contains the baseline
*constituents* plus a generator script. Run the script to produce the deployed tree:
```sh
# 1. Clone WITH submodules (common_cadline_libraries + maintenance are submodules):
git clone --recurse-submodules ssh://git@git.cadline.hu:22222/cadline_web/www_archline_hu.git
cd www_archline_hu
# (if you already cloned without --recurse-submodules:)
git submodule update --init
# 2. Generate the baseline:
./build-baseline.sh # → ./out/
# 3. Use ./out/ as the per-vhost vanilla_ref (the known-good reference tree).
```
- `core/` — Joomla 3.8.11 official package (deployed form).
- `packages/<slug>/` — upstream-obtainable extensions; the pristine package is
manifest-mapped to deployed paths by `lib/jmap.py`, then our legit delta
(`cadline.patch`) is applied — so git history shows exactly how we differ from upstream.
- `deployed/<slug>/` — no-source extensions: vetted live files, placed directly.
- `cadline/<slug>/` — Cadline own-code (+ submodules for the deployed-layout Cadline repos).
- `overrides/` — Cadline core modifications as patches on vanilla.
- Malware (`malware-iocs.md`) and runtime data are excluded; the result is code only.
`out/` is the deployed **code** docroot (~23.5k files). It is git-ignored and fully
regenerated on every run (the script is idempotent — it `rm -rf out/` first). Point the
verifier's baseline-diff at `out/`, or copy it to wherever the verifier expects the ref.
See [`RUNBOOK.md`](RUNBOOK.md) for the build recipe and module inventory,
[`PROVENANCE.md`](PROVENANCE.md) for per-extension origins, and
[`malware-iocs.md`](malware-iocs.md) for the excluded IOC set.
**Prerequisites:** `bash`, `rsync`, `git` (for submodules), `find`, `sed`. No PHP, no
build toolchain, no network at build time (submodules are already cloned).
`lib/jmap.py` (python3) is a *maintenance* tool used only when authoring a package's
pristine commit — **it is not invoked by `build-baseline.sh`**.
**What `out/` contains / excludes:**
- **Contains:** Joomla 3.8.11 core + every installed extension (110 components, ~98
modules, 164 plugins, 8 templates) + the Cadline-own code — all as deployed files.
- **Excludes:** malware/IOCs (see [`malware-iocs.md`](malware-iocs.md)) and runtime
**data** (`cache/`, `tmp/`, `logs/`, `images/`, `public/`, media data). The result is
code only.
- Byte-matches the live docroot for all legit code; it is intentionally **clean** on the
4 files the attacker infected (3 trojanized core files + `shaper_helix3/index.php`),
so the verifier flags those on the live server. Verified: non-malware code residual = 0.
---
## Repo layout (the constituents)
| Path | What | How `build-baseline.sh` uses it |
|---|---|---|
| `core/` | Joomla 3.8.11 official package (deployed form) | rsync → `out/`, minus demo assets + data dirs |
| `packages/<slug>/` | 5 upstream-obtainable extensions, deployed-layout, reconciled to live bytes. Modified ones are two commits (pristine upstream → live delta) so `git log`/`git diff` shows exactly how we differ from upstream. | rsync → `out/` |
| `deployed/<slug>/` | ~55 no-source extensions: vetted live files (deployed layout). `_shared/` holds cross-extension language/vendor/manifests. | rsync → `out/` |
| `cadline/<slug>/` | Cadline own-code. `cadline/backend/common_cadline_libraries` and `…/maintenance` are **git submodules** of the developer repos (cadcommonlib / maintenance). | rsync → `out/` (`.git` excluded) |
| `overrides/` | Cadline core modifications (live versions overlaid on the package core) + a few package-missing core files. | rsync → `out/` (last, so it wins) |
| `lib/jmap.py` | Generic Joomla manifest→deployed-path mapper (authoring aid only). | not used at build time |
Details: [`RUNBOOK.md`](RUNBOOK.md) (recipe + module inventory),
[`PROVENANCE.md`](PROVENANCE.md) (per-extension origins),
[`malware-iocs.md`](malware-iocs.md) (excluded IOC set).
---
## Updating the baseline
- **Developer-controlled code** (`common_cadline_libraries`, `maintenance`): the
developer pushes to the cadcommonlib / maintenance repos, then:
```sh
git submodule update --remote # pull the developer's latest
./build-baseline.sh # regenerate out/
git add -A && git commit # record the new submodule pointers
```
- **Everything else** (Joomla core EOL, 3rd-party extensions): effectively frozen; if a
legit change ever lands, re-sync the affected `deployed/<slug>/` or `overrides/` from
the live docroot and commit.
**Known divergence (heads-up for the verifier):** `common_cadline_libraries` and
`maintenance` currently take the *authoritative* submodule HEAD content, which differs
from the current live docroot (mixed CRLF/LF + a content drift on
`crm_hardlock.class.php` / `POfile.php`) because live was not last deployed from those
HEADs. The verifier will flag this until live is re-deployed from the submodules or the
drift is reconciled. Line-ending normalization, if wanted, is a verifier-side choice.
---
## Authority
The live docroot (RO mirror) is the source of truth — the goal is its faithful,
malware-free reproduction. The earlier single-commit "monolith" baseline is an
unvalidated helper only (it dropped extension manifests and clean core files and kept
installer junk); it is not a target.
The live docroot (RO mirror) is the source of truth for reproduction; the developer git
repos are authoritative for the code they own. The earlier single-commit "monolith"
baseline is an unvalidated helper only (it dropped extension manifests and clean core
files and kept installer junk) — it is not a target.
## References
- The archline.hu 2026 security audit and incident analysis (operator-held).
- The baseline is consumed by the operator's per-vhost HIDS baseline-diff verifier.
- The excluded malware set is documented in [`malware-iocs.md`](malware-iocs.md).