Go to file
2026-07-23 07:24:47 +02:00
cadline chore(submodules): bump backend submodules to 2026-07-17 state 2026-07-21 18:49:51 +02:00
core chore: renormalize stored line endings to LF per .gitattributes 2026-07-21 18:46:11 +02:00
deployed fix(baseline): catch .htaccess php-enable persistence in safety-net 2026-07-22 07:52:52 +02:00
lib build(baseline): add lib/jmap.py Joomla manifest-mapper + tests 2026-07-16 11:27:45 +02:00
overrides chore: renormalize stored line endings to LF per .gitattributes 2026-07-21 18:46:11 +02:00
packages chore: renormalize stored line endings to LF per .gitattributes 2026-07-21 18:46:11 +02:00
tests build(baseline): add lib/jmap.py Joomla manifest-mapper + tests 2026-07-16 11:27:45 +02:00
.gitattributes Add .gitattributes: force LF line-endings for deterministic baseline 2026-07-19 18:37:41 +02:00
.gitignore build(baseline): constituents+generator skeleton 2026-07-16 09:40:46 +02:00
.gitmodules chore(submodules): bump backend submodules to 2026-07-17 state 2026-07-21 18:38:59 +02:00
AGENTS.md docs: document the repo as a multi-site baseline generator 2026-07-17 12:52:40 +02:00
build-baseline.sh fix(baseline): catch .htaccess php-enable persistence in safety-net 2026-07-22 07:52:52 +02:00
malware-iocs.md docs: remove operator-internal (git.illusion.hu) references 2026-07-16 12:14:05 +02:00
malware-iocs.paths fix(baseline): catch .htaccess php-enable persistence in safety-net 2026-07-22 07:52:52 +02:00
PROVENANCE.md build(baseline): constituents+generator skeleton 2026-07-16 09:40:46 +02:00
README.md docs: document the repo as a multi-site baseline generator 2026-07-17 12:52:40 +02:00
RUNBOOK.md docs: remove operator-internal (git.illusion.hu) references 2026-07-16 12:14:05 +02:00

Cadline web baselines — constituents + generator

This repo produces the clean code baselines of the Cadline web sites hosted on tanis.cadline.hu — malware-free, faithful reproductions of what each site's source should be, assembled from clean sources rather than copied from the live server.

A baseline has two jobs:

  1. Known-good reference. The HIDS baseline-diff compares the live docroot against it and classifies every file (baseline-match / data / malware / residual).
  2. Deployment source of truth. The baseline is what gets deployed to the server, so that code reaches production through git instead of being edited directly on the live host. Because the live tree is regenerated from the baseline, cleanup becomes a by-product of deployment: anything not in the source disappears.

The repo stores the baseline constituents plus a generator — never the deployed tree.


Sites and branches

There is no separate repo per site. Sites (and CMS versions) live on branches:

Branch Site CMS core Own code source
main www.archline.hu Joomla 3.8.11 reconstructed here (no usable developer source)
site/archlinexp.eu www.archlinexp.eu Joomla 3.9.2 cadline/websourcewww.archlinexp.eu/

build-baseline.sh is site-agnostic — it walks the constituent directories and has no site-specific logic. A new site is a new branch with different content, not a new script and not a new repo. Site branches are parallel and long-lived; they do not merge into main. Only repo-wide files (this README, AGENTS.md, the generator, lib/) live on main for every branch to inherit.

Automated agents: read AGENTS.md first — it carries the rules (verification, repo boundary, layer semantics) in machine-facing form.


Building a baseline (read this first)

# 1. Clone, and check out the branch of the site you want:
git clone --recurse-submodules ssh://git@git.cadline.hu:22222/cadline_web/www_archline_hu.git
cd www_archline_hu
git checkout site/archlinexp.eu       # or stay on main for www.archline.hu
#    (if you cloned without --recurse-submodules and the branch uses submodules:)
git submodule update --init

# 2. Generate:
./build-baseline.sh                   # → ./out/

# 3. Use ./out/ as that site's known-good reference / deploy source.

out/ is the deployed code docroot. It is git-ignored and fully regenerated on every run (the script rm -rf out/ first, so it is idempotent).

Prerequisites: bash, rsync, git, find, sed. No PHP, no build toolchain, no network at build time. lib/jmap.py (python3) is an authoring aid used when preparing a package's pristine commit — build-baseline.sh never invokes it.

What out/ contains / excludes:

  • Contains: the CMS core + every installed extension + the Cadline-own code, as deployed files.
  • Excludes: malware and known planted paths (malware-iocs.paths), and runtime data (cache/, tmp/, logs/, images/, public/, media). The result is code only — which is also why a deploy must never wipe the data directories.

Verify before you trust it

The build output is not trusted until checked. This is not ceremony: the first archline baseline candidate contained 34 malware files, and only the check caught them; on the eu site the check caught a file-write webshell and a leftover Akeeba restoration file that carried a password — neither of which YARA flagged. See AGENTS.md §4 for the full checklist (YARA, IOC paths, disguise sweep, the structural core-namespace rule, core version).


Repo layout (the constituents)

Path What How build-baseline.sh uses it
core/ CMS official package (deployed form, installer removed) rsync → out/, minus demo assets + data dirs
packages/<slug>/ extensions with an obtainable upstream, deployed-layout. Modified ones are authored as two commits (pristine upstream → our delta) so git log/git diff shows exactly how we differ. rsync → out/
deployed/<slug>/ extensions with no obtainable upstream: vetted live files, deployed layout. rsync → out/
cadline/<slug>/ Cadline own-code. On main this includes git submodules of the developer repos (cadcommonlib / maintenance). rsync → out/ (.git excluded)
overrides/ the site's modifications to core files, on the current core's base. Rsynced last, so it wins. rsync → out/
malware-iocs.paths machine-readable exclusion list (droppers, leftovers) build step 6
lib/jmap.py Joomla manifest→deployed-path mapper (authoring aid only) not used at build time

Details: RUNBOOK.md (recipe + module inventory), PROVENANCE.md (per-extension origins), malware-iocs.md (the excluded IOC set, main).


Why customized core files never come from live

A CMS updater skips files the site has customized. The version string moves forward; the customized files silently stay on the old base. The eu site demonstrated this: it reported Joomla 3.9.2 while its com_users was still pre-3.8.13 code — 31 stale files.

So: take vanilla for the version you target, then apply only the genuine delta into overrides/. Never lift the customized file from live — that would preserve the stale (and possibly vulnerable) base forever.


This branch: www.archline.hu (main)

Joomla 3.8.11, host tanis.cadline.hu. out/ ≈ 23.5k files. It byte-matches the live docroot for all legit code and 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.

The own-code here is reconstructed in this repo, because the developer source (cadline/websource) does not contain this site — its sub.archline.hu directory is an older snapshot missing ~630 files and the third-party module layer entirely.

Updating

  • Developer-controlled code (common_cadline_libraries, maintenance): the developer pushes to the cadcommonlib / maintenance repos, then:
    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 (EOL core, 3rd-party extensions): effectively frozen. If a legit change lands, re-sync the affected deployed/<slug>/ or overrides/ and commit.

Known divergence (heads-up for the verifier): common_cadline_libraries and maintenance 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 flags this until live is re-deployed or the drift is reconciled.

This branch: www.archlinexp.eu (site/archlinexp.eu)

Joomla 3.9.2. out/ ≈ 12.3k files. Built from clean sources end to end: vanilla 3.9.2 core + the developer source's own code + a vetted module layer, with only 5 genuine core modifications in overrides/. The developer source for this site is complete and clean (its com_users is already on the 3.9.2 base), which is why this site — not archline.hu — was the first to get a fully source-built baseline.


Authority

  • The upstream vendor package is authoritative for the CMS core.
  • The developer source repo is authoritative for the code it owns.
  • The live docroot (read-only mirror) is authoritative only for reproduction fidelity and for extensions that have no obtainable upstream — and even then the files are vetted, never trusted.
  • The earlier single-commit "monolith" baseline is an unvalidated helper only (it dropped extension manifests and clean core files and kept installer junk) — not a target.