Skip to content
22 changes: 22 additions & 0 deletions DeepClean.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ if [ -r "$(dirname "$(readlink -f "${BASH_SOURCE[0]:-$0}")")/lib/color.sh" ]; th
source "$(dirname "$(readlink -f "${BASH_SOURCE[0]:-$0}")")/lib/color.sh"
fi

# Repository transport guard. DeepClean's apt branch runs
# `apt-get autoremove --purge`, which resolves dependency chains and can
# pull packages from a mirror, so HTTPS is enforced before it.
# shellcheck disable=SC1091
if [ -r "$(dirname "$(readlink -f "${BASH_SOURCE[0]:-$0}")")/lib/apt-https.sh" ]; then
source "$(dirname "$(readlink -f "${BASH_SOURCE[0]:-$0}")")/lib/apt-https.sh"
fi

# If lib/color.sh was not sourced or did not set USE_COLOR, run the canonical
# gate inline so _c is safe to call in all execution paths.
if [ -z "${USE_COLOR:-}" ]; then
Expand Down Expand Up @@ -66,6 +74,20 @@ PM=$(pkg_mgr)
USED_BEFORE_KB=$(df -kP / | tail -1 | awk '{print $3}')

msg "Detected package manager: ${PM:-none}"

# Precaution: `apt-get autoremove --purge` below resolves dependencies and
# can fetch from a mirror, so force repository traffic over HTTPS first.
# No-op once per process, and a silent no-op when the lib is unavailable
# (curl|bash of DeepClean.sh on its own).
if declare -F apt_https_guard >/dev/null 2>&1 && [ "$PM" = "apt" ]; then
apt_https_guard "DeepClean" || true
elif [ "$PM" = "apt" ]; then
# Reached when this file is curl|bash'd on its own, with no lib/ next to
# it. Say so rather than silently skipping the precaution.
echo "[!] lib/apt-https.sh not found next to this script; skipping the" >&2
echo "[!] repository transport guard before 'apt-get autoremove --purge'." >&2
fi

msg "Starting DeepClean..."

# 1. Systemd Journal Logs
Expand Down
287 changes: 272 additions & 15 deletions README.md

Large diffs are not rendered by default.

53 changes: 53 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,59 @@ multiple distribution families (Debian, RHEL/Fedora, SUSE, Arch). Always
review what will be applied, keep backups/restoration points, and test
on non-critical systems first.

### Package and app-store transport

Every package download, update, and upgrade is preceded by
`apt_https_guard` (see `lib/apt-https.sh`). The audit spans every app
store on the host, not just the distro package manager:

`apt`, `dnf`, `yum`, `zypper`, `pacman`, `apk`, `flatpak`, `snap`,
`docker`, `brew`, `pip`, `npm`, `cargo`, `gem`, `nix`, `fwupd`.

Detection is format-agnostic: any non-comment line carrying an `http://`
URL in a store's configuration, or a plaintext transport URL exported in
the environment, is reported. Signature verification catches *forged*
packages; only TLS prevents a *downgrade* to an older, genuinely-signed,
vulnerable build.

On apt the guard:

* installs `/etc/apt/apt.conf.d/99neohiro-force-https`, whose
`Acquire::http::AllowRedirect "false"` prevents an `https://` mirror
from silently downgrading a fetch to plaintext HTTP;
* rewrites `http://` repo URLs to `https://` in `sources.list`,
`sources.list.d/*.list`, and DEB822 `*.sources`;
* backs every file up to `/var/backups/neohiro-apt-https/` first and logs
it to `/var/log/linux-install-rollback.log`;
* applies each change by staging in the target's own directory and
`rename(2)`, so an interrupted run cannot leave a truncated repo file;
* runs a verification `apt-get update` and rolls the rewrite back
automatically if a mirror does not serve the same paths over HTTPS.

Other stores are reported rather than rewritten, because whether
`https://<same host><same path>` exists is not knowable offline and
silently breaking a working mirror is worse than the threat. Opt in with
`NEOHIRO_APT_HTTPS_REWRITE=1`.

Escape hatches and audit tooling:

```bash
sudo bash linuxinstall.sh --apt-https-audit # read-only, exit 1 if plaintext remains
sudo bash linuxinstall.sh --apt-https-off # restore backups, remove the drop-in
NEOHIRO_APT_HTTPS=0 # disable the guard for one run
```

The optional `NEOHIRO_APT_BLOCK_PORT80=1` adds `ufw deny out 80/tcp`.
It is off by default because a blanket outbound block also affects
unrelated plaintext protocols, and the guard declines to add it while
any plaintext endpoint is still configured.

Under `curl | sudo bash` the guard is loaded from `lib/apt-https.sh`
(fetched from the same base the script already trusts) rather than
duplicated inline, so there is one implementation to audit. If it cannot
be loaded the script says so and runs with the guard inactive — it never
reports success for a precaution that is not running.

---

Maintained by **[neohiro](https://github.com/neohiro)**.
37 changes: 35 additions & 2 deletions lib/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,45 @@ each file for the API contract.
EXIT trap cleans everything. ERR trap in STRICT_RUN / CI mode logs
the failing command to `NEOHIRO_DEBUG_LOG` (default
`/var/log/neohiro-debug.log`).
- `updater.sh` — the comprehensive cross-distro update engine
(`_run_all_updates` plus one `_update_*` per tool). Sourceable and
runnable standalone (`sudo bash lib/updater.sh`).
- `apt-https.sh` — repository/app-store transport guard. `apt_https_guard`
is called by every package entry point so nothing is ever fetched over
plaintext HTTP. It audits **every** app store, not just apt: `apt`, `dnf`,
`yum`, `zypper`, `pacman`, `apk`, `flatpak`, `snap`, `docker`, `brew`,
`pip`, `npm`, `cargo`, `gem`, `nix`, `fwupd` (see `_apt_https_source_ids`).
Detection is format-agnostic — any non-comment line carrying an `http://`
URL — so a new key in a new distro release cannot silently slip past.
On apt it installs `/etc/apt/apt.conf.d/99neohiro-force-https` (refusing
HTTPS→HTTP downgrade redirects), rewrites `http://` to `https://` across
`sources.list`, `sources.list.d/*.list` and DEB822 `*.sources`, verifies
with a real `apt-get update`, and rolls the rewrite back if a mirror does
not speak TLS. Every write is a same-directory staging file plus
`rename(2)`, so a crash cannot leave a truncated repo file. Other stores
are reported, and rewritten only on `NEOHIRO_APT_HTTPS_REWRITE=1`,
because whether `https://<same host><same path>` exists is not knowable
offline. API: `apt_https_guard`, `apt_https_enforce`, `apt_https_report`,
`apt_https_revert`, `apt_https_status_text`, `apt_https_plaintext_for`;
also runnable standalone. `NEOHIRO_APT_ETC_DIR` / `NEOHIRO_APT_BACKUP_DIR`
relocate the whole tree, so tests never touch the real `/etc`.
- `sync-inline.sh`, `color-gate.sh` — shared inline-fallback sources
consumed by the `curl | bash` path of the top-level scripts.

Top-level scripts (`linuxinstall.sh`, `restore_ssh.sh`,
`DeepClean.sh`, `OptimizeLinuxASR.sh`) source these automatically
when run from a clone. When run via `curl ... | bash`, the lib
directory is not on disk, so each script falls back to inline
definitions of the same helpers.

To regenerate the inline fallbacks, copy the body of each lib file
into the `else` branch in the top-level script.
`apt-https.sh` is the exception: it is never duplicated inline.
`linuxinstall.sh` resolves the canonical file — from disk, or by
fetching it from the same `REPO_RAW_BASE` it already trusts for
`DeepClean.sh` — and sources that, so there is exactly one
implementation. If it cannot be loaded the public entry points become
loud no-ops rather than undefined functions. `tests/test_apt_https.sh`
asserts both properties: the resolver is present, and no library
helper is redefined inline.

To regenerate the inline fallbacks for the other helpers, copy the body
of each lib file into the `else` branch in the top-level script.
Loading
Loading