5 Commits

Author SHA256 Message Date
ahz 85ff080b40 V9.14.022.2026.06.11: document and test audit safeguards 2026-06-11 05:08:18 +02:00
ahz 9d3f283297 V9.14.022.2026.06.11: enforce secret and cleanup safeguards 2026-06-11 05:08:01 +02:00
ahz 74897d85b1 V9.14.022.2026.06.11: add path security helpers 2026-06-11 05:07:33 +02:00
msw 9ef535554a V9.14.022.2026.06.10
🛡️ Retrieve DNSSEC status of coresecret.dev. / 🛡️ Retrieve DNSSEC status of coresecret.dev. (push) Has been cancelled
🛡️ Shell Script Linting / 🛡️ Shell Script Linting (push) Has been cancelled
💙 Generating a PUBLIC Live ISO. / 💙 Generating a PUBLIC Live ISO. (push) Has been cancelled
🔐 Generating a Private Live ISO TRIXIE. / 🔐 Generating a Private Live ISO TRIXIE. (push) Has been cancelled
Signed-off-by: Marc S. Weidner <msw@coresecret.dev>
2026-06-10 18:57:46 +01:00
msw 800cd175fc V9.14.022.2026.06.10
Signed-off-by: Marc S. Weidner <msw@coresecret.dev>
2026-06-10 17:57:31 +01:00
70 changed files with 2085 additions and 260 deletions
+1 -1
View File
@@ -9,7 +9,7 @@
# SPDX-PackageName: CISS.debian.live.builder # SPDX-PackageName: CISS.debian.live.builder
# SPDX-Security-Contact: security@coresecret.eu # SPDX-Security-Contact: security@coresecret.eu
# Version Master V9.14.020.2026.06.08 # Version Master V9.14.022.2026.06.10
name: 🔐 Generating a Private Live ISO TRIXIE. name: 🔐 Generating a Private Live ISO TRIXIE.
+1 -1
View File
@@ -9,7 +9,7 @@
# SPDX-PackageName: CISS.debian.live.builder # SPDX-PackageName: CISS.debian.live.builder
# SPDX-Security-Contact: security@coresecret.eu # SPDX-Security-Contact: security@coresecret.eu
# Version Master V9.14.020.2026.06.08 # Version Master V9.14.022.2026.06.10
name: 🔐 Generating a Private Live ISO TRIXIE. name: 🔐 Generating a Private Live ISO TRIXIE.
+1 -1
View File
@@ -9,7 +9,7 @@
# SPDX-PackageName: CISS.debian.live.builder # SPDX-PackageName: CISS.debian.live.builder
# SPDX-Security-Contact: security@coresecret.eu # SPDX-Security-Contact: security@coresecret.eu
# Version Master V9.14.020.2026.06.08 # Version Master V9.14.022.2026.06.10
name: 💙 Generating a PUBLIC Live ISO. name: 💙 Generating a PUBLIC Live ISO.
+1 -1
View File
@@ -25,7 +25,7 @@ body:
attributes: attributes:
label: "Version" label: "Version"
description: "Which version are you running? Use `./ciss_live_builder.sh -v`." description: "Which version are you running? Use `./ciss_live_builder.sh -v`."
placeholder: "e.g., Master V9.14.020.2026.06.08" placeholder: "e.g., Master V9.14.022.2026.06.10"
validations: validations:
required: true required: true
+1 -1
View File
@@ -9,7 +9,7 @@
# SPDX-PackageName: CISS.debian.live.builder # SPDX-PackageName: CISS.debian.live.builder
# SPDX-Security-Contact: security@coresecret.eu # SPDX-Security-Contact: security@coresecret.eu
# Version Master V9.14.020.2026.06.08 # Version Master V9.14.022.2026.06.10
FROM debian:bookworm FROM debian:bookworm
+1 -1
View File
@@ -9,7 +9,7 @@
# SPDX-PackageName: CISS.debian.live.builder # SPDX-PackageName: CISS.debian.live.builder
# SPDX-Security-Contact: security@coresecret.eu # SPDX-Security-Contact: security@coresecret.eu
# Version Master V9.14.020.2026.06.08 # Version Master V9.14.022.2026.06.10
name: 🔁 Render README.md to README.html. name: 🔁 Render README.md to README.html.
@@ -11,5 +11,5 @@
build: build:
counter: 1023 counter: 1023
version: V9.14.020.2026.06.08 version: V9.14.022.2026.06.10
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=yaml # vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=yaml
+1 -1
View File
@@ -11,5 +11,5 @@
build: build:
counter: 1023 counter: 1023
version: V9.14.020.2026.06.08 version: V9.14.022.2026.06.10
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=yaml # vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=yaml
+1 -1
View File
@@ -11,5 +11,5 @@
build: build:
counter: 1023 counter: 1023
version: V9.14.020.2026.06.08 version: V9.14.022.2026.06.10
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=yaml # vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=yaml
@@ -9,7 +9,7 @@
# SPDX-PackageName: CISS.debian.live.builder # SPDX-PackageName: CISS.debian.live.builder
# SPDX-Security-Contact: security@coresecret.eu # SPDX-Security-Contact: security@coresecret.eu
# Version Master V9.14.020.2026.06.08 # Version Master V9.14.022.2026.06.10
name: 🔐 Generating a Private Live ISO TRIXIE. name: 🔐 Generating a Private Live ISO TRIXIE.
@@ -9,7 +9,7 @@
# SPDX-PackageName: CISS.debian.live.builder # SPDX-PackageName: CISS.debian.live.builder
# SPDX-Security-Contact: security@coresecret.eu # SPDX-Security-Contact: security@coresecret.eu
# Version Master V9.14.020.2026.06.08 # Version Master V9.14.022.2026.06.10
name: 🔐 Generating a Private Live ISO TRIXIE. name: 🔐 Generating a Private Live ISO TRIXIE.
+1 -1
View File
@@ -9,7 +9,7 @@
# SPDX-PackageName: CISS.debian.live.builder # SPDX-PackageName: CISS.debian.live.builder
# SPDX-Security-Contact: security@coresecret.eu # SPDX-Security-Contact: security@coresecret.eu
# Version Master V9.14.020.2026.06.08 # Version Master V9.14.022.2026.06.10
name: 💙 Generating a PUBLIC Live ISO. name: 💙 Generating a PUBLIC Live ISO.
+1 -1
View File
@@ -9,7 +9,7 @@
# SPDX-PackageName: CISS.debian.live.builder # SPDX-PackageName: CISS.debian.live.builder
# SPDX-Security-Contact: security@coresecret.eu # SPDX-Security-Contact: security@coresecret.eu
# Version Master V9.14.020.2026.06.08 # Version Master V9.14.022.2026.06.10
# Gitea Workflow: Shell-Script Linting # Gitea Workflow: Shell-Script Linting
# #
+1 -1
View File
@@ -9,7 +9,7 @@
# SPDX-PackageName: CISS.debian.live.builder # SPDX-PackageName: CISS.debian.live.builder
# SPDX-Security-Contact: security@coresecret.eu # SPDX-Security-Contact: security@coresecret.eu
# Version Master V9.14.020.2026.06.08 # Version Master V9.14.022.2026.06.10
name: 🛡️ Retrieve DNSSEC status of coresecret.dev. name: 🛡️ Retrieve DNSSEC status of coresecret.dev.
+1 -1
View File
@@ -9,7 +9,7 @@
# SPDX-PackageName: CISS.debian.live.builder # SPDX-PackageName: CISS.debian.live.builder
# SPDX-Security-Contact: security@coresecret.eu # SPDX-Security-Contact: security@coresecret.eu
# Version Master V9.14.020.2026.06.08 # Version Master V9.14.022.2026.06.10
name: 🔁 Render Graphviz Diagrams. name: 🔁 Render Graphviz Diagrams.
+1 -1
View File
@@ -15,5 +15,5 @@ properties_SPDX-License-Identifier="LicenseRef-CNCL-1.1 OR LicenseRef-CCLA-1.1 "
properties_SPDX-LicenseComment="This file is part of the CISS.debian.installer.secure framework." properties_SPDX-LicenseComment="This file is part of the CISS.debian.installer.secure framework."
properties_SPDX-PackageName="CISS.debian.live.builder" properties_SPDX-PackageName="CISS.debian.live.builder"
properties_SPDX-Security-Contact="security@coresecret.eu" properties_SPDX-Security-Contact="security@coresecret.eu"
properties_version="V9.14.020.2026.06.08" properties_version="V9.14.022.2026.06.10"
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=conf # vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=conf
+1 -1
View File
@@ -6,7 +6,7 @@ Creator: Person: Marc S. Weidner (Centurion Intelligence Consulting Agency)
Created: 2025-05-07T12:00:00Z Created: 2025-05-07T12:00:00Z
Package: CISS.debian.live.builder Package: CISS.debian.live.builder
PackageName: CISS.debian.live.builder PackageName: CISS.debian.live.builder
PackageVersion: Master V9.14.020.2026.06.08 PackageVersion: Master V9.14.022.2026.06.10
PackageSupplier: Organization: Centurion Intelligence Consulting Agency PackageSupplier: Organization: Centurion Intelligence Consulting Agency
PackageDownloadLocation: https://git.coresecret.dev/msw/CISS.debian.live.builder PackageDownloadLocation: https://git.coresecret.dev/msw/CISS.debian.live.builder
PackageHomePage: https://git.coresecret.dev/msw/CISS.debian.live.builder PackageHomePage: https://git.coresecret.dev/msw/CISS.debian.live.builder
+43 -20
View File
@@ -2,7 +2,7 @@
gitea: none gitea: none
include_toc: true include_toc: true
--- ---
[![Static Badge](https://badges.coresecret.dev/badge/Release-V9.14.020.2026.06.08-white?style=plastic&logo=linux&logoColor=white&logoSize=auto&label=Release&color=%23FCC624)](https://git.coresecret.dev/msw/CISS.debian.live.builder) [![Static Badge](https://badges.coresecret.dev/badge/Release-V9.14.022.2026.06.10-white?style=plastic&logo=linux&logoColor=white&logoSize=auto&label=Release&color=%23FCC624)](https://git.coresecret.dev/msw/CISS.debian.live.builder)
&nbsp; &nbsp;
[![Static Badge](https://badges.coresecret.dev/badge/Licence-EUPL1.2-white?style=plastic&logo=europeanunion&logoColor=white&logoSize=auto&label=Licence&color=%23003399)](https://eupl.eu/1.2/en/) &nbsp; [![Static Badge](https://badges.coresecret.dev/badge/Licence-EUPL1.2-white?style=plastic&logo=europeanunion&logoColor=white&logoSize=auto&label=Licence&color=%23003399)](https://eupl.eu/1.2/en/) &nbsp;
[![Static Badge](https://badges.coresecret.dev/badge/opensourceinitiative-Compliant-white?style=plastic&logo=opensourceinitiative&logoColor=white&logoSize=auto&label=OSI&color=%233DA639)](https://opensource.org/license/eupl-1-2) &nbsp; [![Static Badge](https://badges.coresecret.dev/badge/opensourceinitiative-Compliant-white?style=plastic&logo=opensourceinitiative&logoColor=white&logoSize=auto&label=OSI&color=%233DA639)](https://opensource.org/license/eupl-1-2) &nbsp;
@@ -27,7 +27,7 @@ include_toc: true
**Centurion Intelligence Consulting Agency Information Security Standard**<br> **Centurion Intelligence Consulting Agency Information Security Standard**<br>
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br> *Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
**Master Version**: 9.14<br> **Master Version**: 9.14<br>
**Build**: V9.14.020.2026.06.08<br> **Build**: V9.14.022.2026.06.10<br>
**CISS.debian.live.builder — First of its own.**<br> **CISS.debian.live.builder — First of its own.**<br>
**World-class CIA: Designed, handcrafted, and powered by Centurion Intelligence Consulting Agency.** **World-class CIA: Designed, handcrafted, and powered by Centurion Intelligence Consulting Agency.**
@@ -60,12 +60,15 @@ and spoofing surfaces.
Internally, the builder employs a dedicated secret-handling pipeline backed by a tmpfs-only secrets directory Internally, the builder employs a dedicated secret-handling pipeline backed by a tmpfs-only secrets directory
(`/dev/shm/cdlb_secrets`). Sensitive material such as root passwords, SSH keys, and signing keys never appears on the command (`/dev/shm/cdlb_secrets`). Sensitive material such as root passwords, SSH keys, and signing keys never appears on the command
line, is guarded by strict `0400 root:root` permissions, and any symlink inside the secret path is treated as a hard failure line, is guarded by a `0700 root:root` secret root and single-link regular `0400` or `0600` root-owned files, and any symlink
that aborts the run. Critical code paths temporarily disable Bash xtrace so that credentials never leak into debug logs, and inside the secret path is treated as a hard failure that aborts the run. Filename-only secret arguments reject slashes and
transient secret files are shredded (`shred -fzu`) as soon as they are no longer needed. GNUPG homes used for signing are traversal.
wiped, unencrypted chroot artifacts and includes are removed after `lb build`, and the final artifact is reduced to the Critical code paths temporarily disable Bash xtrace, and a final exact-value debug-log sanitisation pass provides additional
encrypted SquashFS inside the LUKS2 container. At runtime, LUKS passphrases in the live ISO and installer are transported via defence in depth. Transient secret files are shredded (`shred -fzu`) as soon as they are no longer needed, but this is only a
named pipes inside the initramfs instead of process arguments, further minimizing exposure in process listings. best-effort cleanup on SSD, NVMe, copy-on-write, journaled, and virtualised storage. Use tmpfs for secrets and encrypted storage
for build workspaces. Destructive build cleanup is restricted to the exact canonical directory carrying the
`.ciss-live-builder-owned` marker. This private operator workflow still requires strict local path validation; it does not
define public ISO release policy.
Check out more leading world-class services powered by Centurion Intelligence Consulting Agency: Check out more leading world-class services powered by Centurion Intelligence Consulting Agency:
* [CenturionDNS Resolver](https://eddns.eu/) * [CenturionDNS Resolver](https://eddns.eu/)
@@ -175,7 +178,7 @@ installer toolchain.
This project adheres strictly to a structured versioning scheme following the pattern x.y.z-Date. This project adheres strictly to a structured versioning scheme following the pattern x.y.z-Date.
Example: `V9.14.020.2026.06.08` Example: `V9.14.022.2026.06.10`
`x.y.z` represents major (x), minor (y), and patch (z) version increments. `x.y.z` represents major (x), minor (y), and patch (z) version increments.
@@ -365,6 +368,11 @@ For further details see: **[90-ciss-local.hardened.md](docs/documentation/90-cis
## 2.9. UFW Hardening ## 2.9. UFW Hardening
* **Description**: Defaults to `deny incoming` and (optionally) `deny outgoing`; automatically opens only whitelisted ports. * **Description**: Defaults to `deny incoming` and (optionally) `deny outgoing`; automatically opens only whitelisted ports.
* **Primordial SSH exception**: `--primordial-url <https-git-url>`, `--primordial-key <ssh-identity-filename>` and
`--primordial-ssh <port>` configure the CDI Primordial overlay clone. `--primordial-ssh` also adds an outgoing-only UFW TCP
exception for a bootstrap/recovery SSH port when the live system's UFW outgoing policy is `deny`. It adds no incoming firewall
rule and does not replace `--ssh-port`. If the requested port already matches an existing outgoing SSH exception, the current
hook still emits the requested labelled rule because this repository has no separate UFW rule deduplication layer.
* **Rationale**: Implements a default-deny firewall, reducing lateral movement and data exfiltration risks immediately after * **Rationale**: Implements a default-deny firewall, reducing lateral movement and data exfiltration risks immediately after
deployment. deployment.
@@ -488,10 +496,14 @@ To use **``CISS.debian.live.builder``** as intended, the following baseline is e
2. Preparation: 2. Preparation:
1. Ensure you are root. 1. Ensure you are root.
2. Create the build directory `mkdir /opt/cdlb` and the tmpfs secrets directory `mkdir /dev/shm/cdlb_secrets`. 2. Create the empty build directory with `install -d -m 0700 -o root -g root /opt/cdlb`.
3. Place your desired SSH public key in the `authorized_keys` file, for example, in the `/dev/shm/cdlb_secrets` directory. 3. Create the tmpfs secret root with `install -d -m 0700 -o root -g root /dev/shm/cdlb_secrets`.
4. Place your desired Password in the `password.txt` file, for example, in the `/dev/shm/cdlb_secrets` directory. 4. Place required secret files in the secret root as single-link regular, non-symlink, root-owned files with mode `0400`
5. Make any other changes you need to. or `0600`.
5. Place your desired SSH public key in `/dev/shm/cdlb_secrets/authorized_keys`.
6. Place your desired root password in `/dev/shm/cdlb_secrets/password.txt`.
7. Use filename-only values without slashes, `.` or `..` for `--key_age`, `--key_luks`, and signing-file arguments.
8. Make any other changes you need to.
3. Run the config builder script `./ciss_live_builder.sh` and the integrated `lb build` command (example): 3. Run the config builder script `./ciss_live_builder.sh` and the integrated `lb build` command (example):
@@ -520,6 +532,9 @@ To use **``CISS.debian.live.builder``** as intended, the following baseline is e
--signing_key_pass=signing_key_pass.txt \ --signing_key_pass=signing_key_pass.txt \
--signing_key=signing_key.asc \ --signing_key=signing_key.asc \
--ssh-port 4242 \ --ssh-port 4242 \
--primordial-url https://git.coresecret.dev/ahz/PhysNet.primordial.git \
--primordial-key id--git.coresecret.dev--PhysNet.primordial_deploy--ed25519--newton--2025-10 \
--primordial-ssh 42842 \
--ssh-pubkey /dev/shm/cdlb_secrets \ --ssh-pubkey /dev/shm/cdlb_secrets \
--sshfp \ --sshfp \
--trixie --trixie
@@ -530,6 +545,10 @@ To use **``CISS.debian.live.builder``** as intended, the following baseline is e
both the newer Sigstore bundle asset, and the legacy-split certificate/signature assets before checking the downloaded both the newer Sigstore bundle asset, and the legacy-split certificate/signature assets before checking the downloaded
SOPS binary with `sha256sum -c --ignore-missing`. SOPS binary with `sha256sum -c --ignore-missing`.
On the first run, the builder creates `.ciss-live-builder-owned` in a new or empty build directory whose canonical parent
already exists. A populated directory without that marker is rejected and is never adopted automatically. Cleanup remains
intentionally destructive inside the exact validated marker-owned directory.
4. Locate your ISO in the `--build-directory`. 4. Locate your ISO in the `--build-directory`.
5. Boot from the ISO and login to the live image via the console, or the multi-layer secured **coresecret** SSH tunnel. 5. Boot from the ISO and login to the live image via the console, or the multi-layer secured **coresecret** SSH tunnel.
6. Type `sysp` for the final kernel hardening features. 6. Type `sysp` for the final kernel hardening features.
@@ -551,7 +570,8 @@ preview it or run it.
2. Preparation: 2. Preparation:
1. Ensure you are root. 1. Ensure you are root.
2. Create the build directory `mkdir /opt/cdlb` and the tmpfs secrets directory `mkdir /dev/shm/cdlb_secrets`. 2. Create the empty build directory and tmpfs secret root with restrictive ownership and permissions:
`install -d -m 0700 -o root -g root /opt/cdlb /dev/shm/cdlb_secrets`.
3. Place your desired SSH public key in the `authorized_keys` file, for example, in the `/dev/shm/cdlb_secrets` directory. 3. Place your desired SSH public key in the `authorized_keys` file, for example, in the `/dev/shm/cdlb_secrets` directory.
4. Place your desired Password in the `password.txt` file, for example, in the `/dev/shm/cdlb_secrets` directory. 4. Place your desired Password in the `password.txt` file, for example, in the `/dev/shm/cdlb_secrets` directory.
5. Copy and edit the sample and set your options (no spaces around commas in lists): 5. Copy and edit the sample and set your options (no spaces around commas in lists):
@@ -569,6 +589,9 @@ preview it or run it.
SSH_PUBKEY=/dev/shm/cdlb_secrets SSH_PUBKEY=/dev/shm/cdlb_secrets
# Optional # Optional
PRIMORDIAL_URL=https://git.coresecret.dev/ahz/PhysNet.primordial.git
PRIMORDIAL_KEY=id--git.coresecret.dev--PhysNet.primordial_deploy--ed25519--newton--2025-10
PRIMORDIAL_SSH_PORT=42842
PROVIDER_NETCUP_IPV6=2001:cdb::1 PROVIDER_NETCUP_IPV6=2001:cdb::1
# comma-separated; IPv6 in [] is fine # comma-separated; IPv6 in [] is fine
JUMP_HOSTS=[2001:db8::1],[2001:db8::2] JUMP_HOSTS=[2001:db8::1],[2001:db8::2]
@@ -645,10 +668,10 @@ The private directory is ignored by Git. The hooks fail if the CISS EFI image si
#... #...
- name: Preparing the build environment. - name: Preparing the build environment.
run: | run: |
mkdir -p /opt/config install -d -m 0700 -o root -g root /opt/livebuild /dev/shm/cdlb_secrets
mkdir -p /opt/livebuild umask 0077
echo "${{ secrets.CHANGE_ME }}" >| /opt/config/password.txt printf '%s\n' "${{ secrets.CHANGE_ME }}" >| /dev/shm/cdlb_secrets/password.txt
echo "${{ secrets.CHANGE_ME }}" >| /opt/config/authorized_keys printf '%s\n' "${{ secrets.CHANGE_ME }}" >| /dev/shm/cdlb_secrets/authorized_keys
#... #...
- name: Starting CISS.debian.live.builder. This may take a while ... - name: Starting CISS.debian.live.builder. This may take a while ...
run: | run: |
@@ -661,9 +684,9 @@ The private directory is ignored by Git. The hooks fail if the CISS EFI image si
--build-directory /opt/livebuild \ --build-directory /opt/livebuild \
--control "${timestamp}" \ --control "${timestamp}" \
--jump-host "${{ secrets.CHANGE_ME }}" \ --jump-host "${{ secrets.CHANGE_ME }}" \
--root-password-file /opt/config/password.txt \ --root-password-file /dev/shm/cdlb_secrets/password.txt \
--ssh-port CHANGE_ME \ --ssh-port CHANGE_ME \
--ssh-pubkey /opt/config --ssh-pubkey /dev/shm/cdlb_secrets
#... #...
### SKIP OR CHANGE ALL REMAINING STEPS ### SKIP OR CHANGE ALL REMAINING STEPS
``` ```
+2 -2
View File
@@ -8,13 +8,13 @@ include_toc: true
**Centurion Intelligence Consulting Agency Information Security Standard**<br> **Centurion Intelligence Consulting Agency Information Security Standard**<br>
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br> *Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
**Master Version**: 9.14<br> **Master Version**: 9.14<br>
**Build**: V9.14.020.2026.06.08<br> **Build**: V9.14.022.2026.06.10<br>
# 2. Repository Structure # 2. Repository Structure
**Project:** Centurion Intelligence Consulting Agency Information Security Standard (CISS) — Debian Live Builder **Project:** Centurion Intelligence Consulting Agency Information Security Standard (CISS) — Debian Live Builder
**Branch:** `master` **Branch:** `master`
**Repository State:** Master Version **9.14**, Build **V9.14.020.2026.06.08** (as of 2025-10-11) **Repository State:** Master Version **9.14**, Build **V9.14.022.2026.06.10** (as of 2025-10-11)
## 3.1. Top-Level Layout ## 3.1. Top-Level Layout
+37
View File
@@ -0,0 +1,37 @@
.:-=++***#####***+==-:.
.-=*#%%@@@@@@@@@@@@@@@@@@@@@%%#*=-.
.=*#@@@@@@@%%%%%%%%%%%%%%%%%%%%%@@@@@@@%*=:
:+#@@@@%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@@@@%*=.
.+#@@@%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@@@#=:
:*%@@%%%%%%%%%%%%%%%%@@@@@@@@@@@@@%%%%%%%%%%%%%%%%@@@@%%%*=
:*@@%%%%%%%%%%%%%%@@@@@%%#*******#%%@@@@%%%%%%%%%@@%#+-:.
.+@@%%%%%%%%%%%%%%@@%#+-. .-+#%@@%%%%@@#=.
-%@%%%%%%%%%%%%%@@%*-. :-+**####**+-: .-*%@@@*:
+@@%%%%%%%%%%%%%@%+. :+#%@@@@@@@@@@@@@@%#+: .+#:
*@%%%%%%%%%%%%%%@*. =#@@@@%%%%%%%%%%%%%%@@@@#-
*@%%%%%%%%%%%%%%@- -%@@%%%%%%%%%%%%%%%%%%%%%%@@#-
+@%%%%%%%%%%%%%%@- +@@%%%%%%%%%%%%%%%%%%%%%%%%%%@@+-*#
-@%%%%%%%%%%%%%%@+ +@%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@@@@-
%%%%%%%%%%%%%%%%% :@%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-@%%%%%%%%%%%%%%@* +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@=
#%%%%%%%%%%%%%%%@= *@%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
.%%%%%%%%%%%%%%%%@+ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@@%%%%%%%=
-@%%%%%%%%%%%%%%%@* :@%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@@@@@@@@.
=@%%%%%%%%%%%%%%%%%. #@%%%%%%%%%%%%%%%%%%%%%%%%%%%*..:--==+*-
=@%%%%%%%%%%%%%%%%@= :@%%%%%%%%%%%%%%%%%%%%%%%%%%%@#:
=@%%%%%%%%%%%%%%%%%%. +@%%%%%%%%%%%%%%%%%%%%%%%%%%%@@+
:@%%%%%%%%%%%%%%%%%@# #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@#::::.
%@%%%%%%%%%%%%%%%%%@= :@%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@@@@@@%#:
*%%%%%%%%%%%%%%%%%%- *@%%%%%%%%%%%%%%%@@@@%%%%%%%%%%%%%%%@@@.
:@%%%%%%%%%%%%%%%@- -@%%%%%%%%%%%%@@@%%%%%@@%%%%%%%%%%%%%%%.
*@%%%%%%%%%%%%%@+ .%%%%%%%%%%%@@*=:. .-*@%%%%%%%%%%%%@=
.%%%%%%%%%%%%%%%. .%%%%%%%%%@@*: :%%%%%%%%%%%@+
=@%%%%%%%%%%%@* -@%%%%%%%@#: =@%%%%%%%%@*
+@%%%%%%%%%%@. *@%%%%%@@+ .@%%%%%%%%%.
*@%%%%%%%%@+ -@%%%%%@%- .@%%%%%%%@=
+@%%%%%@@* :%%%%%@@*. -@%%%%%%%%
=@@@@@#- :%%%%@@%- #%%%%%%%@+
:#*+: :%%%@@%+ -@@@%%%%%@:
=@@@@#=. :+#@@@@%%.
.*%#*=. .=*%@%
::. .-+
+1 -1
View File
@@ -8,7 +8,7 @@ include_toc: true
**Centurion Intelligence Consulting Agency Information Security Standard**<br> **Centurion Intelligence Consulting Agency Information Security Standard**<br>
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br> *Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
**Master Version**: 9.14<br> **Master Version**: 9.14<br>
**Build**: V9.14.020.2026.06.08<br> **Build**: V9.14.022.2026.06.10<br>
# 2. CISS Secure Boot Private Material # 2. CISS Secure Boot Private Material
+1 -1
View File
@@ -8,7 +8,7 @@ include_toc: true
**Centurion Intelligence Consulting Agency Information Security Standard**<br> **Centurion Intelligence Consulting Agency Information Security Standard**<br>
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br> *Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
**Master Version**: 9.14<br> **Master Version**: 9.14<br>
**Build**: V9.14.020.2026.06.08<br> **Build**: V9.14.022.2026.06.10<br>
# 2. CISS Secure Boot Public Material # 2. CISS Secure Boot Public Material
+20 -17
View File
@@ -111,6 +111,7 @@ source_guard "./var/bash.var.sh"
### CHECK FOR CONTACT, HELP, VERSION STRING, AND XTRACE DEBUG. ### CHECK FOR CONTACT, HELP, VERSION STRING, AND XTRACE DEBUG.
for arg in "$@"; do case "${arg,,}" in -c|--contact) . ./lib/lib_contact.sh ; contact; exit 0;; esac; done for arg in "$@"; do case "${arg,,}" in -c|--contact) . ./lib/lib_contact.sh ; contact; exit 0;; esac; done
for arg in "$@"; do case "${arg,,}" in -h|--help) . ./lib/lib_usage.sh ; usage ; exit 0;; esac; done for arg in "$@"; do case "${arg,,}" in -h|--help) . ./lib/lib_usage.sh ; usage ; exit 0;; esac; done
for arg in "$@"; do case "${arg,,}" in -l|--logo) . ./lib/lib_logo.sh ; logo ; exit 0;; esac; done
for arg in "$@"; do case "${arg,,}" in -v|--version) . ./lib/lib_version.sh ; version; exit 0;; esac; done for arg in "$@"; do case "${arg,,}" in -v|--version) . ./lib/lib_version.sh ; version; exit 0;; esac; done
for arg in "$@"; do case "${arg,,}" in -d|--debug) . ./meta_sources_debug.sh; debugger "${@}";; esac; done for arg in "$@"; do case "${arg,,}" in -d|--debug) . ./meta_sources_debug.sh; debugger "${@}";; esac; done
@@ -123,22 +124,28 @@ sleep 4
printf "\e[95m🧪 %s starting ... \e[0m\n" "${BASH_SOURCE[0]}" printf "\e[95m🧪 %s starting ... \e[0m\n" "${BASH_SOURCE[0]}"
declare -grx VAR_SETUP="true" declare -grx VAR_SETUP="true"
### SECURING SECRETS ARTIFACTS.
test ! -L "${VAR_TMP_SECRET}" || {
. ./var/global.var.sh
printf "\e[91m❌ Refusing symlink: '%s'! Bye... \e[0m\n" "${VAR_TMP_SECRET}" >&2
exit "${ERR_SECRETSSYM}"
}
find "${VAR_TMP_SECRET}" -type f -exec chmod 0400 {} +
find "${VAR_TMP_SECRET}" -type f -exec chown root:root {} +
### SOURCING VARIABLES. ### SOURCING VARIABLES.
[[ "${VAR_SETUP}" == true ]] && { [[ "${VAR_SETUP}" == true ]] && {
source_guard "./var/color.var.sh" source_guard "./var/color.var.sh"
source_guard "./var/global.var.sh" source_guard "./var/global.var.sh"
} }
### SOURCING LIBRARIES. ### SOURCE THE MINIMUM REQUIRED FOR EARLY EXIT CLEANUP COVERAGE.
[[ "${VAR_SETUP}" == true ]] && {
source_guard "./lib/lib_secret_validation.sh"
source_guard "./lib/lib_build_directory.sh"
source_guard "./lib/lib_debug_sanitizer.sh"
source_guard "./lib/lib_clean_up.sh"
source_guard "./lib/lib_trap_on_err.sh"
source_guard "./lib/lib_trap_on_exit.sh"
}
trap 'trap_on_exit "$?" "${BASH_SOURCE[0]}" "${LINENO}" "${FUNCNAME[0]:-main}" "${BASH_COMMAND}"' EXIT
### Validate the fixed tmpfs secret staging area without modifying operator-provided files.
validate_secret_staging_area
### SOURCING REMAINING LIBRARIES.
[[ "${VAR_SETUP}" == true ]] && { [[ "${VAR_SETUP}" == true ]] && {
source_guard "./lib/lib_arg_parser.sh" source_guard "./lib/lib_arg_parser.sh"
source_guard "./lib/lib_arg_priority_check.sh" source_guard "./lib/lib_arg_priority_check.sh"
@@ -157,7 +164,6 @@ find "${VAR_TMP_SECRET}" -type f -exec chown root:root {} +
source_guard "./lib/lib_ciss_upgrades_boot.sh" source_guard "./lib/lib_ciss_upgrades_boot.sh"
source_guard "./lib/lib_ciss_upgrades_build.sh" source_guard "./lib/lib_ciss_upgrades_build.sh"
source_guard "./lib/lib_clean_screen.sh" source_guard "./lib/lib_clean_screen.sh"
source_guard "./lib/lib_clean_up.sh"
source_guard "./lib/lib_copy_integrity.sh" source_guard "./lib/lib_copy_integrity.sh"
source_guard "./lib/lib_gnupg.sh" source_guard "./lib/lib_gnupg.sh"
source_guard "./lib/lib_hardening_root_pw.sh" source_guard "./lib/lib_hardening_root_pw.sh"
@@ -173,12 +179,13 @@ find "${VAR_TMP_SECRET}" -type f -exec chown root:root {} +
source_guard "./lib/lib_run_analysis.sh" source_guard "./lib/lib_run_analysis.sh"
source_guard "./lib/lib_sanitizer.sh" source_guard "./lib/lib_sanitizer.sh"
source_guard "./lib/lib_secureboot_profile.sh" source_guard "./lib/lib_secureboot_profile.sh"
source_guard "./lib/lib_trap_on_err.sh"
source_guard "./lib/lib_trap_on_exit.sh"
source_guard "./lib/lib_update_microcode.sh" source_guard "./lib/lib_update_microcode.sh"
source_guard "./lib/lib_usage.sh" source_guard "./lib/lib_usage.sh"
} }
### Add ERR handling after all remaining libraries are available.
trap 'trap_on_err "$?" "${BASH_SOURCE[0]}" "${LINENO}" "${FUNCNAME[0]:-main}" "${BASH_COMMAND}"' ERR
### PRE-SCAN SECURE BOOT PROFILE FOR BUILD-HOST PACKAGE CHECKS. ### PRE-SCAN SECURE BOOT PROFILE FOR BUILD-HOST PACKAGE CHECKS.
### Formal validation still happens in arg_parser(). ### Formal validation still happens in arg_parser().
for ((idx=0; idx<${#ARY_PARAM_ARRAY[@]}; idx++)); do for ((idx=0; idx<${#ARY_PARAM_ARRAY[@]}; idx++)); do
@@ -222,10 +229,6 @@ if ! ${VAR_HANDLER_AUTOBUILD}; then printf "XXX\nInitialization done ... \nXXX\n
### Updating Status of Dialog Gauge Bar. ### Updating Status of Dialog Gauge Bar.
if ! ${VAR_HANDLER_AUTOBUILD}; then printf "XXX\nActivate traps ... \nXXX\n50\n" >&3; fi if ! ${VAR_HANDLER_AUTOBUILD}; then printf "XXX\nActivate traps ... \nXXX\n50\n" >&3; fi
### Following the CISS Bash naming and ordering scheme:
trap 'trap_on_exit "$?" "${BASH_SOURCE[0]}" "${LINENO}" "${FUNCNAME[0]:-main}" "${BASH_COMMAND}"' EXIT
trap 'trap_on_err "$?" "${BASH_SOURCE[0]}" "${LINENO}" "${FUNCNAME[0]:-main}" "${BASH_COMMAND}"' ERR
### Updating Status of Dialog Gauge Bar. ### Updating Status of Dialog Gauge Bar.
if ! ${VAR_HANDLER_AUTOBUILD}; then printf "XXX\nSanitizing Arguments ... \nXXX\n75\n" >&3; fi if ! ${VAR_HANDLER_AUTOBUILD}; then printf "XXX\nSanitizing Arguments ... \nXXX\n75\n" >&3; fi
arg_check "$@" arg_check "$@"
+4
View File
@@ -15,6 +15,10 @@ BUILD_DIR ?=
DROPBEAR_VERSION ?= DROPBEAR_VERSION ?=
### Optional SOPS release override; empty uses VAR_SOPS_VERSION from var/global.var.sh: ### Optional SOPS release override; empty uses VAR_SOPS_VERSION from var/global.var.sh:
SOPS_VERSION ?= SOPS_VERSION ?=
### Optional Primordial CDI overlay settings; all three values are required for automatic overlay bootstrap:
PRIMORDIAL_URL ?=
PRIMORDIAL_KEY ?=
PRIMORDIAL_SSH_PORT ?=
PROVIDER_NETCUP_IPV6 ?= PROVIDER_NETCUP_IPV6 ?=
ROOT_PASSWORD_FILE ?= ROOT_PASSWORD_FILE ?=
### Secure Boot profile; debian-shim or ciss-uki: ### Secure Boot profile; debian-shim or ciss-uki:
+3 -1
View File
@@ -15,6 +15,7 @@ printf "\e[95m🧪 '%s' starting ... \e[0m\n" "${0}"
declare -r UFW_OUT_POLICY="deny" declare -r UFW_OUT_POLICY="deny"
declare -r SSHPORT="SSHPORT_MUST_BE_SET" declare -r SSHPORT="SSHPORT_MUST_BE_SET"
# PRIMORDIAL_SSH_PORT_DECLARATION_MUST_BE_SET
ufw --force reset ufw --force reset
@@ -44,7 +45,8 @@ if [[ ${UFW_OUT_POLICY,,} == "deny" ]]; then
ufw allow out 853/tcp comment 'Outgoing DoT' ufw allow out 853/tcp comment 'Outgoing DoT'
ufw allow out 993/tcp comment 'Outgoing IMAPS' ufw allow out 993/tcp comment 'Outgoing IMAPS'
ufw allow out 4460/tcp comment 'Outgoing NTS' ufw allow out 4460/tcp comment 'Outgoing NTS'
ufw allow out "${SSHPORT}"/tcp comment 'Outgoing SSH (Custom-Port)' ufw allow out "${SSHPORT}"/tcp comment 'Outgoing SSH Custom-Port'
# PRIMORDIAL_SSH_RULE_MUST_BE_SET
ufw allow out 53/udp comment 'Outgoing DNS' ufw allow out 53/udp comment 'Outgoing DNS'
ufw allow out 123/udp comment 'Outgoing NTP' ufw allow out 123/udp comment 'Outgoing NTP'
ufw allow out 443/udp comment 'Outgoing QUIC' ufw allow out 443/udp comment 'Outgoing QUIC'
@@ -66,6 +66,49 @@ readonly -f preallocate
declare ROOTFS="${VAR_HANDLER_BUILD_DIR}/binary/live/filesystem.squashfs" declare ROOTFS="${VAR_HANDLER_BUILD_DIR}/binary/live/filesystem.squashfs"
declare LUKSFS="${VAR_HANDLER_BUILD_DIR}/binary/live/ciss_rootfs.crypt" declare LUKSFS="${VAR_HANDLER_BUILD_DIR}/binary/live/ciss_rootfs.crypt"
declare KEYFD="" declare KEYFD=""
declare LUKS_KEY_FILE=""
declare LUKS_KEY_FILENAME="${VAR_LUKS_KEY:-luks.txt}"
declare LUKS_KEY_LINK_COUNT=""
declare LUKS_KEY_MODE=""
declare LUKS_KEY_OWNER=""
declare SECRET_ROOT_FS=""
declare SECRET_ROOT_MODE=""
declare SECRET_ROOT_OWNER=""
if [[ -L "${VAR_TMP_SECRET}" || ! -d "${VAR_TMP_SECRET}" ]]; then
printf "\e[91m❌ Unsafe secret root rejected. \e[0m\n" >&2
exit 42
fi
SECRET_ROOT_OWNER="$(stat -c '%u' "${VAR_TMP_SECRET}")"
SECRET_ROOT_MODE="$(stat -c '%a' "${VAR_TMP_SECRET}")"
SECRET_ROOT_FS="$(stat -f -c '%T' "${VAR_TMP_SECRET}")"
if [[ "${SECRET_ROOT_OWNER}" != "${EUID}" || "${SECRET_ROOT_MODE}" != "700" \
|| ( "${SECRET_ROOT_FS}" != "tmpfs" && "${SECRET_ROOT_FS}" != "ramfs" ) ]]; then
printf "\e[91m❌ Unsafe secret-root ownership, permissions, or filesystem rejected. \e[0m\n" >&2
exit 42
fi
if [[ -z "${LUKS_KEY_FILENAME}" || "${LUKS_KEY_FILENAME}" == "." || "${LUKS_KEY_FILENAME}" == ".." \
|| "${LUKS_KEY_FILENAME}" == */* || ! "${LUKS_KEY_FILENAME}" =~ ^[A-Za-z0-9._@%+=:,~-]+$ ]]; then
printf "\e[91m❌ Unsafe LUKS key filename rejected. \e[0m\n" >&2
exit 42
fi
LUKS_KEY_FILE="${VAR_TMP_SECRET}/${LUKS_KEY_FILENAME}"
if [[ -L "${LUKS_KEY_FILE}" || ! -f "${LUKS_KEY_FILE}" ]]; then
printf "\e[91m❌ Unsafe LUKS key file rejected. \e[0m\n" >&2
exit 42
fi
LUKS_KEY_OWNER="$(stat -c '%u' "${LUKS_KEY_FILE}")"
LUKS_KEY_MODE="$(stat -c '%a' "${LUKS_KEY_FILE}")"
LUKS_KEY_LINK_COUNT="$(stat -c '%h' "${LUKS_KEY_FILE}")"
if [[ "${LUKS_KEY_OWNER}" != "${EUID}" || "${LUKS_KEY_LINK_COUNT}" != "1" \
|| ( "${LUKS_KEY_MODE}" != "400" && "${LUKS_KEY_MODE}" != "600" ) ]]; then
printf "\e[91m❌ Unsafe LUKS key ownership, permissions, or link count rejected. \e[0m\n" >&2
exit 42
fi
# shellcheck disable=SC2155 # shellcheck disable=SC2155
declare -i VAR_ROOTFS_SIZE=$(stat -c%s -- "${ROOTFS}") declare -i VAR_ROOTFS_SIZE=$(stat -c%s -- "${ROOTFS}")
@@ -82,7 +125,7 @@ declare -i VAR_LUKSFS_SIZE=$(( ( (BASE_SIZE + ALIGN_BYTES - 1) / ALIGN_BYTES ) *
preallocate "${LUKSFS}" "${VAR_LUKSFS_SIZE}" preallocate "${LUKSFS}" "${VAR_LUKSFS_SIZE}"
exec {KEYFD}<"${VAR_TMP_SECRET}/luks.txt" exec {KEYFD}<"${LUKS_KEY_FILE}"
if [[ "${VAR_CDLB_INSIDE_RUNNER}" == "false" ]]; then if [[ "${VAR_CDLB_INSIDE_RUNNER}" == "false" ]]; then
@@ -146,7 +189,7 @@ cryptsetup close crypt_liveiso
exec {KEYFD}<&- exec {KEYFD}<&-
shred -fzu -n 5 -- "${VAR_TMP_SECRET}/luks.txt" shred -fzu -n 5 -- "${LUKS_KEY_FILE}"
rm -f -- "${ROOTFS}" rm -f -- "${ROOTFS}"
@@ -9,7 +9,7 @@
# SPDX-PackageName: CISS.debian.live.builder # SPDX-PackageName: CISS.debian.live.builder
# SPDX-Security-Contact: security@coresecret.eu # SPDX-Security-Contact: security@coresecret.eu
# Version Master V9.14.020.2026.06.08 # Version Master V9.14.022.2026.06.10
[git.coresecret.dev]:42842 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGQA107AVmg1D/jnyXiqbPf38zQRl8s3c+PM1zbfpeQl [git.coresecret.dev]:42842 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGQA107AVmg1D/jnyXiqbPf38zQRl8s3c+PM1zbfpeQl
[git.coresecret.dev]:42842 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDYD9ysmMWZlejUnxu0qOzeWcIYezoFLbYdo6ffGUL5kqOBAYb+5CF4bJLUpA93XFYVF+TbrcMV1yJh6JaHFL0VU5CvgAzruCeedx0c4qUV6lWcJUGNk5K0yb9n2Wosdy6F/zTOxL9KXBt/TV+cscsen2Dahvx0ctMKgNbu+vvUcWxHf9lOkbYoF/uA/nW5CVXy5XUPVUDFUhEeKXL85+6gid5AEMfYT8aRl5YDGvo1iMBmBYOljN4S7MnRe14qbAZG0GDGvF22eHbSU2pILcFIjc2Lo/S5Ox/MJpbLAqpFlLPTKgr6F7yVwfNMSNwl05ysUOZfrQKSXzCU6+lfqKYCwemLALyG/n1ernpp7/8W/2RYoz3fd+TQyfhW++rx3yUHpYCkTv9A4LRYZYGSAWKMHSBEYq3EcATQUxQi0xpwmcR+u0uC9F9eta5Bim+sBZD6F2hgPJ5xgYT8LFm880g1YadAwBoD4TAkqSvl+jYW0VA2GH9CknKHJ36gc/X4eeUHDC1Hf/E8M5RBj4D6NuHfeVRik/ahHmoCqKQUW7VU/EBsWFsngDiLEHcV71iMtWiUddWOHwoAPHIzn6p9HTeLCxTwsPMG5UDGK/S9HUozqDXxexRtqbcFa7DWuzRvZ1bcZ2VQsaafuzKCkkc4NjC7h1wssel7q9aeYPFg+1vS6Q== [git.coresecret.dev]:42842 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDYD9ysmMWZlejUnxu0qOzeWcIYezoFLbYdo6ffGUL5kqOBAYb+5CF4bJLUpA93XFYVF+TbrcMV1yJh6JaHFL0VU5CvgAzruCeedx0c4qUV6lWcJUGNk5K0yb9n2Wosdy6F/zTOxL9KXBt/TV+cscsen2Dahvx0ctMKgNbu+vvUcWxHf9lOkbYoF/uA/nW5CVXy5XUPVUDFUhEeKXL85+6gid5AEMfYT8aRl5YDGvo1iMBmBYOljN4S7MnRe14qbAZG0GDGvF22eHbSU2pILcFIjc2Lo/S5Ox/MJpbLAqpFlLPTKgr6F7yVwfNMSNwl05ysUOZfrQKSXzCU6+lfqKYCwemLALyG/n1ernpp7/8W/2RYoz3fd+TQyfhW++rx3yUHpYCkTv9A4LRYZYGSAWKMHSBEYq3EcATQUxQi0xpwmcR+u0uC9F9eta5Bim+sBZD6F2hgPJ5xgYT8LFm880g1YadAwBoD4TAkqSvl+jYW0VA2GH9CknKHJ36gc/X4eeUHDC1Hf/E8M5RBj4D6NuHfeVRik/ahHmoCqKQUW7VU/EBsWFsngDiLEHcV71iMtWiUddWOHwoAPHIzn6p9HTeLCxTwsPMG5UDGK/S9HUozqDXxexRtqbcFa7DWuzRvZ1bcZ2VQsaafuzKCkkc4NjC7h1wssel7q9aeYPFg+1vS6Q==
+1 -1
View File
@@ -9,7 +9,7 @@
# SPDX-PackageName: CISS.debian.live.builder # SPDX-PackageName: CISS.debian.live.builder
# SPDX-Security-Contact: security@coresecret.eu # SPDX-Security-Contact: security@coresecret.eu
# Version Master V9.14.020.2026.06.08 # Version Master V9.14.022.2026.06.10
### https://www.ssh-audit.com/ ### https://www.ssh-audit.com/
### ssh -Q cipher | cipher-auth | compression | kex | kex-gss | key | key-cert | key-plain | key-sig | mac | protocol-version | sig ### ssh -Q cipher | cipher-auth | compression | kex | kex-gss | key | key-cert | key-plain | key-sig | mac | protocol-version | sig
@@ -11,7 +11,7 @@
# SPDX-PackageName: CISS.debian.live.builder # SPDX-PackageName: CISS.debian.live.builder
# SPDX-Security-Contact: security@coresecret.eu # SPDX-Security-Contact: security@coresecret.eu
# Version Master V9.14.020.2026.06.08 # Version Master V9.14.022.2026.06.10
### https://docs.kernel.org/ ### https://docs.kernel.org/
### https://github.com/a13xp0p0v/kernel-hardening-checker/ ### https://github.com/a13xp0p0v/kernel-hardening-checker/
@@ -10,7 +10,7 @@
# SPDX-PackageName: CISS.debian.live.builder # SPDX-PackageName: CISS.debian.live.builder
# SPDX-Security-Contact: security@coresecret.eu # SPDX-Security-Contact: security@coresecret.eu
declare -gr VERSION="Master V9.14.020.2026.06.08" declare -gr VERSION="Master V9.14.022.2026.06.10"
### VERY EARLY CHECK FOR DEBUGGING ### VERY EARLY CHECK FOR DEBUGGING
if [[ $* == *" --debug "* ]]; then if [[ $* == *" --debug "* ]]; then
+1 -1
View File
@@ -112,4 +112,4 @@ d-i preseed/late_command string sh /preseed/.ash/3_di_preseed_late_command.sh
# Please consider donating to my work at: https://coresecret.eu/spenden/ # Please consider donating to my work at: https://coresecret.eu/spenden/
########################################################################################### ###########################################################################################
# Written by: ./preseed_hash_generator.sh Version: Master V9.14.020.2026.06.08 at: 10:18:37.9542 # Written by: ./preseed_hash_generator.sh Version: Master V9.14.022.2026.06.10 at: 10:18:37.9542
+1 -1
View File
@@ -8,7 +8,7 @@ include_toc: true
**Centurion Intelligence Consulting Agency Information Security Standard**<br> **Centurion Intelligence Consulting Agency Information Security Standard**<br>
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br> *Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
**Master Version**: 9.14<br> **Master Version**: 9.14<br>
**Build**: V9.14.020.2026.06.08<br> **Build**: V9.14.022.2026.06.10<br>
# 2. DNSSEC Status # 2. DNSSEC Status
+1 -1
View File
@@ -8,7 +8,7 @@ include_toc: true
**Centurion Intelligence Consulting Agency Information Security Standard**<br> **Centurion Intelligence Consulting Agency Information Security Standard**<br>
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br> *Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
**Master Version**: 9.14<br> **Master Version**: 9.14<br>
**Build**: V9.14.020.2026.06.08<br> **Build**: V9.14.022.2026.06.10<br>
# 2. Haveged Audit on Netcup RS 2000 G11 # 2. Haveged Audit on Netcup RS 2000 G11
+1 -1
View File
@@ -8,7 +8,7 @@ include_toc: true
**Centurion Intelligence Consulting Agency Information Security Standard**<br> **Centurion Intelligence Consulting Agency Information Security Standard**<br>
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br> *Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
**Master Version**: 9.14<br> **Master Version**: 9.14<br>
**Build**: V9.14.020.2026.06.08<br> **Build**: V9.14.022.2026.06.10<br>
# 2. Lynis Audit: # 2. Lynis Audit:
+1 -1
View File
@@ -8,7 +8,7 @@ include_toc: true
**Centurion Intelligence Consulting Agency Information Security Standard**<br> **Centurion Intelligence Consulting Agency Information Security Standard**<br>
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br> *Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
**Master Version**: 9.14<br> **Master Version**: 9.14<br>
**Build**: V9.14.020.2026.06.08<br> **Build**: V9.14.022.2026.06.10<br>
# 2. SSH Audit by ssh-audit.com # 2. SSH Audit by ssh-audit.com
+1 -1
View File
@@ -8,7 +8,7 @@ include_toc: true
**Centurion Intelligence Consulting Agency Information Security Standard**<br> **Centurion Intelligence Consulting Agency Information Security Standard**<br>
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br> *Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
**Master Version**: 9.14<br> **Master Version**: 9.14<br>
**Build**: V9.14.020.2026.06.08<br> **Build**: V9.14.022.2026.06.10<br>
# 2. TLS Audit: # 2. TLS Audit:
````text ````text
+1 -1
View File
@@ -8,7 +8,7 @@ include_toc: true
**Centurion Intelligence Consulting Agency Information Security Standard**<br> **Centurion Intelligence Consulting Agency Information Security Standard**<br>
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br> *Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
**Master Version**: 9.14<br> **Master Version**: 9.14<br>
**Build**: V9.14.020.2026.06.08<br> **Build**: V9.14.022.2026.06.10<br>
# 2. Hardened Kernel Boot Parameters # 2. Hardened Kernel Boot Parameters
+19 -13
View File
@@ -8,11 +8,17 @@ include_toc: true
**Centurion Intelligence Consulting Agency Information Security Standard**<br> **Centurion Intelligence Consulting Agency Information Security Standard**<br>
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br> *Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
**Master Version**: 9.14<br> **Master Version**: 9.14<br>
**Build**: V9.14.020.2026.06.08<br> **Build**: V9.14.022.2026.06.10<br>
# 2. Changelog # 2. Changelog
## V9.14.022.2026.06.10
* **Added**: [lib_logo.sh](../lib/lib_logo.sh)
* **Added**: [9999_cdi_starter.sh](../scripts/usr/local/sbin/9999_cdi_starter.sh) Retrieve rdns for Primordial-Workflow™
* **Added**: [0900_ufw_setup.chroot](../config/hooks/live/0900_ufw_setup.chroot) SSH ufw out exception for Primordial-Workflow™
## V9.14.020.2026.06.08 ## V9.14.020.2026.06.08
* **Added**: [bootscreen.txt](../bootscreen.txt)
* **Changed**: ``sops 3.13.0`` to ``sops 3.13.1`` * **Changed**: ``sops 3.13.0`` to ``sops 3.13.1``
## V9.14.018.2026.06.07 ## V9.14.018.2026.06.07
@@ -132,7 +138,7 @@ include_toc: true
* **Changed**: [lib_check_secrets.sh](../lib/lib_check_secrets.sh) + updated shopt handling. * **Changed**: [lib_check_secrets.sh](../lib/lib_check_secrets.sh) + updated shopt handling.
* **Changed**: [lib_ciss_upgrades_boot.sh](../lib/lib_ciss_upgrades_boot.sh) + integrates and generates sha512sum and GPG signatures on CISS specific LIVE boot artifacts. * **Changed**: [lib_ciss_upgrades_boot.sh](../lib/lib_ciss_upgrades_boot.sh) + integrates and generates sha512sum and GPG signatures on CISS specific LIVE boot artifacts.
* **Changed**: [lib_gnupg.sh](../lib/lib_gnupg.sh) + integration of optional import of offline GPG CA public keys. * **Changed**: [lib_gnupg.sh](../lib/lib_gnupg.sh) + integration of optional import of offline GPG CA public keys.
* **Changed**: [lib_primordial.sh](../lib/lib_primordial.sh) + Updates for CISS and PhysNet primordial-workflow™. * **Changed**: [lib_primordial.sh](../lib/lib_primordial.sh) + Updates for CISS and PhysNet Primordial-Workflow™.
* **Changed**: [lib_usage.sh](../lib/lib_usage.sh) + ``--signing_ca=*``. * **Changed**: [lib_usage.sh](../lib/lib_usage.sh) + ``--signing_ca=*``.
* **Changed**: [binary_checksums.sh](../scripts/usr/lib/live/build/binary_checksums.sh) + ``! -path './live/filesystem.squashfs'`` * **Changed**: [binary_checksums.sh](../scripts/usr/lib/live/build/binary_checksums.sh) + ``! -path './live/filesystem.squashfs'``
* **Changed**: [9999_cdi_starter.sh](../scripts/usr/local/sbin/9999_cdi_starter.sh) + increased verbosity. * **Changed**: [9999_cdi_starter.sh](../scripts/usr/local/sbin/9999_cdi_starter.sh) + increased verbosity.
@@ -186,10 +192,10 @@ include_toc: true
* **Added**: [marc_s_weidner_msw+deploy@coresecet.dev_0x2CCF4601_public.asc](../.pubkey/marc_s_weidner_msw%2Bdeploy%40coresecet.dev_0x2CCF4601_public.asc) * **Added**: [marc_s_weidner_msw+deploy@coresecet.dev_0x2CCF4601_public.asc](../.pubkey/marc_s_weidner_msw%2Bdeploy%40coresecet.dev_0x2CCF4601_public.asc)
* **Added**: [0870_bashdb.chroot](../config/hooks/live/0870_bashdb.chroot) bashdb debugger https://github.com/Trepan-Debuggers/bashdb.git * **Added**: [0870_bashdb.chroot](../config/hooks/live/0870_bashdb.chroot) bashdb debugger https://github.com/Trepan-Debuggers/bashdb.git
* **Added**: [0030-ciss-verify-checksums](../config/includes.chroot/usr/lib/live/boot/0030-ciss-verify-checksums) Unified handling via includes.chroot. * **Added**: [0030-ciss-verify-checksums](../config/includes.chroot/usr/lib/live/boot/0030-ciss-verify-checksums) Unified handling via includes.chroot.
* **Added**: [lib_ciss_upgrades_boot.sh](../lib/lib_ciss_upgrades_boot.sh) Updates for CISS and PhysNet primordial-workflow™. * **Added**: [lib_ciss_upgrades_boot.sh](../lib/lib_ciss_upgrades_boot.sh) Updates for CISS and PhysNet Primordial-Workflow™.
* **Added**: [lib_ciss_upgrades_build.sh](../lib/lib_ciss_upgrades_build.sh) Updates for CISS and PhysNet primordial-workflow™. * **Added**: [lib_ciss_upgrades_build.sh](../lib/lib_ciss_upgrades_build.sh) Updates for CISS and PhysNet Primordial-Workflow™.
* **Added**: [lib_gnupg.sh](../lib/lib_gnupg.sh) Updates for CISS and PhysNet primordial-workflow™. * **Added**: [lib_gnupg.sh](../lib/lib_gnupg.sh) Updates for CISS and PhysNet Primordial-Workflow™.
* **Added**: [lib_primordial.sh](../lib/lib_primordial.sh) Updates for CISS and PhysNet primordial-workflow™. * **Added**: [lib_primordial.sh](../lib/lib_primordial.sh) Updates for CISS and PhysNet Primordial-Workflow™.
* **Added**: [0030-ciss-verify-checksums](../scripts/usr/lib/live/boot/0030-ciss-verify-checksums) Unified handling via includes.chroot. * **Added**: [0030-ciss-verify-checksums](../scripts/usr/lib/live/boot/0030-ciss-verify-checksums) Unified handling via includes.chroot.
* **Bugfixes**: [linter_char_scripts.yaml](../.gitea/workflows/linter_char_scripts.yaml) - WORKFLOW_ID="${GITHUB_WORKFLOW:-linter_char_scripts.yaml}" * **Bugfixes**: [linter_char_scripts.yaml](../.gitea/workflows/linter_char_scripts.yaml) - WORKFLOW_ID="${GITHUB_WORKFLOW:-linter_char_scripts.yaml}"
* **Bugfixes**: [render-dnssec-status.yaml](../.gitea/workflows/render-dnssec-status.yaml) - WORKFLOW_ID="${GITHUB_WORKFLOW:-render-dnssec-status.yaml}" * **Bugfixes**: [render-dnssec-status.yaml](../.gitea/workflows/render-dnssec-status.yaml) - WORKFLOW_ID="${GITHUB_WORKFLOW:-render-dnssec-status.yaml}"
@@ -197,11 +203,11 @@ include_toc: true
* **Changed**: [generate_PRIVATE_trixie_1.yaml](../.gitea/workflows/generate_PRIVATE_trixie_1.yaml) Rewritten for new secrets handling. * **Changed**: [generate_PRIVATE_trixie_1.yaml](../.gitea/workflows/generate_PRIVATE_trixie_1.yaml) Rewritten for new secrets handling.
* **Changed**: [0000_basic_chroot_setup.chroot](../config/hooks/live/0000_basic_chroot_setup.chroot) + VAR_DATE improvements. * **Changed**: [0000_basic_chroot_setup.chroot](../config/hooks/live/0000_basic_chroot_setup.chroot) + VAR_DATE improvements.
* **Changed**: [0001_initramfs_modules.chroot](../config/hooks/live/0001_initramfs_modules.chroot) + VAR_DATE improvements. * **Changed**: [0001_initramfs_modules.chroot](../config/hooks/live/0001_initramfs_modules.chroot) + VAR_DATE improvements.
* **Changed**: [9930_hardening_ssh.chroot](../config/hooks/live/9930_hardening_ssh.chroot) Rewritten for CISS and PhysNet primordial-workflow™. * **Changed**: [9930_hardening_ssh.chroot](../config/hooks/live/9930_hardening_ssh.chroot) Rewritten for CISS and PhysNet Primordial-Workflow™.
* **Changed**: [9999_zzzz.chroot](../config/hooks/live/9999_zzzz.chroot) + Final update-initramfs * **Changed**: [9999_zzzz.chroot](../config/hooks/live/9999_zzzz.chroot) + Final update-initramfs
* **Changed**: [sshd_config](../config/includes.chroot/etc/ssh/sshd_config) + Less strict MaxStartups settings. * **Changed**: [sshd_config](../config/includes.chroot/etc/ssh/sshd_config) + Less strict MaxStartups settings.
* **Changed**: [live.list.common.chroot](../config/package-lists/live.list.common.chroot) + tmux * **Changed**: [live.list.common.chroot](../config/package-lists/live.list.common.chroot) + tmux
* **Changed**: [lib_arg_parser.sh](../lib/lib_arg_parser.sh) Rewritten for CISS and PhysNet primordial-workflow™. * **Changed**: [lib_arg_parser.sh](../lib/lib_arg_parser.sh) Rewritten for CISS and PhysNet Primordial-Workflow™.
* **Changed**: [lib_arg_priority_check.sh](../lib/lib_arg_priority_check.sh) Unified UI. * **Changed**: [lib_arg_priority_check.sh](../lib/lib_arg_priority_check.sh) Unified UI.
* **Changed**: [lib_cdi.sh](../lib/lib_cdi.sh) + Commandline parameters: verify-checksums=sha512,sha384 verify-checksums-signatures * **Changed**: [lib_cdi.sh](../lib/lib_cdi.sh) + Commandline parameters: verify-checksums=sha512,sha384 verify-checksums-signatures
* **Changed**: [lib_change_splash.sh](../lib/lib_change_splash.sh) Unified UI. * **Changed**: [lib_change_splash.sh](../lib/lib_change_splash.sh) Unified UI.
@@ -210,11 +216,11 @@ include_toc: true
* **Changed**: [lib_check_kernel.sh](../lib/lib_check_kernel.sh) Minor declare unification. * **Changed**: [lib_check_kernel.sh](../lib/lib_check_kernel.sh) Minor declare unification.
* **Changed**: [lib_check_pkgs.sh](../lib/lib_check_pkgs.sh) Improved command checks. Unified UI. * **Changed**: [lib_check_pkgs.sh](../lib/lib_check_pkgs.sh) Improved command checks. Unified UI.
* **Changed**: [lib_check_provider.sh](../lib/lib_check_provider.sh) Unified variables. * **Changed**: [lib_check_provider.sh](../lib/lib_check_provider.sh) Unified variables.
* **Changed**: [lib_clean_up.sh](../lib/lib_clean_up.sh) Secure deletion of CISS and PhysNet primordial-workflow™ artifacts. * **Changed**: [lib_clean_up.sh](../lib/lib_clean_up.sh) Secure deletion of CISS and PhysNet Primordial-Workflow™ artifacts.
* **Changed**: [lib_debug.sh](../lib/lib_debug.sh) + Integrated EPOCH in PS4. * **Changed**: [lib_debug.sh](../lib/lib_debug.sh) + Integrated EPOCH in PS4.
* **Changed**: [lib_debug_header.sh](../lib/lib_debug_header.sh) + Integrated SOURCE_DATE_EPOCH. * **Changed**: [lib_debug_header.sh](../lib/lib_debug_header.sh) + Integrated SOURCE_DATE_EPOCH.
* **Changed**: [lib_hardening_root_pw.sh](../lib/lib_hardening_root_pw.sh) Unified UI. * **Changed**: [lib_hardening_root_pw.sh](../lib/lib_hardening_root_pw.sh) Unified UI.
* **Changed**: [lib_hardening_ultra.sh](../lib/lib_hardening_ultra.sh) Rewritten for CISS and PhysNet primordial-workflow™. * **Changed**: [lib_hardening_ultra.sh](../lib/lib_hardening_ultra.sh) Rewritten for CISS and PhysNet Primordial-Workflow™.
* **Changed**: [lib_hardening_ssh_tcp.sh](../lib/lib_hardening_ssh_tcp.sh) Unified UI. * **Changed**: [lib_hardening_ssh_tcp.sh](../lib/lib_hardening_ssh_tcp.sh) Unified UI.
* **Changed**: [lib_lb_build_start.sh](../lib/lib_lb_build_start.sh) Deterministic return code examination. * **Changed**: [lib_lb_build_start.sh](../lib/lib_lb_build_start.sh) Deterministic return code examination.
* **Changed**: [lib_lb_config_start.sh](../lib/lib_lb_config_start.sh) Removed potential disown race condition. * **Changed**: [lib_lb_config_start.sh](../lib/lib_lb_config_start.sh) Removed potential disown race condition.
@@ -254,11 +260,11 @@ include_toc: true
## V8.13.290.2025.10.26 ## V8.13.290.2025.10.26
* **Updated**: [0001_initramfs_modules.chroot](../config/hooks/live/0001_initramfs_modules.chroot) + ESP/FAT/UEFI mods * **Updated**: [0001_initramfs_modules.chroot](../config/hooks/live/0001_initramfs_modules.chroot) + ESP/FAT/UEFI mods
* **Updated**: [9950_hardening_fail2ban.chroot](../config/hooks/live/9950_hardening_fail2ban.chroot) * **Updated**: [9950_hardening_fail2ban.chroot](../config/hooks/live/9950_hardening_fail2ban.chroot)
* **Updated**: [9999-cdi-starter](../scripts/usr/local/sbin/9999_cdi_starter.sh) Preparations for CISS and PhysNet primordial-workflow™. * **Updated**: [9999-cdi-starter](../scripts/usr/local/sbin/9999_cdi_starter.sh) Preparations for CISS and PhysNet Primordial-Workflow™.
## V8.13.288.2025.10.24 ## V8.13.288.2025.10.24
* **Added**: Preparations for CISS and PhysNet primordial-workflow™. * **Added**: Preparations for CISS and PhysNet Primordial-Workflow™.
* **Added**: [0865_yq.chroot](../config/hooks/live/0865_yq.chroot)Preparations for CISS and PhysNet primordial-workflow™. * **Added**: [0865_yq.chroot](../config/hooks/live/0865_yq.chroot)Preparations for CISS and PhysNet Primordial-Workflow™.
* **Updated**: [0001_initramfs_modules.chroot](../config/hooks/live/0001_initramfs_modules.chroot) + nftables mods * **Updated**: [0001_initramfs_modules.chroot](../config/hooks/live/0001_initramfs_modules.chroot) + nftables mods
* **Updated**: [9950_hardening_fail2ban.chroot](../config/hooks/live/9950_hardening_fail2ban.chroot) + banaction = nftables-* * **Updated**: [9950_hardening_fail2ban.chroot](../config/hooks/live/9950_hardening_fail2ban.chroot) + banaction = nftables-*
* **Updated**: [0900_ufw_setup.chroot](../config/hooks/live/0900_ufw_setup.chroot) changed var injection * **Updated**: [0900_ufw_setup.chroot](../config/hooks/live/0900_ufw_setup.chroot) changed var injection
+1 -1
View File
@@ -8,7 +8,7 @@ include_toc: true
**Centurion Intelligence Consulting Agency Information Security Standard**<br> **Centurion Intelligence Consulting Agency Information Security Standard**<br>
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br> *Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
**Master Version**: 9.14<br> **Master Version**: 9.14<br>
**Build**: V9.14.020.2026.06.08<br> **Build**: V9.14.022.2026.06.10<br>
# 2. Centurion Net - Developer Branch Overview # 2. Centurion Net - Developer Branch Overview
+1 -1
View File
@@ -8,7 +8,7 @@ include_toc: true
**Centurion Intelligence Consulting Agency Information Security Standard**<br> **Centurion Intelligence Consulting Agency Information Security Standard**<br>
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br> *Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
**Master Version**: 9.14<br> **Master Version**: 9.14<br>
**Build**: V9.14.020.2026.06.08<br> **Build**: V9.14.022.2026.06.10<br>
# 2. Purpose # 2. Purpose
+1 -1
View File
@@ -8,7 +8,7 @@ include_toc: true
**Centurion Intelligence Consulting Agency Information Security Standard**<br> **Centurion Intelligence Consulting Agency Information Security Standard**<br>
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br> *Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
**Master Version**: 9.14<br> **Master Version**: 9.14<br>
**Build**: V9.14.020.2026.06.08<br> **Build**: V9.14.022.2026.06.10<br>
# 2. Contributing / participating # 2. Contributing / participating
+1 -1
View File
@@ -8,7 +8,7 @@ include_toc: true
**Centurion Intelligence Consulting Agency Information Security Standard**<br> **Centurion Intelligence Consulting Agency Information Security Standard**<br>
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br> *Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
**Master Version**: 9.14<br> **Master Version**: 9.14<br>
**Build**: V9.14.020.2026.06.08<br> **Build**: V9.14.022.2026.06.10<br>
# 2. Credits # 2. Credits
+1 -1
View File
@@ -8,7 +8,7 @@ include_toc: true
**Centurion Intelligence Consulting Agency Information Security Standard**<br> **Centurion Intelligence Consulting Agency Information Security Standard**<br>
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br> *Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
**Master Version**: 9.14<br> **Master Version**: 9.14<br>
**Build**: V9.14.020.2026.06.08<br> **Build**: V9.14.022.2026.06.10<br>
# 2. Download the latest PUBLIC CISS.debian.live.ISO # 2. Download the latest PUBLIC CISS.debian.live.ISO
+34 -5
View File
@@ -8,14 +8,14 @@ include_toc: true
**Centurion Intelligence Consulting Agency Information Security Standard**<br> **Centurion Intelligence Consulting Agency Information Security Standard**<br>
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br> *Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
**Master Version**: 9.14<br> **Master Version**: 9.14<br>
**Build**: V9.14.020.2026.06.08<br> **Build**: V9.14.022.2026.06.10<br>
# 2.1. Usage # 2.1. Usage
````text ````text
CDLB(1) CISS.debian.live.builder CDLB(1) CDLB(1) CISS.debian.live.builder CDLB(1)
CISS.debian.live.builder from https://git.coresecret.dev/msw CISS.debian.live.builder from https://git.coresecret.dev/msw
Master V9.14.020.2026.06.08 Master V9.14.022.2026.06.10
A lightweight Shell Wrapper for building a hardened Debian Live ISO Image. A lightweight Shell Wrapper for building a hardened Debian Live ISO Image.
(c) Marc S. Weidner, 2018 - 2026 (c) Marc S. Weidner, 2018 - 2026
@@ -37,6 +37,10 @@ A lightweight Shell Wrapper for building a hardened Debian Live ISO Image.
--build-directory </path/to/build_directory> --build-directory </path/to/build_directory>
Where the Debian Live Build Image should be generated. RECOMMENDED path: </opt/cdlb> Where the Debian Live Build Image should be generated. RECOMMENDED path: </opt/cdlb>
The path MUST be canonical and dedicated to the builder; a new directory's canonical parent MUST already exist.
New or empty directories receive the
'.ciss-live-builder-owned' marker; populated unmarked directories are rejected. Cleanup is intentionally destructive
only inside the exact validated marker-owned directory.
MUST be provided. MUST be provided.
--change-splash <STRING> one of <club | hexagon> --change-splash <STRING> one of <club | hexagon>
@@ -57,6 +61,7 @@ A lightweight Shell Wrapper for building a hardened Debian Live ISO Image.
--debug, -d --debug, -d
Enables debug logging for the main program routine. Detailed logging information are written to: Enables debug logging for the main program routine. Detailed logging information are written to:
</tmp/ciss_live_builder_1801049.log> </tmp/ciss_live_builder_1801049.log>
A final exact-value sanitisation pass is defence in depth and does not replace careful tracing discipline.
--dhcp-centurion --dhcp-centurion
If a DHCP lease is provided, the provider's name server will be overridden and the hardened, privacy-focused If a DHCP lease is provided, the provider's name server will be overridden and the hardened, privacy-focused
@@ -86,11 +91,13 @@ A lightweight Shell Wrapper for building a hardened Debian Live ISO Image.
--key_age=* --key_age=*
The SOPS AGE private keyring for decryption operations. Change '*' to your desired SOPS AGE key file. The SOPS AGE private keyring for decryption operations. Change '*' to your desired SOPS AGE key file.
'*' MUST be a filename only without slashes, '.' or '..' traversal.
File MUST be placed in: File MUST be placed in:
</dev/shm/cdlb_secrets> </dev/shm/cdlb_secrets>
--key_luks=* --key_luks=*
The LUKS encryption / decryption passphrase for '/'-fs-encryption. Change '*' to your desired passphrase file. The LUKS encryption / decryption passphrase for '/'-fs-encryption. Change '*' to your desired passphrase file.
'*' MUST be a filename only without slashes, '.' or '..' traversal.
File MUST be placed in: File MUST be placed in:
</dev/shm/cdlb_secrets> </dev/shm/cdlb_secrets>
@@ -98,6 +105,24 @@ A lightweight Shell Wrapper for building a hardened Debian Live ISO Image.
Provides statistic only after successful building a CISS.debian.live-ISO. While enabling '--log-statistics-only' Provides statistic only after successful building a CISS.debian.live-ISO. While enabling '--log-statistics-only'
the argument '--build-directory' MUST be provided. the argument '--build-directory' MUST be provided.
--primordial-key <ssh-identity-filename>
SSH identity filename for the Primordial overlay clone. This MUST be a filename only; the runtime path is derived as
'/root/.ssh/<ssh-identity-filename>'.
Example fragment:
./ciss_live_builder.sh --primordial-url https://git.coresecret.dev/ahz/PhysNet.primordial.git \
--primordial-key id--git.coresecret.dev--PhysNet.primordial_deploy--ed25519--newton--2025-10 \
--primordial-ssh 42842
--primordial-ssh <INTEGER>
Adds one outgoing UFW TCP exception for a bootstrap/recovery SSH port.
Outgoing only: no incoming firewall rule is added, and this option does not replace '--ssh-port'.
Effective only when the Live System's UFW outgoing policy is 'deny'.
Port MUST be a decimal integer between '1' and '65535'.
--primordial-url <https-git-url>
HTTPS Git repository URL for the Primordial CDI overlay. MUST start with 'https://', include a host and path, and end in
'.git'. The CDI starter converts this URL to an SSH clone URL at runtime.
--provider-netcup-ipv6 --provider-netcup-ipv6
Activates IPv6 support for Netcup Root Server. One unique IPv6 address MUST be provided in this case and MUST be Activates IPv6 support for Netcup Root Server. One unique IPv6 address MUST be provided in this case and MUST be
encapsulated with [], e.g., [1234::abcd]. encapsulated with [], e.g., [1234::abcd].
@@ -122,7 +147,7 @@ A lightweight Shell Wrapper for building a hardened Debian Live ISO Image.
--root-password-file </dev/shm/cdlb_secrets/password.txt>> --root-password-file </dev/shm/cdlb_secrets/password.txt>>
Password file for 'root', if given, MUST be a string of 42 to 64 characters. Password file for 'root', if given, MUST be a string of 42 to 64 characters.
If the argument is omitted, no further login authentication is required for the local console. If the argument is omitted, no further login authentication is required for the local console.
MUST be placed in: Safe absolute paths remain supported and are validated separately. RECOMMENDED path:
</dev/shm/cdlb_secrets/password.txt> </dev/shm/cdlb_secrets/password.txt>
--secure-boot-profile <STRING> one of <debian-shim | ciss-uki> --secure-boot-profile <STRING> one of <debian-shim | ciss-uki>
@@ -138,7 +163,8 @@ A lightweight Shell Wrapper for building a hardened Debian Live ISO Image.
specified via '--signing_key=*'. If the keyring is protected, then provide the passphrase in its own file. specified via '--signing_key=*'. If the keyring is protected, then provide the passphrase in its own file.
Specify the fingerprint of the key to use via '--signing_key_fpr=*'. Specify the fingerprint of the key to use via '--signing_key_fpr=*'.
Optionally import an offline GPG CA signing public key via: '--signing_ca=*'. Optionally import an offline GPG CA signing public key via: '--signing_ca=*'.
Change '*' to your desired files / fingerprint. Files MUST be placed in: Change '*' to your desired filename-only files / fingerprint. Filename-only values MUST NOT contain slashes or traversal.
Files MUST be placed in:
</dev/shm/cdlb_secrets> </dev/shm/cdlb_secrets>
--sshfp --sshfp
@@ -164,11 +190,14 @@ A lightweight Shell Wrapper for building a hardened Debian Live ISO Image.
💡 Notes: 💡 Notes:
🔵 You MUST be 'root' to run this script. 🔵 You MUST be 'root' to run this script.
🔵 Private operator control does not remove the requirement for strict local secret path validation.
🔵 '/dev/shm/cdlb_secrets' MUST be tmpfs-backed, root-owned, mode 0700, and contain only single-link regular non-symlink files
with mode 0400 or 0600. Secure deletion with shred is best-effort only on modern storage.
💷 Please consider donating to my work at: 💷 Please consider donating to my work at:
🌐 https://coresecret.eu/spenden/ 🌐 https://coresecret.eu/spenden/
V9.14.020.2026.06.08 2026-05-17 CDLB(1) V9.14.022.2026.06.10 2026-05-17 CDLB(1)
```` ````
# 3. Booting # 3. Booting
+1 -1
View File
@@ -8,7 +8,7 @@ include_toc: true
**Centurion Intelligence Consulting Agency Information Security Standard**<br> **Centurion Intelligence Consulting Agency Information Security Standard**<br>
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br> *Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
**Master Version**: 9.14<br> **Master Version**: 9.14<br>
**Build**: V9.14.020.2026.06.08<br> **Build**: V9.14.022.2026.06.10<br>
# 2. CISS.debian.live.builder Boot & Trust Chain (Technical Documentation) # 2. CISS.debian.live.builder Boot & Trust Chain (Technical Documentation)
+1 -1
View File
@@ -8,7 +8,7 @@ include_toc: true
**Centurion Intelligence Consulting Agency Information Security Standard**<br> **Centurion Intelligence Consulting Agency Information Security Standard**<br>
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br> *Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
**Master Version**: 9.14<br> **Master Version**: 9.14<br>
**Build**: V9.14.020.2026.06.08<br> **Build**: V9.14.022.2026.06.10<br>
# 2. SSH Host Key Policy CISS.debian.live.builder / CISS.debian.installer # 2. SSH Host Key Policy CISS.debian.live.builder / CISS.debian.installer
+1 -1
View File
@@ -8,7 +8,7 @@ include_toc: true
**Centurion Intelligence Consulting Agency Information Security Standard**<br> **Centurion Intelligence Consulting Agency Information Security Standard**<br>
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br> *Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
**Master Version**: 9.14<br> **Master Version**: 9.14<br>
**Build**: V9.14.020.2026.06.08<br> **Build**: V9.14.022.2026.06.10<br>
# 2. Resources # 2. Resources
+1 -1
View File
@@ -8,7 +8,7 @@ include_toc: true
**Centurion Intelligence Consulting Agency Information Security Standard**<br> **Centurion Intelligence Consulting Agency Information Security Standard**<br>
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br> *Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
**Master Version**: 9.14<br> **Master Version**: 9.14<br>
**Build**: V9.14.020.2026.06.08<br> **Build**: V9.14.022.2026.06.10<br>
# 2. ``30-ciss-hardening.conf`` # 2. ``30-ciss-hardening.conf``
+1 -1
View File
@@ -8,7 +8,7 @@ include_toc: true
**Centurion Intelligence Consulting Agency Information Security Standard**<br> **Centurion Intelligence Consulting Agency Information Security Standard**<br>
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br> *Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
**Master Version**: 9.14<br> **Master Version**: 9.14<br>
**Build**: V9.14.020.2026.06.08<br> **Build**: V9.14.022.2026.06.10<br>
# 2. ``90-ciss-local.hardened`` # 2. ``90-ciss-local.hardened``
+1 -1
View File
@@ -8,7 +8,7 @@ include_toc: true
**Centurion Intelligence Consulting Agency Information Security Standard**<br> **Centurion Intelligence Consulting Agency Information Security Standard**<br>
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br> *Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
**Master Version**: 9.14<br> **Master Version**: 9.14<br>
**Build**: V9.14.020.2026.06.08<br> **Build**: V9.14.022.2026.06.10<br>
# 2. ``ciss_live_builder.sh`` # 2. ``ciss_live_builder.sh``
+125 -50
View File
@@ -38,6 +38,9 @@ guard_sourcing || return "${ERR_GUARD_SRCE}"
# VAR_ISO8601 # VAR_ISO8601
# VAR_LUKS # VAR_LUKS
# VAR_LUKS_KEY # VAR_LUKS_KEY
# VAR_PRIMORDIAL_KEY
# VAR_PRIMORDIAL_SSH_PORT
# VAR_PRIMORDIAL_URL
# VAR_REIONICE_CLASS # VAR_REIONICE_CLASS
# VAR_REIONICE_PRIORITY # VAR_REIONICE_PRIORITY
# VAR_SIGNER # VAR_SIGNER
@@ -54,25 +57,25 @@ guard_sourcing || return "${ERR_GUARD_SRCE}"
# None # None
# Returns: # Returns:
# ERR_ARG_MSMTCH: on failure # ERR_ARG_MSMTCH: on failure
# ERR_ARG_MSMTCH: on failure # ERR_BUILD_PATH: on failure
# ERR_CONTROL_CT: on failure # ERR_CONTROL_CT: on failure
# ERR_DROPBEAR_V: on failure # ERR_DROPBEAR_V: on failure
# ERR_MISS_PWD_F: on failure
# ERR_MISS_PWD_P: on failure # ERR_MISS_PWD_P: on failure
# ERR_NOTABSPATH: on failure
# ERR_OWNS_PWD_F: on failure
# ERR_PASS_LENGH: on failure # ERR_PASS_LENGH: on failure
# ERR_PASS_PLICY: on failure # ERR_PASS_PLICY: on failure
# ERR_REIONICE_P: on failure # ERR_REIONICE_P: on failure
# ERR_REIO_C_VAL: on failure # ERR_REIO_C_VAL: on failure
# ERR_REIO_P_VAL: on failure # ERR_REIO_P_VAL: on failure
# ERR_RENICE_PRI: on failure # ERR_RENICE_PRI: on failure
# ERR_RGHT_PWD_F: on failure # ERR_SECRET_PATH: on failure
# ERR_SPLASH_PNG: on failure # ERR_SPLASH_PNG: on failure
# ERR__SOPS__VER: on failure # ERR__SOPS__VER: on failure
# ERR__SSH__PORT: on failure # ERR__SSH__PORT: on failure
####################################### #######################################
arg_parser() { arg_parser() {
declare primordial_key_regex='^[A-Za-z0-9._@%+=:,~-]+$'
declare primordial_url_regex='^https://[A-Za-z0-9.-]+/[A-Za-z0-9._~/%+=:@,-]+\.git$'
while [[ $# -gt 0 ]]; do while [[ $# -gt 0 ]]; do
declare argument="${1}" declare argument="${1}"
@@ -128,12 +131,9 @@ arg_parser() {
;; ;;
--build-directory) --build-directory)
declare -gx VAR_HANDLER_BUILD_DIR="${2}" declare build_directory="${2-}"
if [[ ! "${VAR_HANDLER_BUILD_DIR}" =~ ^/ ]]; then validate_build_directory_path "${build_directory}" build_directory || exit "${ERR_BUILD_PATH}"
if ! ${VAR_HANDLER_AUTOBUILD}; then boot_screen_cleaner; fi declare -gx VAR_HANDLER_BUILD_DIR="${build_directory}"
printf "\e[91m❌ Error: --build-directory MUST be an absolute path. Got: '%s'\n" "${VAR_HANDLER_BUILD_DIR}" >&2
exit "${ERR_NOTABSPATH}"
fi
declare -gx VAR_BUILD_LOG="${VAR_HANDLER_BUILD_DIR}/cdlb_${VAR_ISO8601}_build.log" declare -gx VAR_BUILD_LOG="${VAR_HANDLER_BUILD_DIR}/cdlb_${VAR_ISO8601}_build.log"
shift 2 shift 2
;; ;;
@@ -260,18 +260,22 @@ arg_parser() {
;; ;;
--key_age=*) --key_age=*)
declare age_key="${1#*=}"
validate_secret_file_in_root "${age_key}" "SOPS Age key" || exit "${ERR_SECRET_PATH}"
# shellcheck disable=SC2034 # shellcheck disable=SC2034
declare -gx VAR_AGE="true" declare -gx VAR_AGE="true"
# shellcheck disable=SC2034 # shellcheck disable=SC2034
declare -gx VAR_AGE_KEY="${1#*=}" declare -gx VAR_AGE_KEY="${age_key}"
shift 1 shift 1
;; ;;
--key_luks=*) --key_luks=*)
declare luks_key="${1#*=}"
validate_secret_file_in_root "${luks_key}" "LUKS key file" || exit "${ERR_SECRET_PATH}"
# shellcheck disable=SC2034 # shellcheck disable=SC2034
declare -gx VAR_LUKS="true" declare -gx VAR_LUKS="true"
# shellcheck disable=SC2034 # shellcheck disable=SC2034
declare -gx VAR_LUKS_KEY="${1#*=}" declare -gx VAR_LUKS_KEY="${luks_key}"
shift 1 shift 1
;; ;;
@@ -287,6 +291,99 @@ arg_parser() {
shift 1 shift 1
;; ;;
--primordial-key)
declare primordial_key="${2-}"
if [[ -n "${primordial_key}" && "${primordial_key}" != -* && "${primordial_key}" != "." && "${primordial_key}" != ".." && "${primordial_key}" != */* && "${primordial_key}" =~ ${primordial_key_regex} ]]; then
# shellcheck disable=SC2034
declare -gx VAR_PRIMORDIAL_KEY="${primordial_key}"
shift 2
else
if ! ${VAR_HANDLER_AUTOBUILD}; then boot_screen_cleaner; fi
printf "\e[91m❌ Error: --primordial-key MUST be a filename matching '^[A-Za-z0-9._@%%+=:,~-]+$' and MUST NOT be '.', '..', or contain '/'.\e[0m\n" >&2
read -p -r $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m'
exit "${ERR_ARG_MSMTCH}"
fi
;;
--primordial-key=*)
declare primordial_key="${1#*=}"
if [[ -n "${primordial_key}" && "${primordial_key}" != "." && "${primordial_key}" != ".." && "${primordial_key}" != */* && "${primordial_key}" =~ ${primordial_key_regex} ]]; then
# shellcheck disable=SC2034
declare -gx VAR_PRIMORDIAL_KEY="${primordial_key}"
shift 1
else
if ! ${VAR_HANDLER_AUTOBUILD}; then boot_screen_cleaner; fi
printf "\e[91m❌ Error: --primordial-key MUST be a filename matching '^[A-Za-z0-9._@%%+=:,~-]+$' and MUST NOT be '.', '..', or contain '/'.\e[0m\n" >&2
read -p -r $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m'
exit "${ERR_ARG_MSMTCH}"
fi
;;
--primordial-ssh)
if [[ -n "${2-}" && "${2}" =~ ^-?[0-9]+$ && "${2}" -ge 1 && "${2}" -le 65535 ]]; then
# shellcheck disable=SC2034
declare -gix VAR_PRIMORDIAL_SSH_PORT="${2}"
shift 2
else
if ! ${VAR_HANDLER_AUTOBUILD}; then boot_screen_cleaner; fi
printf "\e[91m❌ Error: --primordial-ssh MUST be an integer between '1' and '65535'.\e[0m\n" >&2
read -p -r $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m'
exit "${ERR__SSH__PORT}"
fi
;;
--primordial-url)
declare primordial_url="${2-}"
if [[ -n "${primordial_url}" && "${primordial_url}" != -* && "${primordial_url}" =~ ${primordial_url_regex} ]]; then
# shellcheck disable=SC2034
declare -gx VAR_PRIMORDIAL_URL="${primordial_url}"
shift 2
else
if ! ${VAR_HANDLER_AUTOBUILD}; then boot_screen_cleaner; fi
printf "\e[91m❌ Error: --primordial-url MUST be an HTTPS Git URL with non-empty host, non-empty path, and '.git' suffix.\e[0m\n" >&2
read -p -r $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m'
exit "${ERR_ARG_MSMTCH}"
fi
;;
--primordial-url=*)
declare primordial_url="${1#*=}"
if [[ -n "${primordial_url}" && "${primordial_url}" =~ ${primordial_url_regex} ]]; then
# shellcheck disable=SC2034
declare -gx VAR_PRIMORDIAL_URL="${primordial_url}"
shift 1
else
if ! ${VAR_HANDLER_AUTOBUILD}; then boot_screen_cleaner; fi
printf "\e[91m❌ Error: --primordial-url MUST be an HTTPS Git URL with non-empty host, non-empty path, and '.git' suffix.\e[0m\n" >&2
read -p -r $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m'
exit "${ERR_ARG_MSMTCH}"
fi
;;
--provider-netcup-ipv6) --provider-netcup-ipv6)
if [[ -n "${2-}" && "${2}" != -* ]]; then if [[ -n "${2-}" && "${2}" != -* ]]; then
declare -i count=0 declare -i count=0
@@ -374,39 +471,7 @@ arg_parser() {
fi fi
if [[ ! -f "${pw_file}" ]]; then validate_secret_absolute_file "${pw_file}" "root password file" || exit "${ERR_SECRET_PATH}"
if ! ${VAR_HANDLER_AUTOBUILD}; then boot_screen_cleaner; fi
printf "\e[91m❌ Error: --root-password-file password file '%s' does not exist.\e[0m\n" "${pw_file}" >&2
# shellcheck disable=SC2162
read -p $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m'
exit "${ERR_MISS_PWD_F}"
fi
declare owner
owner=$(stat -c '%U:%G' "${pw_file}")
if [[ "${owner}" != "root:root" ]]; then
chown root:root "${pw_file}" || {
if ! ${VAR_HANDLER_AUTOBUILD}; then boot_screen_cleaner; fi
printf "\e[91m❌ Error: --root-password-file failed to set owner root:root on '%s'.\e[0m\n" "${pw_file}" >&2
# shellcheck disable=SC2162
read -p $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m'
exit "${ERR_OWNS_PWD_F}"
}
fi
declare perms
perms=$(stat -c '%a' "${pw_file}")
if [[ "${perms}" -ne 400 ]]; then
chmod 0400 "${pw_file}" || {
if ! ${VAR_HANDLER_AUTOBUILD}; then boot_screen_cleaner; fi
printf "\e[91m❌ Error: --root-password-file failed to set permissions 0400 on '%s'.\e[0m\n" "${pw_file}" >&2
# shellcheck disable=SC2162
read -p $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m'
exit "${ERR_RGHT_PWD_F}"
}
fi
declare plaintext_pw declare plaintext_pw
### No tracing for security reasons ---------------------------------------------------------------------------------- ### No tracing for security reasons ----------------------------------------------------------------------------------
@@ -459,6 +524,7 @@ arg_parser() {
[[ "${VAR_EARLY_DEBUG}" == "true" ]] && set +x [[ "${VAR_EARLY_DEBUG}" == "true" ]] && set +x
hash_temp=$(mkpasswd --method=sha-512 --salt="${salt}" --rounds=8388608 "${plaintext_pw}") hash_temp=$(mkpasswd --method=sha-512 --salt="${salt}" --rounds=8388608 "${plaintext_pw}")
register_secret_value "${hash_temp}"
### Turn on tracing again -------------------------------------------------------------------------------------------- ### Turn on tracing again --------------------------------------------------------------------------------------------
[[ "${VAR_EARLY_DEBUG}" == "true" ]] && set -x [[ "${VAR_EARLY_DEBUG}" == "true" ]] && set -x
@@ -507,16 +573,20 @@ arg_parser() {
;; ;;
--signing_ca=*) --signing_ca=*)
declare signing_ca="${1#*=}"
validate_secret_file_in_root "${signing_ca}" "signing CA file" || exit "${ERR_SECRET_PATH}"
# shellcheck disable=SC2034 # shellcheck disable=SC2034
declare -gx VAR_SIGNING_CA="${1#*=}" declare -gx VAR_SIGNING_CA="${signing_ca}"
shift 1 shift 1
;; ;;
--signing_key=*) --signing_key=*)
declare signing_key="${1#*=}"
validate_secret_file_in_root "${signing_key}" "signing key file" || exit "${ERR_SECRET_PATH}"
# shellcheck disable=SC2034 # shellcheck disable=SC2034
declare -gx VAR_SIGNER="true" declare -gx VAR_SIGNER="true"
# shellcheck disable=SC2034 # shellcheck disable=SC2034
declare -gx VAR_SIGNING_KEY="${1#*=}" declare -gx VAR_SIGNING_KEY="${signing_key}"
shift 1 shift 1
;; ;;
@@ -527,8 +597,10 @@ arg_parser() {
;; ;;
--signing_key_pass=*) --signing_key_pass=*)
declare signing_key_pass="${1#*=}"
validate_secret_file_in_root "${signing_key_pass}" "signing passphrase file" || exit "${ERR_SECRET_PATH}"
# shellcheck disable=SC2034 # shellcheck disable=SC2034
declare -gx VAR_SIGNING_KEY_PASS="${1#*=}" declare -gx VAR_SIGNING_KEY_PASS="${signing_key_pass}"
shift 1 shift 1
;; ;;
@@ -595,8 +667,11 @@ arg_parser() {
;; ;;
--ssh-pubkey) --ssh-pubkey)
declare ssh_pubkey_dir="${2-}"
validate_secret_absolute_directory "${ssh_pubkey_dir}" "SSH public-key directory" || exit "${ERR_SECRET_PATH}"
validate_secret_file "${ssh_pubkey_dir}/authorized_keys" "SSH authorized_keys file" || exit "${ERR_SECRET_PATH}"
# shellcheck disable=SC2034 # shellcheck disable=SC2034
declare -gx VAR_SSHPUBKEY="${2}" declare -gx VAR_SSHPUBKEY="${ssh_pubkey_dir}"
shift 2 shift 2
;; ;;
+340
View File
@@ -0,0 +1,340 @@
#!/bin/bash
# SPDX-Version: 3.0
# SPDX-CreationInfo: 2026-06-11; WEIDNER, Marc S.; <msw@coresecret.dev>
# SPDX-ExternalRef: GIT https://git.coresecret.dev/msw/CISS.debian.live.builder.git
# SPDX-FileContributor: WEIDNER, Marc S.; Centurion Intelligence Consulting Agency
# SPDX-FileCopyrightText: 2024-2026; WEIDNER, Marc S.; <msw@coresecret.dev>
# SPDX-FileType: SOURCE
# SPDX-License-Identifier: LicenseRef-CNCL-1.1 OR LicenseRef-CCLA-1.1
# SPDX-LicenseComment: This file is part of the CISS.debian.installer.secure framework.
# SPDX-PackageName: CISS.debian.live.builder
# SPDX-Security-Contact: security@coresecret.eu
guard_sourcing || return "${ERR_GUARD_SRCE}"
#######################################
# Prints a generic build-directory validation error without disclosing a path.
# Arguments:
# 1: unsafe input class
# 2: quiet flag
# Returns:
# ERR_BUILD_PATH
#######################################
build_directory_validation_error() {
declare error_class="$1" quiet="${2:-false}"
if [[ "${quiet}" != "true" ]]; then
printf "\e[91m❌ Unsafe build-directory input rejected: %s. \e[0m\n" "${error_class}" >&2
fi
return "${ERR_BUILD_PATH:-217}"
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f build_directory_validation_error
#######################################
# Canonicalises an existing path or a path whose parent exists.
# Arguments:
# 1: candidate path
# 2: output variable name
# Returns:
# 0: on success
# ERR_BUILD_PATH: on failure
#######################################
canonicalize_build_directory() {
declare candidate="$1" output_variable="$2" basename="" parent="" resolved_path=""
[[ -n "${candidate}" && "${candidate}" == /* ]] || return "${ERR_BUILD_PATH:-217}"
[[ "${candidate}" == "/" ]] || candidate="${candidate%/}"
[[ ! -L "${candidate}" ]] || return "${ERR_BUILD_PATH:-217}"
if [[ -e "${candidate}" ]]; then
resolved_path="$(realpath "${candidate}" 2>/dev/null)" || return "${ERR_BUILD_PATH:-217}"
else
basename="${candidate##*/}"
parent="${candidate%/*}"
[[ -n "${parent}" ]] || parent="/"
[[ -n "${basename}" && "${basename}" != "." && "${basename}" != ".." && -d "${parent}" ]] || return "${ERR_BUILD_PATH:-217}"
resolved_path="$(realpath "${parent}" 2>/dev/null)" || return "${ERR_BUILD_PATH:-217}"
resolved_path="${resolved_path%/}/${basename}"
fi
[[ "${candidate}" == "${resolved_path}" ]] || return "${ERR_BUILD_PATH:-217}"
printf -v "${output_variable}" '%s' "${resolved_path}"
return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f canonicalize_build_directory
#######################################
# Validates a build directory against the repository cleanup policy.
# Globals:
# VAR_TMP_SECRET
# VAR_WORKDIR
# Arguments:
# 1: candidate path
# 2: output variable name
# 3: quiet flag
# Returns:
# 0: on success
# ERR_BUILD_PATH: on failure
#######################################
validate_build_directory_path() {
declare candidate="$1" output_variable="${2:-}" quiet="${3:-false}" secret_root="" validated_path="" workdir=""
declare -a rejected_paths=(
"/" "/bin" "/boot" "/dev" "/etc" "/home" "/lib" "/lib64" "/media" "/mnt" "/opt" "/proc" "/root" "/run" "/sbin" "/srv"
"/sys" "/tmp" "/usr" "/usr/local" "/var" "/var/lib" "/var/tmp"
)
declare rejected_path=""
canonicalize_build_directory "${candidate}" validated_path || {
build_directory_validation_error \
"path is empty, non-absolute, non-canonical, missing its parent, or is a symlink" "${quiet}"
return "${ERR_BUILD_PATH:-217}"
}
for rejected_path in "${rejected_paths[@]}"; do
if [[ "${validated_path}" == "${rejected_path}" ]]; then
build_directory_validation_error "broad or system parent directory" "${quiet}"
return "${ERR_BUILD_PATH:-217}"
fi
done
workdir="$(realpath "${VAR_WORKDIR}" 2>/dev/null)" || {
build_directory_validation_error "repository work directory cannot be resolved" "${quiet}"
return "${ERR_BUILD_PATH:-217}"
}
secret_root="$(realpath "${VAR_TMP_SECRET}" 2>/dev/null)" || {
build_directory_validation_error "secret root cannot be resolved" "${quiet}"
return "${ERR_BUILD_PATH:-217}"
}
if [[ "${workdir}" == "${validated_path}" || "${workdir}" == "${validated_path}/"* || "${validated_path}" == "${workdir}/"* \
|| "${validated_path}" == "${secret_root}" || "${validated_path}" == "${secret_root}/"* ]]; then
build_directory_validation_error "path is outside the dedicated build-directory policy" "${quiet}"
return "${ERR_BUILD_PATH:-217}"
fi
if [[ -n "${output_variable}" ]]; then
printf -v "${output_variable}" '%s' "${validated_path}"
fi
return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f validate_build_directory_path
#######################################
# Validates the builder-owned marker for an exact build directory.
# Globals:
# EUID
# Arguments:
# 1: candidate path
# 2: quiet flag
# Returns:
# 0: on success
# ERR_BUILD_PATH: on failure
#######################################
validate_build_directory_marker() {
declare candidate="$1" quiet="${2:-false}" directory_mode="" directory_owner="" marker="" marker_build_dir=""
declare expected_marker_value="" marker_link_count="" marker_value="" mode="" owner=""
validate_build_directory_path "${candidate}" marker_build_dir "${quiet}" || return "${ERR_BUILD_PATH:-217}"
[[ -d "${marker_build_dir}" ]] || {
build_directory_validation_error "build directory does not exist" "${quiet}"
return "${ERR_BUILD_PATH:-217}"
}
directory_owner="$(secure_stat -c '%u' "${marker_build_dir}" 2>/dev/null)" || return "${ERR_BUILD_PATH:-217}"
directory_mode="$(secure_stat -c '%a' "${marker_build_dir}" 2>/dev/null)" || return "${ERR_BUILD_PATH:-217}"
if [[ "${directory_owner}" != "${EUID}" ]] || (( (8#${directory_mode} & 022) != 0 )); then
build_directory_validation_error "build directory ownership or permissions are unsafe" "${quiet}"
return "${ERR_BUILD_PATH:-217}"
fi
marker="${marker_build_dir}/.ciss-live-builder-owned"
if [[ -L "${marker}" || ! -f "${marker}" ]]; then
build_directory_validation_error "builder-owned marker is missing or unsafe" "${quiet}"
return "${ERR_BUILD_PATH:-217}"
fi
owner="$(secure_stat -c '%u' "${marker}" 2>/dev/null)" || return "${ERR_BUILD_PATH:-217}"
mode="$(secure_stat -c '%a' "${marker}" 2>/dev/null)" || return "${ERR_BUILD_PATH:-217}"
marker_link_count="$(secure_stat -c '%h' "${marker}" 2>/dev/null)" || return "${ERR_BUILD_PATH:-217}"
marker_value="$(cat "${marker}" || exit $?; printf '.')" || return "${ERR_BUILD_PATH:-217}"
marker_value="${marker_value%.}"
expected_marker_value="${marker_build_dir}"$'\n'
if [[ "${owner}" != "${EUID}" || "${mode}" != "400" || "${marker_link_count}" != "1" \
|| "${marker_value}" != "${expected_marker_value}" ]]; then
build_directory_validation_error "builder-owned marker does not match the exact directory" "${quiet}"
return "${ERR_BUILD_PATH:-217}"
fi
return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f validate_build_directory_marker
#######################################
# Validates an existing exact subpath below a marker-owned build directory.
# Arguments:
# 1: build directory
# 2: relative subpath
# 3: output variable name
# 4: quiet flag
# Returns:
# 0: on success
# ERR_BUILD_PATH: on failure
#######################################
validate_build_directory_subpath() {
declare build_directory="$1" relative_path="$2" output_variable="$3" quiet="${4:-false}"
declare candidate_subpath="" resolved_subpath=""
validate_build_directory_marker "${build_directory}" "${quiet}" || return "${ERR_BUILD_PATH:-217}"
if [[ -z "${relative_path}" || "${relative_path}" == /* || "${relative_path}" == "." || "${relative_path}" == ".." \
|| "${relative_path}" == ../* || "${relative_path}" == */../* || "${relative_path}" == */.. \
|| "${relative_path}" == ./* || "${relative_path}" == */./* || "${relative_path}" == */. ]]; then
build_directory_validation_error "unsafe relative cleanup subpath" "${quiet}"
return "${ERR_BUILD_PATH:-217}"
fi
candidate_subpath="${build_directory}/${relative_path}"
if [[ -L "${candidate_subpath}" || ! -e "${candidate_subpath}" ]]; then
build_directory_validation_error "cleanup subpath is missing or is a symlink" "${quiet}"
return "${ERR_BUILD_PATH:-217}"
fi
resolved_subpath="$(realpath "${candidate_subpath}" 2>/dev/null)" || return "${ERR_BUILD_PATH:-217}"
if [[ "${resolved_subpath}" != "${candidate_subpath}" || "${resolved_subpath}" != "${build_directory}/"* ]]; then
build_directory_validation_error "cleanup subpath escapes the exact build directory" "${quiet}"
return "${ERR_BUILD_PATH:-217}"
fi
printf -v "${output_variable}" '%s' "${resolved_subpath}"
return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f validate_build_directory_subpath
#######################################
# Initialises a new or empty build directory and its ownership marker.
# Arguments:
# 1: candidate path
# 2: output variable name
# Returns:
# 0: on success
# ERR_BUILD_PATH: on failure
#######################################
initialize_build_directory() {
declare candidate="$1" output_variable="$2" directory_mode="" directory_owner="" existing_entry=""
declare initialized_build_dir="" marker=""
validate_build_directory_path "${candidate}" initialized_build_dir || return "${ERR_BUILD_PATH:-217}"
if [[ ! -e "${initialized_build_dir}" ]]; then
mkdir -m 0700 "${initialized_build_dir}" || return "${ERR_BUILD_PATH:-217}"
fi
validate_build_directory_path "${initialized_build_dir}" initialized_build_dir || return "${ERR_BUILD_PATH:-217}"
[[ -d "${initialized_build_dir}" && ! -L "${initialized_build_dir}" ]] || return "${ERR_BUILD_PATH:-217}"
directory_owner="$(secure_stat -c '%u' "${initialized_build_dir}" 2>/dev/null)" || return "${ERR_BUILD_PATH:-217}"
directory_mode="$(secure_stat -c '%a' "${initialized_build_dir}" 2>/dev/null)" || return "${ERR_BUILD_PATH:-217}"
if [[ "${directory_owner}" != "${EUID}" ]] || (( (8#${directory_mode} & 022) != 0 )); then
build_directory_validation_error "build directory ownership or permissions are unsafe"
return "${ERR_BUILD_PATH:-217}"
fi
marker="${initialized_build_dir}/.ciss-live-builder-owned"
if [[ -e "${marker}" || -L "${marker}" ]]; then
validate_build_directory_marker "${initialized_build_dir}" || return "${ERR_BUILD_PATH:-217}"
else
existing_entry="$(find "${initialized_build_dir}" -mindepth 1 -maxdepth 1 -print -quit)" || return "${ERR_BUILD_PATH:-217}"
if [[ -n "${existing_entry}" ]]; then
build_directory_validation_error "non-empty directory has no builder-owned marker"
return "${ERR_BUILD_PATH:-217}"
fi
(umask 077; printf '%s\n' "${initialized_build_dir}" >| "${marker}") || return "${ERR_BUILD_PATH:-217}"
chmod 0400 "${marker}" || return "${ERR_BUILD_PATH:-217}"
validate_build_directory_marker "${initialized_build_dir}" || return "${ERR_BUILD_PATH:-217}"
fi
printf -v "${output_variable}" '%s' "${initialized_build_dir}"
return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f initialize_build_directory
#######################################
# Removes paths with a one-filesystem boundary where supported.
# Arguments:
# paths to remove
# Returns:
# rm exit status
#######################################
remove_build_paths() {
# shellcheck disable=SC2312
if rm --help 2>&1 | grep -q -- '--one-file-system'; then
rm -rf --one-file-system -- "$@"
else
rm -rf -- "$@"
fi
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f remove_build_paths
#######################################
# Deletes all content except the ownership marker from an exact build directory.
# Arguments:
# 1: candidate path
# Returns:
# 0: on success
# ERR_BUILD_PATH: on failure
#######################################
clean_build_directory_contents() {
declare candidate="$1" build_entry=""
declare -a build_entries=()
declare -i old_dotglob=0 old_failglob=0 old_nullglob=0
validate_build_directory_marker "${candidate}" || return "${ERR_BUILD_PATH:-217}"
shopt -q dotglob && old_dotglob=1
shopt -q failglob && old_failglob=1
shopt -q nullglob && old_nullglob=1
shopt -s dotglob nullglob
shopt -u failglob
build_entries=("${candidate}"/*)
for build_entry in "${build_entries[@]}"; do
[[ "${build_entry}" == "${candidate}/.ciss-live-builder-owned" ]] && continue
remove_build_paths "${build_entry}" || {
if (( old_dotglob )); then shopt -s dotglob; else shopt -u dotglob; fi
if (( old_failglob )); then shopt -s failglob; else shopt -u failglob; fi
if (( old_nullglob )); then shopt -s nullglob; else shopt -u nullglob; fi
return "${ERR_BUILD_PATH:-217}"
}
done
if (( old_dotglob )); then shopt -s dotglob; else shopt -u dotglob; fi
if (( old_failglob )); then shopt -s failglob; else shopt -u failglob; fi
if (( old_nullglob )); then shopt -s nullglob; else shopt -u nullglob; fi
validate_build_directory_marker "${candidate}" || return "${ERR_BUILD_PATH:-217}"
return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f clean_build_directory_contents
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh
+17 -1
View File
@@ -19,6 +19,9 @@ guard_sourcing || return "${ERR_GUARD_SRCE}"
# VAR_HANDLER_BUILD_DIR # VAR_HANDLER_BUILD_DIR
# VAR_HANDLER_CDI # VAR_HANDLER_CDI
# VAR_KERNEL # VAR_KERNEL
# VAR_PRIMORDIAL_KEY
# VAR_PRIMORDIAL_SSH_PORT
# VAR_PRIMORDIAL_URL
# VAR_WORKDIR # VAR_WORKDIR
# Arguments: # Arguments:
# None # None
@@ -38,7 +41,20 @@ cdi() {
fi fi
install -m 0755 -o root -g root "${VAR_WORKDIR}/scripts/usr/local/sbin/9999_cdi_starter.sh" "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/usr/local/sbin/9999_cdi_starter.sh" declare var_cdi_starter="${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/usr/local/sbin/9999_cdi_starter.sh"
declare var_primordial_key_q="" var_primordial_ssh_port_q="" var_primordial_url_q=""
install -m 0755 -o root -g root "${VAR_WORKDIR}/scripts/usr/local/sbin/9999_cdi_starter.sh" "${var_cdi_starter}"
printf -v var_primordial_key_q '%q' "${VAR_PRIMORDIAL_KEY:-}"
printf -v var_primordial_ssh_port_q '%q' "${VAR_PRIMORDIAL_SSH_PORT:-}"
printf -v var_primordial_url_q '%q' "${VAR_PRIMORDIAL_URL:-}"
sed -i \
-e "s|^declare -gx VAR_PRIMORDIAL_KEY=.*$|declare -gx VAR_PRIMORDIAL_KEY=${var_primordial_key_q} # Primordial SSH identity filename.|" \
-e "s|^declare -gx VAR_PRIMORDIAL_SSH_PORT=.*$|declare -gx VAR_PRIMORDIAL_SSH_PORT=${var_primordial_ssh_port_q} # Primordial SSH port.|" \
-e "s|^declare -gx VAR_PRIMORDIAL_URL=.*$|declare -gx VAR_PRIMORDIAL_URL=${var_primordial_url_q} # Primordial HTTPS Git URL.|" \
"${var_cdi_starter}"
declare tmp_entry declare tmp_entry
tmp_entry="$(mktemp)" tmp_entry="$(mktemp)"
+14 -24
View File
@@ -23,36 +23,26 @@ guard_sourcing || return "${ERR_GUARD_SRCE}"
# 0: on success # 0: on success
####################################### #######################################
x_remove() { x_remove() {
declare luks_key_filename="${VAR_LUKS_KEY:-luks.txt}" luks_key_path="" signing_pass_path=""
declare -a find_args=("${VAR_TMP_SECRET}" -xdev -type f)
printf "\e[95m🧪 %s starting ... \e[0m\n" "${BASH_SOURCE[0]}" printf "\e[95m🧪 %s starting ... \e[0m\n" "${BASH_SOURCE[0]}"
declare _old_nullglob="" _old_dotglob="" validate_secret_staging_area || return "${ERR_SECRET_PATH}"
### Enable nullglob/dotglob, disable failglob for safe globbing.
_old_nullglob="$(shopt -p nullglob || true)"
_old_dotglob="$( shopt -p dotglob || true)"
shopt -s nullglob dotglob
if [[ "${VAR_SIGNER}" == "true" ]]; then if [[ "${VAR_SIGNER}" == "true" ]]; then
validate_secret_file_in_root "${VAR_SIGNING_KEY_PASS}" "signing passphrase file" || return "${ERR_SECRET_PATH}"
# shellcheck disable=SC2312 signing_pass_path="${VAR_TMP_SECRET}/${VAR_SIGNING_KEY_PASS}"
find "${VAR_TMP_SECRET}" -xdev -type f \ find_args+=(! -path "${signing_pass_path}")
! -path "${VAR_TMP_SECRET}/signing_key_pass.txt" \
! -path "${VAR_TMP_SECRET}/luks.txt" \
-print0 \
| xargs -0 --no-run-if-empty shred -fzu -n 5 --
else
### Removes secrets securely.
# shellcheck disable=SC2312
find "${VAR_TMP_SECRET}" -xdev -type f -print0 | xargs -0 --no-run-if-empty shred -fzu -n 5 --
find "${VAR_TMP_SECRET}" -xdev -depth -type d -empty -delete
fi fi
eval "${_old_nullglob}" 2>/dev/null || true validate_secret_file_in_root "${luks_key_filename}" "LUKS key file" || return "${ERR_SECRET_PATH}"
eval "${_old_dotglob}" 2>/dev/null || true luks_key_path="${VAR_TMP_SECRET}/${luks_key_filename}"
find_args+=(! -path "${luks_key_path}")
# shellcheck disable=SC2312
find "${find_args[@]}" -print0 | xargs -0 --no-run-if-empty shred -fzu -n 5 --
find "${VAR_TMP_SECRET}" -xdev -depth -type d -empty -delete
printf "\e[92m✅ %s successfully applied. \e[0m\n" "${BASH_SOURCE[0]}" printf "\e[92m✅ %s successfully applied. \e[0m\n" "${BASH_SOURCE[0]}"
+29 -32
View File
@@ -32,15 +32,7 @@ guard_sourcing || return "${ERR_GUARD_SRCE}"
# 0: on success # 0: on success
####################################### #######################################
clean_up() { clean_up() {
declare clean_exit_code="$1" fs_type="" _old_nullglob="" _old_dotglob="" _old_failglob="" declare chroot_directory="" clean_exit_code="$1" fs_type="" includes_directory=""
### Enable nullglob/dotglob, disable failglob for safe globbing.
_old_nullglob="$(shopt -p nullglob || true)"
_old_dotglob="$( shopt -p dotglob || true)"
_old_failglob="$(shopt -p failglob || true)"
shopt -s nullglob dotglob
shopt -u failglob
if [[ -e /dev/mapper/crypt_liveiso ]]; then if [[ -e /dev/mapper/crypt_liveiso ]]; then
cryptsetup close crypt_liveiso || true cryptsetup close crypt_liveiso || true
@@ -52,10 +44,10 @@ clean_up() {
rm -f -- "${VAR_NOTES}" rm -f -- "${VAR_NOTES}"
### Release advisory lock on FD 127. ### Release advisory lock on FD 127.
flock -u 127 flock -u 127 2>/dev/null || true
### Close file descriptor 127. ### Close file descriptor 127.
exec 127>&- exec 127>&- 2>/dev/null || true
### Remove the lockfile artifact. ### Remove the lockfile artifact.
rm -f /run/lock/ciss_live_builder.lock rm -f /run/lock/ciss_live_builder.lock
@@ -100,36 +92,41 @@ clean_up() {
### No tracing for security reasons ------------------------------------------------------------------------------------------ ### No tracing for security reasons ------------------------------------------------------------------------------------------
[[ "${VAR_EARLY_DEBUG}" == "true" ]] && set +x [[ "${VAR_EARLY_DEBUG}" == "true" ]] && set +x
### Removes secrets securely. ### Removes secrets securely only after re-validating the fixed tmpfs staging area.
if validate_secret_staging_area "true"; then
# shellcheck disable=SC2312 # shellcheck disable=SC2312
find "${VAR_TMP_SECRET}" -xdev -type f -print0 | xargs -0 --no-run-if-empty shred -fzu -n 5 -- find "${VAR_TMP_SECRET}" -xdev -type f -print0 | xargs -0 --no-run-if-empty shred -fzu -n 5 -- || true
find "${VAR_TMP_SECRET}" -xdev -depth -type d -empty -delete find "${VAR_TMP_SECRET}" -xdev -depth -type d -empty -delete || true
else
### Securely shred all regular files below ./includes.chroot, then remove empty dirs. printf "\e[93m⚠ Secret cleanup skipped because the staging area failed validation. \e[0m\n" >&2
if [[ -d "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot" ]]; then
# shellcheck disable=SC2312
find "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot" -xdev -type f -print0 | xargs -0 --no-run-if-empty shred -fzu -n 5 --
### Remove empty directories (bottom-up).
find "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot" -depth -xdev -type d -empty -delete
fi fi
### Delete all files and directories below ./chroot. ### Destructive build cleanup requires the exact builder-owned directory marker.
if [[ -d "${VAR_HANDLER_BUILD_DIR}/chroot" ]]; then if [[ -n "${VAR_HANDLER_BUILD_DIR}" ]] && validate_build_directory_marker "${VAR_HANDLER_BUILD_DIR}" "true"; then
if [[ -e "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot" || -L "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot" ]]; then
rm -rf "${VAR_HANDLER_BUILD_DIR}/chroot" if validate_build_directory_subpath "${VAR_HANDLER_BUILD_DIR}" "config/includes.chroot" includes_directory "true"; then
# shellcheck disable=SC2312
find "${includes_directory}" -xdev -type f -print0 | xargs -0 --no-run-if-empty shred -fzu -n 5 -- || true
find "${includes_directory}" -depth -xdev -type d -empty -delete || true
else
printf "\e[93m⚠ Build includes cleanup skipped because the exact subpath failed validation. \e[0m\n" >&2
fi
fi
if [[ -e "${VAR_HANDLER_BUILD_DIR}/chroot" || -L "${VAR_HANDLER_BUILD_DIR}/chroot" ]]; then
if validate_build_directory_subpath "${VAR_HANDLER_BUILD_DIR}" "chroot" chroot_directory "true"; then
remove_build_paths "${chroot_directory}" || true
else
printf "\e[93m⚠ Build chroot cleanup skipped because the exact subpath failed validation. \e[0m\n" >&2
fi
fi
elif [[ -n "${VAR_HANDLER_BUILD_DIR}" ]]; then
printf "\e[93m⚠ Build-directory cleanup skipped because the exact builder-owned marker failed validation. \e[0m\n" >&2
fi fi
### Turn on tracing again ---------------------------------------------------------------------------------------------------- ### Turn on tracing again ----------------------------------------------------------------------------------------------------
[[ "${VAR_EARLY_DEBUG}" == "true" ]] && set -x [[ "${VAR_EARLY_DEBUG}" == "true" ]] && set -x
eval "${_old_nullglob}" 2>/dev/null || true
eval "${_old_dotglob}" 2>/dev/null || true
eval "${_old_failglob}" 2>/dev/null || true
return 0 return 0
} }
### Prevents accidental 'unset -f'. ### Prevents accidental 'unset -f'.
+92
View File
@@ -0,0 +1,92 @@
#!/bin/bash
# SPDX-Version: 3.0
# SPDX-CreationInfo: 2026-06-11; WEIDNER, Marc S.; <msw@coresecret.dev>
# SPDX-ExternalRef: GIT https://git.coresecret.dev/msw/CISS.debian.live.builder.git
# SPDX-FileContributor: WEIDNER, Marc S.; Centurion Intelligence Consulting Agency
# SPDX-FileCopyrightText: 2024-2026; WEIDNER, Marc S.; <msw@coresecret.dev>
# SPDX-FileType: SOURCE
# SPDX-License-Identifier: LicenseRef-CNCL-1.1 OR LicenseRef-CCLA-1.1
# SPDX-LicenseComment: This file is part of the CISS.debian.installer.secure framework.
# SPDX-PackageName: CISS.debian.live.builder
# SPDX-Security-Contact: security@coresecret.eu
guard_sourcing || return "${ERR_GUARD_SRCE}"
#######################################
# Replaces exact registered secret values in one controlled log file.
# Globals:
# _ARY_SECRET_REDACTION_VALUES
# Arguments:
# 1: log file
# Returns:
# 0: on success or missing log
# ERR_SANITIZING: on failure
#######################################
sanitize_debug_log() {
declare log_file="$1" log_text="" replacement="" secret_value="" tmp_file=""
[[ -n "${log_file}" && -f "${log_file}" ]] || return 0
[[ ! -L "${log_file}" ]] || return "${ERR_SANITIZING:-133}"
log_text="$(cat "${log_file}" || exit $?; printf '.')" || return "${ERR_SANITIZING:-133}"
log_text="${log_text%.}"
for secret_value in "${_ARY_SECRET_REDACTION_VALUES[@]}"; do
[[ -n "${secret_value}" ]] || continue
printf -v replacement '%*s' "${#secret_value}" ''
replacement="${replacement// /*}"
log_text="${log_text//"${secret_value}"/"${replacement}"}"
done
tmp_file="$(mktemp "${log_file}.sanitize.XXXXXX")" || return "${ERR_SANITIZING:-133}"
chmod 0600 "${tmp_file}" || {
rm -f "${tmp_file}"
return "${ERR_SANITIZING:-133}"
}
printf '%s' "${log_text}" >| "${tmp_file}" || {
rm -f "${tmp_file}"
return "${ERR_SANITIZING:-133}"
}
mv -f "${tmp_file}" "${log_file}" || {
rm -f "${tmp_file}"
return "${ERR_SANITIZING:-133}"
}
return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f sanitize_debug_log
#######################################
# Runs the final exact-value sanitisation pass for controlled logs.
# Globals:
# LOG_DEBUG
# LOG_ERROR
# LOG_VAR
# Arguments:
# None
# Returns:
# 0: on success
# ERR_SANITIZING: on failure
#######################################
sanitize_debug_logs() {
declare log_file=""
declare -a log_files=("${LOG_DEBUG:-}" "${LOG_VAR:-}" "${LOG_ERROR:-}")
set +x
if [[ -e "/proc/$$/fd/42" || -e "/dev/fd/42" ]]; then
exec 42>&-
fi
for log_file in "${log_files[@]}"; do
sanitize_debug_log "${log_file}" || return "${ERR_SANITIZING:-133}"
done
return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f sanitize_debug_logs
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh
+7
View File
@@ -41,6 +41,12 @@ init_gnupg() {
if [[ "${VAR_SIGNER}" == "true" ]]; then if [[ "${VAR_SIGNER}" == "true" ]]; then
validate_secret_file_in_root "${VAR_SIGNING_KEY}" "signing key file" || return "${ERR_SECRET_PATH}"
validate_secret_file_in_root "${VAR_SIGNING_KEY_PASS}" "signing passphrase file" || return "${ERR_SECRET_PATH}"
if [[ -n "${VAR_SIGNING_CA}" ]]; then
validate_secret_file_in_root "${VAR_SIGNING_CA}" "signing CA file" || return "${ERR_SECRET_PATH}"
fi
__umask=$(umask) __umask=$(umask)
umask 0077 umask 0077
@@ -82,6 +88,7 @@ EOF
declare __pw="" declare __pw=""
__pw="$(<"${VAR_SIGNING_KEY_PASSFILE}")"; __pw="${__pw%$'\r'}"; printf '%s' "${__pw}" >| "${VAR_SIGNING_KEY_PASSFILE}" __pw="$(<"${VAR_SIGNING_KEY_PASSFILE}")"; __pw="${__pw%$'\r'}"; printf '%s' "${__pw}" >| "${VAR_SIGNING_KEY_PASSFILE}"
register_secret_value "${__pw}"
__pw="" && unset __pw __pw="" && unset __pw
### Turn on tracing again ---------------------------------------------------------------------------------------------------- ### Turn on tracing again ----------------------------------------------------------------------------------------------------
+22 -5
View File
@@ -13,13 +13,14 @@
guard_sourcing || return "${ERR_GUARD_SRCE}" guard_sourcing || return "${ERR_GUARD_SRCE}"
####################################### #######################################
# Module for accompanying all 'CISS.debian.hardening' features into the Live ISO image. # Module for following all 'CISS.debian.hardening' features into the Live ISO image.
# Globals: # Globals:
# ARY_HANDLER_JUMPHOST # ARY_HANDLER_JUMPHOST
# ARY_HANDLER_JUMPHOST_UNIQUE # ARY_HANDLER_JUMPHOST_UNIQUE
# BASH_SOURCE # BASH_SOURCE
# VAR_ARCHITECTURE # VAR_ARCHITECTURE
# VAR_HANDLER_BUILD_DIR # VAR_HANDLER_BUILD_DIR
# VAR_PRIMORDIAL_SSH_PORT
# VAR_SSHFP # VAR_SSHFP
# VAR_SSHPORT # VAR_SSHPORT
# VAR_SSHPUBKEY # VAR_SSHPUBKEY
@@ -181,6 +182,8 @@ hardening_ultra() {
printf "\e[95m🧪 Updating SSH Keys, Ports ... \e[0m\n" printf "\e[95m🧪 Updating SSH Keys, Ports ... \e[0m\n"
### ./config/includes.chroot/root/.ssh --------------------------------------------------------------------------------------- ### ./config/includes.chroot/root/.ssh ---------------------------------------------------------------------------------------
validate_secret_absolute_directory "${VAR_SSHPUBKEY}" "SSH public-key directory" || return "${ERR_SECRET_PATH}"
validate_secret_file "${VAR_SSHPUBKEY}/authorized_keys" "SSH authorized_keys file" || return "${ERR_SECRET_PATH}"
install -d -m 0700 "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/.ssh" install -d -m 0700 "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/.ssh"
install -m 0600 -o root -g root "${VAR_SSHPUBKEY}/authorized_keys" "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/.ssh/" install -m 0600 -o root -g root "${VAR_SSHPUBKEY}/authorized_keys" "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/.ssh/"
@@ -196,12 +199,26 @@ hardening_ultra() {
sed -i "s|PORT_MUST_BE_SET|${sshport}|g" "${VAR_HANDLER_BUILD_DIR}/config/hooks/live/9950_hardening_fail2ban.chroot" sed -i "s|PORT_MUST_BE_SET|${sshport}|g" "${VAR_HANDLER_BUILD_DIR}/config/hooks/live/9950_hardening_fail2ban.chroot"
### /config/hooks/live/0900_ufw_setup.chroot ### /config/hooks/live/0900_ufw_setup.chroot
sed -i "s|SSHPORT_MUST_BE_SET|${sshport}|g" "${VAR_HANDLER_BUILD_DIR}/config/hooks/live/0900_ufw_setup.chroot" declare ufw_file="${VAR_HANDLER_BUILD_DIR}/config/hooks/live/0900_ufw_setup.chroot"
sed -i "s|SSHPORT_MUST_BE_SET|${sshport}|g" "${ufw_file}"
declare primordial_ssh_port="${VAR_PRIMORDIAL_SSH_PORT:-}"
if [[ -n "${primordial_ssh_port}" ]]; then
sed -i "s|^# PRIMORDIAL_SSH_PORT_DECLARATION_MUST_BE_SET$|declare -r PRIMORDIAL_SSH_PORT=\"${primordial_ssh_port}\"|" "${ufw_file}"
sed -i "s|^[[:space:]]*# PRIMORDIAL_SSH_RULE_MUST_BE_SET$| ufw allow out \"\${PRIMORDIAL_SSH_PORT}\"/tcp comment 'Outgoing Primordial SSH'|" "${ufw_file}"
else
sed -i '/^# PRIMORDIAL_SSH_PORT_DECLARATION_MUST_BE_SET$/d' "${ufw_file}"
sed -i '/^[[:space:]]*# PRIMORDIAL_SSH_RULE_MUST_BE_SET$/d' "${ufw_file}"
fi
### /config/hooks/live/0900_ufw_setup.chroot ### /config/hooks/live/0900_ufw_setup.chroot
if [[ ${#ARY_HANDLER_JUMPHOST[@]} -gt 0 ]]; then if [[ ${#ARY_HANDLER_JUMPHOST[@]} -gt 0 ]]; then
declare file="${VAR_HANDLER_BUILD_DIR}/config/hooks/live/0900_ufw_setup.chroot" declare file="${ufw_file}"
sed -i "/^ufw allow in \"\${SSHPORT}\"\/tcp comment 'Incoming SSH (Custom-Port)'$/d" "${file}" sed -i "/^ufw allow in \"\${SSHPORT}\"\/tcp comment 'Incoming SSH (Custom-Port)'$/d" "${file}"
@@ -251,7 +268,7 @@ hardening_ultra() {
### ./config/hooks/live/9950_hardening_fail2ban.chroot ----------------------------------------------------------------------- ### ./config/hooks/live/9950_hardening_fail2ban.chroot -----------------------------------------------------------------------
if ((${#ARY_HANDLER_JUMPHOST[@]} > 0)); then if ((${#ARY_HANDLER_JUMPHOST[@]} > 0)); then
printf "\e[95m🧪 Updating fail2ban Jumphosts IPs ... \e[0m\n" printf "\e[95m🧪 Updating fail2ban Jump-hosts IPs ... \e[0m\n"
# Join array entries with spaces, preserving any newlines # Join array entries with spaces, preserving any newlines
declare ips="${ARY_HANDLER_JUMPHOST[*]}" declare ips="${ARY_HANDLER_JUMPHOST[*]}"
@@ -265,7 +282,7 @@ hardening_ultra() {
# Perform an in-place replacement of IGNORE_IP_MUST_BE_SET with the cleaned list # Perform an in-place replacement of IGNORE_IP_MUST_BE_SET with the cleaned list
sed -i -E "/^[[:space:]]*ignoreip[[:space:]]*=/ s|IGNORE_IP_MUST_BE_SET|${flat_ips}|g" "${VAR_HANDLER_BUILD_DIR}/config/hooks/live/9950_hardening_fail2ban.chroot" sed -i -E "/^[[:space:]]*ignoreip[[:space:]]*=/ s|IGNORE_IP_MUST_BE_SET|${flat_ips}|g" "${VAR_HANDLER_BUILD_DIR}/config/hooks/live/9950_hardening_fail2ban.chroot"
printf "\e[92m✅ Updating fail2ban Jumphosts IPs done. \e[0m\n" printf "\e[92m✅ Updating fail2ban Jump-hosts IPs done. \e[0m\n"
else else
+7 -21
View File
@@ -23,36 +23,22 @@ guard_sourcing || return "${ERR_GUARD_SRCE}"
# 0: on success # 0: on success
####################################### #######################################
lb_config_start() { lb_config_start() {
declare canonical_build_dir=""
printf "\e[95m🧪 %s starting ... \e[0m\n" "${BASH_SOURCE[0]}" printf "\e[95m🧪 %s starting ... \e[0m\n" "${BASH_SOURCE[0]}"
if [[ ! -d ${VAR_HANDLER_BUILD_DIR} ]]; then initialize_build_directory "${VAR_HANDLER_BUILD_DIR}" canonical_build_dir || return "${ERR_BUILD_PATH}"
VAR_HANDLER_BUILD_DIR="${canonical_build_dir}"
mkdir -p "${VAR_HANDLER_BUILD_DIR}" cd "${VAR_HANDLER_BUILD_DIR}" || return "${ERR_BUILD_PATH}"
# shellcheck disable=SC2164
cd "${VAR_HANDLER_BUILD_DIR}"
printf "\e[92m✅ '%s' created. \e[0m\n" "${VAR_HANDLER_BUILD_DIR}"
else
# shellcheck disable=SC2164
cd "${VAR_HANDLER_BUILD_DIR}"
fi
if [[ -d "${VAR_HANDLER_BUILD_DIR}/.build" ]]; then if [[ -d "${VAR_HANDLER_BUILD_DIR}/.build" ]]; then
# shellcheck disable=SC2164 validate_build_directory_marker "${VAR_HANDLER_BUILD_DIR}" || return "${ERR_BUILD_PATH}"
cd "${VAR_HANDLER_BUILD_DIR}"
printf "\e[95m🧪 Deleting former config, binary and cache ... \e[0m\n" printf "\e[95m🧪 Deleting former config, binary and cache ... \e[0m\n"
lb clean --binary --cache --purge --source lb clean --binary --cache --purge --source
clean_build_directory_contents "${VAR_HANDLER_BUILD_DIR}" || return "${ERR_BUILD_PATH}"
if [[ "${PWD}" == "${VAR_HANDLER_BUILD_DIR}" && "${PWD}" != "/" && -n "${PWD}" ]]; then
rm -rf -- ./* ./.??*
fi
printf "\e[92m✅ Deleting former config, binary and cache done.\e[0m\n" printf "\e[92m✅ Deleting former config, binary and cache done.\e[0m\n"
+33
View File
@@ -0,0 +1,33 @@
#!/bin/bash
# SPDX-Version: 3.0
# SPDX-CreationInfo: 2026-06-10; WEIDNER, Marc S.; <msw@coresecret.dev>
# SPDX-ExternalRef: GIT https://git.coresecret.dev/msw/CISS.debian.live.builder.git
# SPDX-FileContributor: WEIDNER, Marc S.; Centurion Intelligence Consulting Agency
# SPDX-FileCopyrightText: 2024-2026; WEIDNER, Marc S.; <msw@coresecret.dev>
# SPDX-FileType: SOURCE
# SPDX-License-Identifier: LicenseRef-CNCL-1.1 OR LicenseRef-CCLA-1.1
# SPDX-LicenseComment: This file is part of the CISS.debian.installer.secure framework.
# SPDX-PackageName: CISS.debian.live.builder
# SPDX-Security-Contact: security@coresecret.eu
#######################################
# Logo Wrapper CISS.debian.live.builder
# Globals:
# None
# Arguments:
# None
# Returns:
# 0: on success
#######################################
logo() {
clear
printf '\033[95m'
cat centurion.txt
printf '\033[0m\n'
sleep 4
return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f logo
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh
+25 -5
View File
@@ -84,24 +84,44 @@ init_primordial() {
### Check for SOPS AGE key integration --------------------------------------------------------------------------------------- ### Check for SOPS AGE key integration ---------------------------------------------------------------------------------------
if [[ "${VAR_AGE,,}" == "true" ]]; then if [[ "${VAR_AGE,,}" == "true" ]]; then
validate_secret_file_in_root "${VAR_AGE_KEY}" "SOPS Age key" || return "${ERR_SECRET_PATH}"
install -d -m 0700 "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/.config/sops/age" install -d -m 0700 "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/.config/sops/age"
install -m 0400 "${VAR_TMP_SECRET}/${VAR_AGE_KEY}" "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/.config/sops/age/keys.txt" install -m 0400 "${VAR_TMP_SECRET}/${VAR_AGE_KEY}" "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/.config/sops/age/keys.txt"
shred -fzu -n 5 -- "${VAR_TMP_SECRET}/${VAR_AGE_KEY}" 2>/dev/null || rm -f "${VAR_TMP_SECRET}/${VAR_AGE_KEY}" shred -fzu -n 5 -- "${VAR_TMP_SECRET}/${VAR_AGE_KEY}" 2>/dev/null || rm -f "${VAR_TMP_SECRET}/${VAR_AGE_KEY}"
fi fi
### Check for SSH CISS and PhysNet primordial-workflow(tm) integration ------------------------------------------------------- ### Check for SSH CISS and PhysNet Primordial-Workflow integration -------------------------------------------------------
if [[ "${VAR_SSHFP,,}" == "true" ]]; then if [[ "${VAR_SSHFP,,}" == "true" ]]; then
declare secret_key_file=""
declare -a identity_files=() host_key_files=()
validate_secret_directory "${VAR_TMP_SECRET}" "secret root" "true" || return "${ERR_SECRET_PATH}"
while IFS= read -r -d '' secret_key_file; do
validate_secret_file "${secret_key_file}" "primordial SSH identity file" || return "${ERR_SECRET_PATH}"
identity_files+=("${secret_key_file}")
done < <(find "${VAR_TMP_SECRET}" -maxdepth 1 -type f -name 'id*' -print0)
while IFS= read -r -d '' secret_key_file; do
validate_secret_file "${secret_key_file}" "primordial SSH host-key file" || return "${ERR_SECRET_PATH}"
host_key_files+=("${secret_key_file}")
done < <(find "${VAR_TMP_SECRET}" -maxdepth 1 -type f -name 'ssh_host_*' -print0)
(( ${#identity_files[@]} > 0 && ${#host_key_files[@]} > 0 )) || {
secret_validation_error "required primordial SSH key files are missing"
return "${ERR_SECRET_PATH}"
}
install -d -m 0700 "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/.ssh" install -d -m 0700 "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/.ssh"
install -m 0600 "${VAR_TMP_SECRET}/id"* "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/.ssh/" install -m 0600 "${identity_files[@]}" "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/.ssh/"
normalize_ssh_keys_in_dir "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/.ssh" normalize_ssh_keys_in_dir "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/.ssh"
shred -fzu -n 5 -- "${VAR_TMP_SECRET}/id"* 2>/dev/null || rm -f "${VAR_TMP_SECRET}/id"* shred -fzu -n 5 -- "${identity_files[@]}" 2>/dev/null || rm -f "${identity_files[@]}"
install -d -m 0700 "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/ssh" install -d -m 0700 "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/ssh"
install -m 0600 "${VAR_TMP_SECRET}/ssh_host_"* "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/ssh/" install -m 0600 "${host_key_files[@]}" "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/ssh/"
normalize_ssh_keys_in_dir "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/ssh/" normalize_ssh_keys_in_dir "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/ssh/"
shred -fzu -n 5 -- "${VAR_TMP_SECRET}/ssh_host_"* 2>/dev/null || rm -f "${VAR_TMP_SECRET}/ssh_host_"* shred -fzu -n 5 -- "${host_key_files[@]}" 2>/dev/null || rm -f "${host_key_files[@]}"
fi fi
+8 -8
View File
@@ -55,7 +55,7 @@ sanitize_arg() {
{ {
printf "❌ Control character : '%s'. \n" "${disallowed_ctrl}" printf "❌ Control character : '%s'. \n" "${disallowed_ctrl}"
printf "❌ in argument : '%s'. \n" "${input}" printf "❌ in argument : '%s'. \n" "${input}"
printf "❌ Allowed Characters : 'a-z A-Z 0-9 . _ / = [ ] : \" - + space' \n" printf "❌ Allowed Characters : 'a-z A-Z 0-9 . _ / = [ ] : \" @ %% , ~ - + space' \n"
printf "\n" printf "\n"
} >> "${LOG_ERROR}" } >> "${LOG_ERROR}"
@@ -63,7 +63,7 @@ sanitize_arg() {
printf "\e[91m❌ Control character : '%s'. \e[0m\n" "${disallowed_ctrl}" >&2 printf "\e[91m❌ Control character : '%s'. \e[0m\n" "${disallowed_ctrl}" >&2
printf "\e[91m❌ in argument : '%s'. \e[0m\n" "${input}" >&2 printf "\e[91m❌ in argument : '%s'. \e[0m\n" "${input}" >&2
printf "\e[91m❌ Allowed Characters : 'a-z A-Z 0-9 . _ / = [ ] : \" - + space' \e[0m\n" >&2 printf "\e[91m❌ Allowed Characters : 'a-z A-Z 0-9 . _ / = [ ] : \" @ %% , ~ - + space' \e[0m\n" >&2
# shellcheck disable=SC2162 # shellcheck disable=SC2162
read -p $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m' read -p $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m'
@@ -73,8 +73,8 @@ sanitize_arg() {
fi fi
### Step 2: Define allowed characters: ### Step 2: Define allowed characters:
### letters, digits, dot, underscore, slash, equals, [, ], colon, double-quote, hyphen, space. ### letters, digits, dot, underscore, slash, equals, [, ], colon, double-quote, @, %, comma, tilde, hyphen, plus, space.
declare allowed='a-zA-Z0-9._/=\[\]:"\-+ ' declare allowed='a-zA-Z0-9._/=\[\]:"@%,~\-+ '
declare disallowed declare disallowed
disallowed=$(printf '%s' "${input}" | tr -d "${allowed}") disallowed=$(printf '%s' "${input}" | tr -d "${allowed}")
@@ -82,7 +82,7 @@ sanitize_arg() {
{ {
printf "❌ Invalid character : '%s'. \n" "${disallowed//?/& }" printf "❌ Invalid character : '%s'. \n" "${disallowed//?/& }"
printf "❌ in argument : '%s'. \n" "${input}" printf "❌ in argument : '%s'. \n" "${input}"
printf "❌ Allowed Characters : 'a-z A-Z 0-9 . _ / = [ ] : \" - + space' \n" printf "❌ Allowed Characters : 'a-z A-Z 0-9 . _ / = [ ] : \" @ %% , ~ - + space' \n"
printf "\n" printf "\n"
} >> "${LOG_ERROR}" } >> "${LOG_ERROR}"
@@ -90,7 +90,7 @@ sanitize_arg() {
printf "\e[91m❌ Invalid character : '%s'. \e[0m\n" "${disallowed//?/& }" >&2 printf "\e[91m❌ Invalid character : '%s'. \e[0m\n" "${disallowed//?/& }" >&2
printf "\e[91m❌ in argument : '%s'. \e[0m\n" "${input}" >&2 printf "\e[91m❌ in argument : '%s'. \e[0m\n" "${input}" >&2
printf "\e[91m❌ Allowed Characters : 'a-z A-Z 0-9 . _ / = [ ] : \" - + space' \e[0m\n" >&2 printf "\e[91m❌ Allowed Characters : 'a-z A-Z 0-9 . _ / = [ ] : \" @ %% , ~ - + space' \e[0m\n" >&2
# shellcheck disable=SC2162 # shellcheck disable=SC2162
read -p $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m' read -p $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m'
@@ -119,8 +119,8 @@ readonly -f sanitize_arg
sanitize_string() { sanitize_string() {
declare input="$1" declare input="$1"
### Define allowed characters: ### Define allowed characters:
### letters, digits, dot, underscore, slash, equals, [, ], colon, double-quote, hyphen, space. ### letters, digits, dot, underscore, slash, equals, [, ], colon, double-quote, @, %, comma, tilde, hyphen, plus, space.
declare allowed='a-zA-Z0-9._/=\[\]:"\-+ ' declare allowed='a-zA-Z0-9._/=\[\]:"@%,~\-+ '
printf '%s' "${input}" | tr -cd "${allowed}" printf '%s' "${input}" | tr -cd "${allowed}"
} }
### Prevents accidental 'unset -f'. ### Prevents accidental 'unset -f'.
+384
View File
@@ -0,0 +1,384 @@
#!/bin/bash
# SPDX-Version: 3.0
# SPDX-CreationInfo: 2026-06-11; WEIDNER, Marc S.; <msw@coresecret.dev>
# SPDX-ExternalRef: GIT https://git.coresecret.dev/msw/CISS.debian.live.builder.git
# SPDX-FileContributor: WEIDNER, Marc S.; Centurion Intelligence Consulting Agency
# SPDX-FileCopyrightText: 2024-2026; WEIDNER, Marc S.; <msw@coresecret.dev>
# SPDX-FileType: SOURCE
# SPDX-License-Identifier: LicenseRef-CNCL-1.1 OR LicenseRef-CCLA-1.1
# SPDX-LicenseComment: This file is part of the CISS.debian.installer.secure framework.
# SPDX-PackageName: CISS.debian.live.builder
# SPDX-Security-Contact: security@coresecret.eu
guard_sourcing || return "${ERR_GUARD_SRCE}"
if ! declare -p _ARY_SECRET_REDACTION_VALUES >/dev/null 2>&1; then
declare -ga _ARY_SECRET_REDACTION_VALUES=()
fi
#######################################
# Runs GNU stat on Debian and gstat on macOS development hosts.
# Arguments:
# stat arguments
# Returns:
# stat exit status
#######################################
secure_stat() {
if command -v gstat >/dev/null 2>&1; then
gstat "$@"
else
stat "$@"
fi
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f secure_stat
#######################################
# Prints a generic secret validation error without disclosing a path or value.
# Arguments:
# 1: unsafe input class
# 2: quiet flag
# Returns:
# ERR_SECRET_PATH
#######################################
secret_validation_error() {
declare error_class="$1" quiet="${2:-false}"
if [[ "${quiet}" != "true" ]]; then
printf "\e[91m❌ Unsafe secret input rejected: %s. \e[0m\n" "${error_class}" >&2
fi
return "${ERR_SECRET_PATH:-216}"
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f secret_validation_error
#######################################
# Registers an exact known secret value for final log redaction.
# Globals:
# _ARY_SECRET_REDACTION_VALUES
# Arguments:
# 1: secret value
# Returns:
# 0: on success
#######################################
register_secret_value() {
declare secret_value="$1" registered_value="" was_traced="false"
[[ $- == *x* ]] && was_traced="true"
set +x
if [[ -n "${secret_value}" ]]; then
for registered_value in "${_ARY_SECRET_REDACTION_VALUES[@]}"; do
if [[ "${registered_value}" == "${secret_value}" ]]; then
[[ "${was_traced}" == "true" ]] && set -x
return 0
fi
done
_ARY_SECRET_REDACTION_VALUES+=("${secret_value}")
fi
[[ "${was_traced}" == "true" ]] && set -x
return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f register_secret_value
#######################################
# Registers exact text values from a controlled secret file.
# Globals:
# _ARY_SECRET_REDACTION_VALUES
# Arguments:
# 1: secret file
# Returns:
# 0: on success
#######################################
register_secret_file_for_redaction() {
declare secret_file="$1" secret_line="" secret_text="" was_traced="false"
[[ $- == *x* ]] && was_traced="true"
set +x
secret_text="$(cat "${secret_file}" || exit $?; printf '.')" || {
[[ "${was_traced}" == "true" ]] && set -x
return "${ERR_SANITIZING:-133}"
}
secret_text="${secret_text%.}"
register_secret_value "${secret_text}"
while IFS= read -r secret_line || [[ -n "${secret_line}" ]]; do
register_secret_value "${secret_line}"
done < "${secret_file}"
[[ "${was_traced}" == "true" ]] && set -x
return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f register_secret_file_for_redaction
#######################################
# Validates a filename-only secret argument.
# Arguments:
# 1: filename
# 2: input class
# Returns:
# 0: on success
# ERR_SECRET_PATH: on failure
#######################################
validate_secret_filename() {
declare filename="$1" input_class="${2:-filename-only secret argument}"
declare filename_regex='^[A-Za-z0-9._@%+=:,~-]+$'
if [[ -z "${filename}" || "${filename}" == "." || "${filename}" == ".." || "${filename}" == */* \
|| ! "${filename}" =~ ${filename_regex} ]]; then
secret_validation_error "${input_class}"
return "${ERR_SECRET_PATH:-216}"
fi
return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f validate_secret_filename
#######################################
# Validates a restrictively permissioned secret directory.
# Arguments:
# 1: directory path
# 2: input class
# 3: require tmpfs
# 4: quiet flag
# Returns:
# 0: on success
# ERR_SECRET_PATH: on failure
#######################################
validate_secret_directory() {
declare directory="$1" input_class="${2:-secret directory}" require_tmpfs="${3:-false}" quiet="${4:-false}"
declare fs_type="" mode="" owner=""
if [[ -z "${directory}" || -L "${directory}" || ! -d "${directory}" ]]; then
secret_validation_error "${input_class}" "${quiet}"
return "${ERR_SECRET_PATH:-216}"
fi
owner="$(secure_stat -c '%u' "${directory}" 2>/dev/null)" || {
secret_validation_error "${input_class} ownership" "${quiet}"
return "${ERR_SECRET_PATH:-216}"
}
mode="$(secure_stat -c '%a' "${directory}" 2>/dev/null)" || {
secret_validation_error "${input_class} permissions" "${quiet}"
return "${ERR_SECRET_PATH:-216}"
}
if [[ "${owner}" != "${EUID}" || "${mode}" != "700" ]]; then
secret_validation_error "${input_class} ownership or permissions" "${quiet}"
return "${ERR_SECRET_PATH:-216}"
fi
if [[ "${require_tmpfs}" == "true" ]]; then
fs_type="$(secure_stat -f -c '%T' "${directory}" 2>/dev/null)" || {
secret_validation_error "${input_class} filesystem" "${quiet}"
return "${ERR_SECRET_PATH:-216}"
}
if [[ "${fs_type}" != "tmpfs" && "${fs_type}" != "ramfs" ]]; then
secret_validation_error "${input_class} is not tmpfs-backed" "${quiet}"
return "${ERR_SECRET_PATH:-216}"
fi
fi
return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f validate_secret_directory
#######################################
# Validates and registers a secret file.
# Arguments:
# 1: file path
# 2: input class
# 3: register for redaction
# 4: quiet flag
# Returns:
# 0: on success
# ERR_SECRET_PATH: on failure
#######################################
validate_secret_file() {
declare secret_file="$1" input_class="${2:-secret file}" register_value="${3:-true}" quiet="${4:-false}"
declare link_count="" mode="" owner=""
if [[ -z "${secret_file}" || -L "${secret_file}" || ! -f "${secret_file}" ]]; then
secret_validation_error "${input_class}" "${quiet}"
return "${ERR_SECRET_PATH:-216}"
fi
owner="$(secure_stat -c '%u' "${secret_file}" 2>/dev/null)" || {
secret_validation_error "${input_class} ownership" "${quiet}"
return "${ERR_SECRET_PATH:-216}"
}
mode="$(secure_stat -c '%a' "${secret_file}" 2>/dev/null)" || {
secret_validation_error "${input_class} permissions" "${quiet}"
return "${ERR_SECRET_PATH:-216}"
}
link_count="$(secure_stat -c '%h' "${secret_file}" 2>/dev/null)" || {
secret_validation_error "${input_class} link count" "${quiet}"
return "${ERR_SECRET_PATH:-216}"
}
if [[ "${owner}" != "${EUID}" || "${link_count}" != "1" || ( "${mode}" != "400" && "${mode}" != "600" ) ]]; then
secret_validation_error "${input_class} ownership, permissions, or link count" "${quiet}"
return "${ERR_SECRET_PATH:-216}"
fi
if [[ "${register_value}" == "true" ]]; then
register_secret_file_for_redaction "${secret_file}"
fi
return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f validate_secret_file
#######################################
# Validates an explicitly supported absolute secret file path.
# Arguments:
# 1: file path
# 2: input class
# Returns:
# 0: on success
# ERR_SECRET_PATH: on failure
#######################################
validate_secret_absolute_file() {
declare secret_file="$1" input_class="${2:-absolute secret file}" resolved_file=""
if [[ -z "${secret_file}" || "${secret_file}" != /* ]]; then
secret_validation_error "${input_class} must be an absolute path"
return "${ERR_SECRET_PATH:-216}"
fi
resolved_file="$(realpath "${secret_file}" 2>/dev/null)" || {
secret_validation_error "${input_class} cannot be resolved"
return "${ERR_SECRET_PATH:-216}"
}
if [[ "${resolved_file}" != "${secret_file}" ]]; then
secret_validation_error "${input_class} must be canonical and must not traverse symlinked parents"
return "${ERR_SECRET_PATH:-216}"
fi
validate_secret_file "${secret_file}" "${input_class}" || return "${ERR_SECRET_PATH:-216}"
return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f validate_secret_absolute_file
#######################################
# Validates an explicitly supported absolute secret directory path.
# Arguments:
# 1: directory path
# 2: input class
# Returns:
# 0: on success
# ERR_SECRET_PATH: on failure
#######################################
validate_secret_absolute_directory() {
declare directory="$1" input_class="${2:-absolute secret directory}" resolved_directory=""
if [[ -z "${directory}" || "${directory}" != /* ]]; then
secret_validation_error "${input_class} must be an absolute path"
return "${ERR_SECRET_PATH:-216}"
fi
resolved_directory="$(realpath "${directory}" 2>/dev/null)" || {
secret_validation_error "${input_class} cannot be resolved"
return "${ERR_SECRET_PATH:-216}"
}
if [[ "${resolved_directory}" != "${directory}" ]]; then
secret_validation_error "${input_class} must be canonical and must not traverse symlinked parents"
return "${ERR_SECRET_PATH:-216}"
fi
validate_secret_directory "${directory}" "${input_class}" || return "${ERR_SECRET_PATH:-216}"
return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f validate_secret_absolute_directory
#######################################
# Validates a filename-only secret file below the fixed secret root.
# Globals:
# VAR_TMP_SECRET
# Arguments:
# 1: filename
# 2: input class
# 3: register for redaction
# Returns:
# 0: on success
# ERR_SECRET_PATH: on failure
#######################################
validate_secret_file_in_root() {
declare filename="$1" input_class="${2:-secret file}" register_value="${3:-true}"
validate_secret_directory "${VAR_TMP_SECRET}" "secret root" "true" || return "${ERR_SECRET_PATH:-216}"
validate_secret_filename "${filename}" "${input_class} filename" || return "${ERR_SECRET_PATH:-216}"
validate_secret_file "${VAR_TMP_SECRET}/${filename}" "${input_class}" "${register_value}" || return "${ERR_SECRET_PATH:-216}"
return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f validate_secret_file_in_root
#######################################
# Validates the fixed tmpfs secret staging area and all entries below it.
# Globals:
# VAR_TMP_SECRET
# Arguments:
# 1: quiet flag
# Returns:
# 0: on success
# ERR_SECRET_PATH: on failure
#######################################
validate_secret_staging_area() {
declare quiet="${1:-false}" secret_entries_file="" secret_entry=""
declare -a secret_entries=()
validate_secret_directory "${VAR_TMP_SECRET}" "secret root" "true" "${quiet}" || return "${ERR_SECRET_PATH:-216}"
secret_entries_file="$(mktemp)" || return "${ERR_SECRET_PATH:-216}"
if ! find "${VAR_TMP_SECRET}" -xdev -mindepth 1 -print0 >| "${secret_entries_file}"; then
rm -f "${secret_entries_file}"
secret_validation_error "secret-root enumeration failed" "${quiet}"
return "${ERR_SECRET_PATH:-216}"
fi
mapfile -d '' -t secret_entries < "${secret_entries_file}"
rm -f "${secret_entries_file}"
for secret_entry in "${secret_entries[@]}"; do
if [[ -L "${secret_entry}" ]]; then
secret_validation_error "symlink below secret root" "${quiet}"
return "${ERR_SECRET_PATH:-216}"
elif [[ -d "${secret_entry}" ]]; then
validate_secret_directory "${secret_entry}" "directory below secret root" "false" "${quiet}" \
|| return "${ERR_SECRET_PATH:-216}"
elif [[ -f "${secret_entry}" ]]; then
validate_secret_file "${secret_entry}" "file below secret root" "true" "${quiet}" || return "${ERR_SECRET_PATH:-216}"
else
secret_validation_error "non-regular entry below secret root" "${quiet}"
return "${ERR_SECRET_PATH:-216}"
fi
done
return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f validate_secret_staging_area
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh
+9 -4
View File
@@ -49,8 +49,6 @@ trap_on_exit() {
print_scr_exit "${errcode}" print_scr_exit "${errcode}"
exit "${errcode}"
else else
if [[ "${ERRTRAP}" != "true" ]]; then if [[ "${ERRTRAP}" != "true" ]]; then
@@ -63,9 +61,16 @@ trap_on_exit() {
fi fi
exit "${errcode}"
fi fi
if ! sanitize_debug_logs; then
printf "\e[93m⚠ Final debug-log sanitisation failed; preserving original exit status %s. \e[0m\n" "${errcode}" >&2
if [[ -n "${LOG_ERROR:-}" && -f "${LOG_ERROR}" && ! -L "${LOG_ERROR}" ]]; then
printf "⚠ Final debug-log sanitisation failed; original exit status: %s.\n" "${errcode}" >> "${LOG_ERROR}" || true
fi
fi
exit "${errcode}"
} }
### Prevents accidental 'unset -f'. ### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034 # shellcheck disable=SC2034
+33 -4
View File
@@ -39,13 +39,13 @@ usage() {
# shellcheck disable=SC2155 # shellcheck disable=SC2155
declare var_header=$(center "CDLB(1) CISS.debian.live.builder CDLB(1)" "${var_cols}") declare var_header=$(center "CDLB(1) CISS.debian.live.builder CDLB(1)" "${var_cols}")
# shellcheck disable=SC2155 # shellcheck disable=SC2155
declare var_footer=$(center "V9.14.020.2026.06.08 2026-06-08 CDLB(1)" "${var_cols}") declare var_footer=$(center "V9.14.022.2026.06.10 2026-06-10 CDLB(1)" "${var_cols}")
{ {
echo -e "\e[1;97m${var_header}\e[0m" echo -e "\e[1;97m${var_header}\e[0m"
echo echo
echo -e "\e[92mCISS.debian.live.builder from https://git.coresecret.dev/msw \e[0m" echo -e "\e[92mCISS.debian.live.builder from https://git.coresecret.dev/msw \e[0m"
echo -e "\e[92mMaster V9.14.020.2026.06.08\e[0m" echo -e "\e[92mMaster V9.14.022.2026.06.10\e[0m"
echo -e "\e[92mA lightweight Shell Wrapper for building a hardened Debian Live ISO Image.\e[0m" echo -e "\e[92mA lightweight Shell Wrapper for building a hardened Debian Live ISO Image.\e[0m"
echo echo
echo -e "\e[97m(c) Marc S. Weidner, 2018 - 2026 \e[0m" echo -e "\e[97m(c) Marc S. Weidner, 2018 - 2026 \e[0m"
@@ -67,6 +67,10 @@ usage() {
echo echo
echo -e "\e[97m --build-directory </path/to/build_directory> \e[0m" echo -e "\e[97m --build-directory </path/to/build_directory> \e[0m"
echo " Where the Debian Live Build Image should be generated. RECOMMENDED path: </opt/cdlb>" echo " Where the Debian Live Build Image should be generated. RECOMMENDED path: </opt/cdlb>"
echo " The path MUST be canonical and dedicated to the builder; a new directory's canonical parent MUST already exist."
echo " New or empty directories receive the"
echo " '.ciss-live-builder-owned' marker; populated unmarked directories are rejected. Cleanup is intentionally"
echo " destructive only inside the exact validated marker-owned directory."
echo " MUST be provided." echo " MUST be provided."
echo echo
echo -e "\e[97m --change-splash <STRING> one of <club | hexagon> \e[0m" echo -e "\e[97m --change-splash <STRING> one of <club | hexagon> \e[0m"
@@ -87,6 +91,7 @@ usage() {
echo -e "\e[97m --debug, -d \e[0m" echo -e "\e[97m --debug, -d \e[0m"
echo " Enables debug logging for the main program routine. Detailed logging information are written to:" echo " Enables debug logging for the main program routine. Detailed logging information are written to:"
echo " </tmp/ciss_live_builder_$$.log>" echo " </tmp/ciss_live_builder_$$.log>"
echo " A final exact-value sanitisation pass is defence in depth and does not replace careful tracing discipline."
echo echo
echo -e "\e[97m --dhcp-centurion \e[0m" echo -e "\e[97m --dhcp-centurion \e[0m"
echo " If a DHCP lease is provided, the provider's name server will be overridden and the hardened, privacy-focused " echo " If a DHCP lease is provided, the provider's name server will be overridden and the hardened, privacy-focused "
@@ -108,11 +113,13 @@ usage() {
echo echo
echo -e "\e[97m --key_age=* \e[0m" echo -e "\e[97m --key_age=* \e[0m"
echo " The SOPS AGE private keyring for decryption operations. Change '*' to your desired SOPS AGE key file." echo " The SOPS AGE private keyring for decryption operations. Change '*' to your desired SOPS AGE key file."
echo " '*' MUST be a filename only without slashes, '.' or '..' traversal."
echo " File MUST be placed in:" echo " File MUST be placed in:"
echo " </dev/shm/cdlb_secrets>" echo " </dev/shm/cdlb_secrets>"
echo echo
echo -e "\e[97m --key_luks=* \e[0m" echo -e "\e[97m --key_luks=* \e[0m"
echo " The LUKS encryption / decryption passphrase for '/'-fs-encryption. Change '*' to your desired passphrase file." echo " The LUKS encryption / decryption passphrase for '/'-fs-encryption. Change '*' to your desired passphrase file."
echo " '*' MUST be a filename only without slashes, '.' or '..' traversal."
echo " File MUST be placed in:" echo " File MUST be placed in:"
echo " </dev/shm/cdlb_secrets>" echo " </dev/shm/cdlb_secrets>"
echo echo
@@ -120,6 +127,24 @@ usage() {
echo " Provides statistic only after successful building a CISS.debian.live-ISO. While enabling '--log-statistics-only'" echo " Provides statistic only after successful building a CISS.debian.live-ISO. While enabling '--log-statistics-only'"
echo " the argument '--build-directory' MUST be provided." echo " the argument '--build-directory' MUST be provided."
echo echo
echo -e "\e[97m --primordial-key <ssh-identity-filename> \e[0m"
echo " SSH identity filename for the Primordial overlay clone. This MUST be a filename only; the runtime path is"
echo " derived as '/root/.ssh/<ssh-identity-filename>'."
echo " Example fragment:"
echo " ./ciss_live_builder.sh --primordial-url https://git.coresecret.dev/ahz/PhysNet.primordial.git \\"
echo " --primordial-key id--git.coresecret.dev--PhysNet.primordial_deploy--ed25519--newton--2025-10 \\"
echo " --primordial-ssh 42842"
echo
echo -e "\e[97m --primordial-ssh <INTEGER> \e[0m"
echo " Adds one outgoing UFW TCP exception for a bootstrap SSH port."
echo " Outgoing only: no incoming firewall rule is added, and this option does not replace '--ssh-port'."
echo " Effective only when the Live System's UFW outgoing policy is 'deny'."
echo " Port MUST be a decimal integer between '1' and '65535'."
echo
echo -e "\e[97m --primordial-url <https-git-url> \e[0m"
echo " HTTPS Git repository URL for the Primordial CDI overlay. MUST start with 'https://', include a host and"
echo " path, and end in '.git'. The CDI starter converts this URL to an SSH clone URL at runtime."
echo
echo -e "\e[97m --provider-netcup-ipv6 \e[0m" echo -e "\e[97m --provider-netcup-ipv6 \e[0m"
echo " Activates IPv6 support for Netcup Root Server. One unique IPv6 address MUST be provided in this case and MUST be" echo " Activates IPv6 support for Netcup Root Server. One unique IPv6 address MUST be provided in this case and MUST be"
echo " encapsulated with [], e.g., [1234::abcd]." echo " encapsulated with [], e.g., [1234::abcd]."
@@ -144,7 +169,7 @@ usage() {
echo -e "\e[97m --root-password-file </dev/shm/cdlb_secrets/password.txt>> \e[0m" echo -e "\e[97m --root-password-file </dev/shm/cdlb_secrets/password.txt>> \e[0m"
echo " Password file for 'root', if given, MUST be a string of 42 to 64 characters." echo " Password file for 'root', if given, MUST be a string of 42 to 64 characters."
echo " If the argument is omitted, no further login authentication is required for the local console." echo " If the argument is omitted, no further login authentication is required for the local console."
echo " MUST be placed in:" echo " Safe absolute paths remain supported and are validated separately. RECOMMENDED path:"
echo " </dev/shm/cdlb_secrets/password.txt>" echo " </dev/shm/cdlb_secrets/password.txt>"
echo echo
echo -e "\e[97m --secure-boot-profile <STRING> one of <debian-shim | ciss-uki> \e[0m" echo -e "\e[97m --secure-boot-profile <STRING> one of <debian-shim | ciss-uki> \e[0m"
@@ -160,7 +185,8 @@ usage() {
echo " specified via '--signing_key=*'. If the keyring is protected, then provide the passphrase in its own file." echo " specified via '--signing_key=*'. If the keyring is protected, then provide the passphrase in its own file."
echo " Specify the fingerprint of the key to use via '--signing_key_fpr=*'." echo " Specify the fingerprint of the key to use via '--signing_key_fpr=*'."
echo " Optionally import an offline GPG CA signing public key via: '--signing_ca=*'." echo " Optionally import an offline GPG CA signing public key via: '--signing_ca=*'."
echo " Change '*' to your desired files / fingerprint. Files MUST be placed in:" echo " Change '*' to your desired filename-only files / fingerprint. Filename-only values MUST NOT contain slashes"
echo " or traversal. Files MUST be placed in:"
echo " </dev/shm/cdlb_secrets>" echo " </dev/shm/cdlb_secrets>"
echo echo
echo -e "\e[97m --sops-version <STRING> \e[0m" echo -e "\e[97m --sops-version <STRING> \e[0m"
@@ -194,6 +220,9 @@ usage() {
echo echo
echo -e "\e[93m💡 Notes: \e[0m" echo -e "\e[93m💡 Notes: \e[0m"
echo -e "\e[93m🔵 You MUST be 'root' to run this script. \e[0m" echo -e "\e[93m🔵 You MUST be 'root' to run this script. \e[0m"
echo -e "\e[93m🔵 Private operator control does not remove the requirement for strict local secret path validation. \e[0m"
echo -e "\e[93m🔵 '/dev/shm/cdlb_secrets' MUST be tmpfs-backed, root-owned, mode 0700, and contain only \e[0m"
echo -e "\e[93m single-link regular secret files with mode 0400 or 0600. Secure deletion with shred is best-effort only. \e[0m"
echo echo
echo -e "\e[95m💷 Please consider donating to my work at: \e[0m" echo -e "\e[95m💷 Please consider donating to my work at: \e[0m"
echo -e "\e[95m🌐 https://coresecret.eu/spenden/ \e[0m" echo -e "\e[95m🌐 https://coresecret.eu/spenden/ \e[0m"
+4 -1
View File
@@ -25,7 +25,7 @@ TIMESTAMP ?= $(shell date -u +%Y-%m-%dT%H-%M-%S)
### Core parameters (safe defaults; override in config.mk, rename config.mk.sample to config.mk and apply the remaining values): ### Core parameters (safe defaults; override in config.mk, rename config.mk.sample to config.mk and apply the remaining values):
ARCH ?= amd64 ARCH ?= amd64
AUTOBUILD ?= 6.16.3+deb13-amd64 AUTOBUILD ?= 7.0.10+deb13-amd64
CONTROL ?= $(TIMESTAMP) CONTROL ?= $(TIMESTAMP)
DROPBEAR_VERSION ?= 2026.91 DROPBEAR_VERSION ?= 2026.91
SOPS_VERSION ?= 3.13.1 SOPS_VERSION ?= 3.13.1
@@ -63,6 +63,9 @@ define COMPOSE_AND
[[ -n '$(FLAG_DEBUG)' ]] && cmd+=( --debug ) [[ -n '$(FLAG_DEBUG)' ]] && cmd+=( --debug )
[[ -n '$(FLAG_DHCP_CENTURION)' ]] && cmd+=( --dhcp-centurion ) [[ -n '$(FLAG_DHCP_CENTURION)' ]] && cmd+=( --dhcp-centurion )
[[ -n '$(FLAG_TRIXIE)' ]] && cmd+=( --trixie ) [[ -n '$(FLAG_TRIXIE)' ]] && cmd+=( --trixie )
[[ -n '$(PRIMORDIAL_URL)' ]] && cmd+=( --primordial-url '$(PRIMORDIAL_URL)' )
[[ -n '$(PRIMORDIAL_KEY)' ]] && cmd+=( --primordial-key '$(PRIMORDIAL_KEY)' )
[[ -n '$(PRIMORDIAL_SSH_PORT)' ]] && cmd+=( --primordial-ssh '$(PRIMORDIAL_SSH_PORT)' )
[[ -n '$(PROVIDER_NETCUP_IPV6)' ]] && cmd+=( --provider-netcup-ipv6 '$(PROVIDER_NETCUP_IPV6)' ) [[ -n '$(PROVIDER_NETCUP_IPV6)' ]] && cmd+=( --provider-netcup-ipv6 '$(PROVIDER_NETCUP_IPV6)' )
[[ -n '$(RENICE)' ]] && cmd+=( --renice-priority '$(RENICE)' ) [[ -n '$(RENICE)' ]] && cmd+=( --renice-priority '$(RENICE)' )
if [[ -n '$(REIONICE_CLASS)' && -n '$(REIONICE_PRIO)' ]]; then if [[ -n '$(REIONICE_CLASS)' && -n '$(REIONICE_PRIO)' ]]; then
+490 -3
View File
@@ -13,6 +13,12 @@
set -Ceuo pipefail set -Ceuo pipefail
umask 0077 umask 0077
declare -gx VAR_RDNS_DOMAIN="" # Forward-confirmed reverse DNS domain.
declare -gx VAR_RDNS_IPV4="" # IPv4 address used for RDNS verification.
declare -gx VAR_RDNS_NORMALIZED="" # RDNS domain normalized for Primordial branch names.
declare -gx VAR_PRIMORDIAL_KEY="" # Primordial SSH identity filename.
declare -gx VAR_PRIMORDIAL_SSH_PORT="" # Primordial SSH port.
declare -gx VAR_PRIMORDIAL_URL="" # Primordial HTTPS Git URL.
declare -grx VAR_SEMAPHORE="/root/cdi.ciss" # Semaphore to appear. declare -grx VAR_SEMAPHORE="/root/cdi.ciss" # Semaphore to appear.
declare -girx VAR_TIMEOUT=3600 # Semaphore timer in seconds. declare -girx VAR_TIMEOUT=3600 # Semaphore timer in seconds.
@@ -90,6 +96,472 @@ net_wait() {
# shellcheck disable=SC2034 # shellcheck disable=SC2034
readonly -f net_wait readonly -f net_wait
#######################################
# Validate an IPv4 address.
# Globals:
# None
# Arguments:
# $1: IPv4 address
# Returns:
# 0: valid IPv4 address
# 1: invalid IPv4 address
#######################################
is_ipv4() {
### Declare Arrays, HashMaps, and Variables.
declare -r var_ip="${1:-}"
declare -a ary_octets=()
declare var_octet=""
[[ "${var_ip}" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]] || return 1
IFS='.' read -r -a ary_octets <<< "${var_ip}"
for var_octet in "${ary_octets[@]}"; do
if ! ((10#${var_octet} <= 255)); then
return 1
fi
done
return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f is_ipv4
#######################################
# Validate a DNS domain name returned by RDNS.
# Globals:
# None
# Arguments:
# $1: domain name
# Returns:
# 0: valid domain name
# 1: invalid domain name
#######################################
is_dns_name() {
### Declare Arrays, HashMaps, and Variables.
declare -r var_name="${1:-}"
[[ "${#var_name}" -le 253 ]] || return 1
[[ "${var_name}" =~ ^[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)+$ ]] \
|| return 1
return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f is_dns_name
#######################################
# Retrieve and forward-confirm reverse DNS for the active IPv4 route.
# Globals:
# VAR_RDNS_DOMAIN
# VAR_RDNS_IPV4
# Arguments:
# $1: module log file
# Returns:
# 0: on confirmed RDNS
# 1: on missing or unconfirmed RDNS
#######################################
# retrieve_rdns() intentionally probes optional resolver tools and validation helpers inside conditionals.
# shellcheck disable=SC2310,SC2312
retrieve_rdns() {
### Declare Arrays, HashMaps, and Variables.
declare -r var_log="${1:-}"
declare -a ary_a=()
declare -a ary_rdns=()
declare -a ary_targets=()
declare var_a="" var_ipv4="" var_rdns="" var_target=""
VAR_RDNS_DOMAIN=""
VAR_RDNS_IPV4=""
mapfile -t ary_targets < <(
getent ahostsv4 git.coresecret.dev 2>/dev/null \
| awk '/^([0-9]{1,3}\.){3}[0-9]{1,3}[[:space:]]/ && !seen[$1]++ { print $1 }'
)
ary_targets+=( "1.1.1.1" "9.9.9.9" "8.8.8.8" )
if command -v ip >/dev/null 2>&1; then
for var_target in "${ary_targets[@]}"; do
if var_ipv4="$(
ip -o -4 route get "${var_target}" 2>/dev/null \
| awk '{ for (i = 1; i <= NF; i++) { if ($i == "src") { print $(i + 1); exit } } }'
)" && is_ipv4 "${var_ipv4}"; then
break
fi
var_ipv4=""
done
if [[ -z "${var_ipv4}" ]]; then
mapfile -t ary_targets < <(
ip -o -4 addr show scope global up 2>/dev/null \
| awk '{ split($4, addr, "/"); if (!seen[addr[1]]++) { print addr[1] } }'
)
for var_target in "${ary_targets[@]}"; do
if is_ipv4 "${var_target}"; then
var_ipv4="${var_target}"
break
fi
done
fi
fi
if [[ -z "${var_ipv4}" ]]; then
logger -t cdi-watcher "retrieve_rdns(): no active IPv4 address found; continuing without RDNS."
printf "Command: [retrieve_rdns] no active IPv4 address found; continuing without RDNS.\n" >> "${var_log}"
return 1
fi
if command -v dig >/dev/null 2>&1; then
mapfile -t ary_rdns < <(
dig +time=3 +tries=1 +short -x "${var_ipv4}" 2>/dev/null \
| sed 's/[.]$//' \
| awk 'NF && !seen[$0]++ { print $0 }'
)
fi
if ((${#ary_rdns[@]} == 0)) && command -v host >/dev/null 2>&1; then
mapfile -t ary_rdns < <(
host "${var_ipv4}" 2>/dev/null \
| awk '/domain name pointer/ { sub(/[.]$/, "", $NF); if (!seen[$NF]++) { print $NF } }'
)
fi
if ((${#ary_rdns[@]} == 0)); then
mapfile -t ary_rdns < <(
getent hosts "${var_ipv4}" 2>/dev/null \
| awk '{ for (i = 2; i <= NF; i++) { sub(/[.]$/, "", $i); if (!seen[$i]++) { print $i } } }'
)
fi
for var_rdns in "${ary_rdns[@]}"; do
var_rdns="${var_rdns%.}"
var_rdns="${var_rdns,,}"
if ! is_dns_name "${var_rdns}"; then
continue
fi
ary_a=()
if command -v dig >/dev/null 2>&1; then
mapfile -t ary_a < <(
dig +time=3 +tries=1 +short A "${var_rdns}" 2>/dev/null \
| awk '/^([0-9]{1,3}\.){3}[0-9]{1,3}$/ && !seen[$0]++ { print $0 }'
)
fi
if ((${#ary_a[@]} == 0)) && command -v host >/dev/null 2>&1; then
mapfile -t ary_a < <(
host -t A "${var_rdns}" 2>/dev/null \
| awk '/ has address / && !seen[$NF]++ { print $NF }'
)
fi
if ((${#ary_a[@]} == 0)); then
mapfile -t ary_a < <(
getent ahostsv4 "${var_rdns}" 2>/dev/null \
| awk '!seen[$1]++ { print $1 }'
)
fi
for var_a in "${ary_a[@]}"; do
if is_ipv4 "${var_a}" && [[ "${var_a}" == "${var_ipv4}" ]]; then
VAR_RDNS_IPV4="${var_ipv4}"
VAR_RDNS_DOMAIN="${var_rdns}"
logger -t cdi-watcher "retrieve_rdns(): confirmed IPv4 ${VAR_RDNS_IPV4} RDNS ${VAR_RDNS_DOMAIN}."
printf "Command: [retrieve_rdns] confirmed IPv4 [%s] RDNS [%s].\n" \
"${VAR_RDNS_IPV4}" "${VAR_RDNS_DOMAIN}" >> "${var_log}"
return 0
fi
done
done
logger -t cdi-watcher "retrieve_rdns(): no forward-confirmed RDNS for IPv4 ${var_ipv4}; continuing without RDNS."
printf "Command: [retrieve_rdns] no forward-confirmed RDNS for IPv4 [%s]; continuing without RDNS.\n" \
"${var_ipv4}" >> "${var_log}"
return 1
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f retrieve_rdns
#######################################
# Normalize a DNS domain into a Primordial branch name.
# Globals:
# None
# Arguments:
# $1: DNS domain name
# Returns:
# 0: on success
# 1: on invalid DNS domain
#######################################
normalize_rdns_domain() {
### Declare Arrays, HashMaps, and Variables.
declare var_domain="${1:-}"
var_domain="${var_domain%.}"
var_domain="${var_domain,,}"
# shellcheck disable=SC2310
is_dns_name "${var_domain}" || return 1
printf '%s\n' "${var_domain//./_}"
return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f normalize_rdns_domain
#######################################
# Convert an HTTPS Git URL into the SSH URL used for Primordial clone.
# Globals:
# None
# Arguments:
# $1: HTTPS Git URL
# $2: SSH port
# Returns:
# 0: on success
# 1: on invalid URL or port
#######################################
derive_ssh_git_url() {
### Declare Arrays, HashMaps, and Variables.
declare -r var_https_url="${1:-}"
declare -r var_ssh_port="${2:-}"
declare var_host="" var_path=""
if [[ ! "${var_https_url}" =~ ^https://([A-Za-z0-9.-]+)/([A-Za-z0-9._~/%+=:@,-]+\.git)$ ]]; then
return 1
fi
var_host="${BASH_REMATCH[1]}"
var_path="${BASH_REMATCH[2]}"
if [[ -z "${var_host}" || -z "${var_path}" || ! "${var_ssh_port}" =~ ^[0-9]+$ ]] \
|| ((10#${var_ssh_port} < 1 || 10#${var_ssh_port} > 65535)); then
return 1
fi
printf 'ssh://git@%s:%s/%s\n' "${var_host}" "${var_ssh_port}" "${var_path}"
return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f derive_ssh_git_url
#######################################
# Apply the Primordial overlay and create the CDI semaphore only on success.
# Globals:
# VAR_PRIMORDIAL_KEY
# VAR_PRIMORDIAL_SSH_PORT
# VAR_PRIMORDIAL_URL
# VAR_RDNS_DOMAIN
# VAR_RDNS_NORMALIZED
# VAR_SEMAPHORE
# Arguments:
# $1: module log file
# $2: CISS.debian.installer directory
# Returns:
# 0: on success or optional skip
# 1: on failed configured Primordial overlay
#######################################
apply_primordial_overlay() {
### Declare Arrays, HashMaps, and Variables.
declare -r var_log="${1:-}"
declare -r var_repo_dir="${2:-}"
declare -r var_overlay_dir="/root/git/overlay"
declare var_identity="" var_ssh_url="" var_rdns_normalized=""
if [[ -z "${VAR_PRIMORDIAL_URL}" && -z "${VAR_PRIMORDIAL_KEY}" && -z "${VAR_PRIMORDIAL_SSH_PORT}" ]]; then
logger -t cdi-watcher "Primordial overlay not configured; continuing with existing semaphore polling."
printf "Command: [apply_primordial_overlay] skipped; Primordial overlay not configured.\n" >> "${var_log}"
return 0
fi
if ! rm -f -- "${VAR_SEMAPHORE}"; then
logger -t cdi-watcher "Failed to remove existing CDI semaphore; aborting CDI autostart."
printf "Command: [rm -f -- %s] failed; aborting CDI autostart.\n" "${VAR_SEMAPHORE}" >> "${var_log}"
return 1
fi
if [[ -z "${VAR_PRIMORDIAL_URL}" || -z "${VAR_PRIMORDIAL_KEY}" || -z "${VAR_PRIMORDIAL_SSH_PORT}" || -z "${VAR_RDNS_DOMAIN}" ]]; then
logger -t cdi-watcher "Primordial overlay configuration incomplete; aborting CDI autostart."
printf "Command: [apply_primordial_overlay] failed; Primordial URL, key, SSH port, and RDNS domain are required.\n" >> "${var_log}"
return 1
fi
# shellcheck disable=SC2310
if ! var_rdns_normalized="$(normalize_rdns_domain "${VAR_RDNS_DOMAIN}")"; then
logger -t cdi-watcher "Primordial overlay RDNS branch derivation failed; aborting CDI autostart."
printf "Command: [normalize_rdns_domain %s] failed; aborting CDI autostart.\n" "${VAR_RDNS_DOMAIN}" >> "${var_log}"
return 1
fi
declare -gx VAR_RDNS_NORMALIZED="${var_rdns_normalized}"
# shellcheck disable=SC2310
if ! var_ssh_url="$(derive_ssh_git_url "${VAR_PRIMORDIAL_URL}" "${VAR_PRIMORDIAL_SSH_PORT}")"; then
logger -t cdi-watcher "Primordial HTTPS Git URL conversion failed; aborting CDI autostart."
printf "Command: [derive_ssh_git_url] failed for configured Primordial URL; aborting CDI autostart.\n" >> "${var_log}"
return 1
fi
var_identity="/root/.ssh/${VAR_PRIMORDIAL_KEY}"
if [[ ! -e "${var_identity}" ]]; then
logger -t cdi-watcher "Primordial SSH identity file is missing; aborting CDI autostart."
printf "Command: [test -e /root/.ssh/<primordial-key>] failed; aborting CDI autostart.\n" >> "${var_log}"
return 1
fi
if [[ ! -f "${var_identity}" ]]; then
logger -t cdi-watcher "Primordial SSH identity path is not a regular file; aborting CDI autostart."
printf "Command: [test -f /root/.ssh/<primordial-key>] failed; aborting CDI autostart.\n" >> "${var_log}"
return 1
fi
if [[ ! -r "${var_identity}" ]]; then
logger -t cdi-watcher "Primordial SSH identity file is not readable by root; aborting CDI autostart."
printf "Command: [test -r /root/.ssh/<primordial-key>] failed; aborting CDI autostart.\n" >> "${var_log}"
return 1
fi
if ! rm -rf -- "${var_overlay_dir}"; then
logger -t cdi-watcher "Failed to remove existing Primordial overlay directory; aborting CDI autostart."
printf "Command: [rm -rf -- %s] failed; aborting CDI autostart.\n" "${var_overlay_dir}" >> "${var_log}"
return 1
fi
if ! GIT_SSH_COMMAND="ssh -i ${var_identity} -p ${VAR_PRIMORDIAL_SSH_PORT}" \
git clone --branch "${VAR_RDNS_NORMALIZED}" "${var_ssh_url}" "${var_overlay_dir}"; then
logger -t cdi-watcher "Primordial overlay clone failed; aborting CDI autostart."
printf "Command: [git clone --branch %s <primordial-ssh-url> %s] failed; aborting CDI autostart.\n" \
"${VAR_RDNS_NORMALIZED}" "${var_overlay_dir}" >> "${var_log}"
rm -rf -- "${var_overlay_dir}" || true
return 1
fi
if [[ ! -d "${var_overlay_dir}/.preseed" ]]; then
logger -t cdi-watcher "Primordial overlay .preseed directory is missing; aborting CDI autostart."
printf "Command: [test -d %s/.preseed] failed; aborting CDI autostart.\n" "${var_overlay_dir}" >> "${var_log}"
return 1
fi
if [[ ! -d "${var_overlay_dir}/includes" ]]; then
logger -t cdi-watcher "Primordial overlay includes directory is missing; aborting CDI autostart."
printf "Command: [test -d %s/includes] failed; aborting CDI autostart.\n" "${var_overlay_dir}" >> "${var_log}"
return 1
fi
install -d -m 0700 "${var_repo_dir}/.preseed" "${var_repo_dir}/includes"
if ! rsync -av "${var_overlay_dir}/.preseed/" "${var_repo_dir}/.preseed/"; then
logger -t cdi-watcher "Primordial overlay .preseed rsync failed; aborting CDI autostart."
printf "Command: [rsync -av %s/.preseed/ %s/.preseed/] failed; aborting CDI autostart.\n" \
"${var_overlay_dir}" "${var_repo_dir}" >> "${var_log}"
return 1
fi
if ! rsync -av "${var_overlay_dir}/includes/" "${var_repo_dir}/includes"; then
logger -t cdi-watcher "Primordial overlay includes rsync failed; aborting CDI autostart."
printf "Command: [rsync -av %s/includes/ %s/includes] failed; aborting CDI autostart.\n" \
"${var_overlay_dir}" "${var_repo_dir}" >> "${var_log}"
return 1
fi
if ! install -m 0600 /dev/null "${VAR_SEMAPHORE}"; then
logger -t cdi-watcher "Primordial overlay applied but semaphore creation failed; aborting CDI autostart."
printf "Command: [install -m 0600 /dev/null %s] failed; aborting CDI autostart.\n" "${VAR_SEMAPHORE}" >> "${var_log}"
return 1
fi
logger -t cdi-watcher "Primordial overlay applied for branch ${VAR_RDNS_NORMALIZED}; CDI semaphore created."
printf "Command: [apply_primordial_overlay] executed for branch [%s].\n" "${VAR_RDNS_NORMALIZED}" >> "${var_log}"
return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f apply_primordial_overlay
####################################### #######################################
# Wrapper for loading CISS hardened Kernel Parameters. # Wrapper for loading CISS hardened Kernel Parameters.
# Globals: # Globals:
@@ -129,8 +601,7 @@ main() {
var_log="/root/.ciss/cdi/log/9999-cdi-starter_$(date +"%Y-%m-%d_%H-%M-%S").log" var_log="/root/.ciss/cdi/log/9999-cdi-starter_$(date +"%Y-%m-%d_%H-%M-%S").log"
touch "${var_log}" touch "${var_log}"
printf "CISS.debian.live.builder V9.14.022.2026.06.10 calling CISS.debian.installer ... \n" >> "${var_log}"
printf "CISS.debian.installer Master V9.14.020.2026.06.08 is up! \n" >> "${var_log}"
### Sleep a moment to settle boot artifacts. ### Sleep a moment to settle boot artifacts.
sleep 8 sleep 8
@@ -153,6 +624,12 @@ main() {
fi fi
printf "Command: [net_wait] executed.\n" >> "${var_log}" printf "Command: [net_wait] executed.\n" >> "${var_log}"
### Retrieve forward-confirmed reverse DNS.
printf "Command: [retrieve_rdns] to be executed ... \n" >> "${var_log}"
# shellcheck disable=SC2310
retrieve_rdns "${var_log}" || true
printf "Command: [retrieve_rdns] executed.\n" >> "${var_log}"
### apt update. ### apt update.
if ! apt-get update >> "${var_log}"; then if ! apt-get update >> "${var_log}"; then
@@ -179,6 +656,16 @@ main() {
cd "${var_repo_dir}" cd "${var_repo_dir}"
printf "Command: [git clone %s %s] executed.\n" "${var_repo_url}" "${var_repo_dir}" >> "${var_log}" printf "Command: [git clone %s %s] executed.\n" "${var_repo_url}" "${var_repo_dir}" >> "${var_log}"
### Apply Primordial overlay before allowing CDI autostart.
# shellcheck disable=SC2310
if ! apply_primordial_overlay "${var_log}" "${var_repo_dir}"; then
logger -t cdi-watcher "Primordial overlay failed; CDI autostart aborted before semaphore polling."
printf "Command: [apply_primordial_overlay] failed; CDI autostart aborted before semaphore polling.\n" >> "${var_log}"
exit 0
fi
### Poll up to VAR_TIMEOUT seconds for the semaphore to appear and be mode 0600. ### Poll up to VAR_TIMEOUT seconds for the semaphore to appear and be mode 0600.
for ((i=0; i<VAR_TIMEOUT; i++)); do for ((i=0; i<VAR_TIMEOUT; i++)); do
@@ -209,7 +696,7 @@ main() {
### Timeout reached without acceptable semaphore. ### Timeout reached without acceptable semaphore.
logger -t cdi-watcher "No valid semaphore ${VAR_SEMAPHORE} (mode 0600) within ${VAR_TIMEOUT}s; exiting idle." logger -t cdi-watcher "No valid semaphore ${VAR_SEMAPHORE} (mode 0600) within ${VAR_TIMEOUT}s; exiting idle."
printf "CISS.debian.installer Master V9.14.020.2026.06.08: No valid semaphore [%s] within [%s]s.\n" "${VAR_SEMAPHORE}" "${VAR_TIMEOUT}" >> "${var_log}" printf "CISS.debian.live.builder V9.14.022.2026.06.10: No valid semaphore [%s] within [%s]s.\n" "${VAR_SEMAPHORE}" "${VAR_TIMEOUT}" >> "${var_log}"
exit 0 exit 0
} }
+191
View File
@@ -0,0 +1,191 @@
#!/bin/bash
# SPDX-Version: 3.0
# SPDX-CreationInfo: 2026-06-11; WEIDNER, Marc S.; <msw@coresecret.dev>
# SPDX-ExternalRef: GIT https://git.coresecret.dev/msw/CISS.debian.live.builder.git
# SPDX-FileContributor: WEIDNER, Marc S.; Centurion Intelligence Consulting Agency
# SPDX-FileCopyrightText: 2024-2026; WEIDNER, Marc S.; <msw@coresecret.dev>
# SPDX-FileType: SOURCE
# SPDX-License-Identifier: LicenseRef-CNCL-1.1 OR LicenseRef-CCLA-1.1
# SPDX-LicenseComment: This file is part of the CISS.debian.installer.secure framework.
# SPDX-PackageName: CISS.debian.live.builder
# SPDX-Security-Contact: security@coresecret.eu
set -Ceuo pipefail
# shellcheck disable=SC1091,SC2034
declare TEST_ROOT=""
declare TEST_TMP=""
TEST_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
TEST_TMP="$(realpath "$(mktemp -d)")"
readonly TEST_ROOT TEST_TMP
declare -r ERR_BUILD_PATH=217
declare -r ERR_GUARD_SRCE=131
declare -r ERR_SANITIZING=133
declare -r ERR_SECRET_PATH=216
declare -r VAR_WORKDIR="${TEST_ROOT}"
declare VAR_TMP_SECRET="${TEST_TMP}/secret-root"
declare LOG_DEBUG=""
declare LOG_ERROR=""
declare LOG_VAR=""
declare VAR_EARLY_DEBUG="false"
declare ERRTRAP="true"
cleanup_test() {
chmod -R u+rwX "${TEST_TMP}" 2>/dev/null || true
rm -rf "${TEST_TMP}"
}
trap cleanup_test EXIT
guard_sourcing() {
return 0
}
# shellcheck source=../lib/lib_secret_validation.sh
. "${TEST_ROOT}/lib/lib_secret_validation.sh"
# shellcheck source=../lib/lib_build_directory.sh
. "${TEST_ROOT}/lib/lib_build_directory.sh"
# shellcheck source=../lib/lib_debug_sanitizer.sh
. "${TEST_ROOT}/lib/lib_debug_sanitizer.sh"
# shellcheck source=../lib/lib_trap_on_exit.sh
. "${TEST_ROOT}/lib/lib_trap_on_exit.sh"
fail() {
printf 'FAIL: %s\n' "$1" >&2
exit 1
}
expect_failure() {
declare description="$1"
shift
if "$@" >/dev/null 2>&1; then
fail "${description}"
fi
}
mkdir -m 0700 "${VAR_TMP_SECRET}"
printf 'safe-private-value\n' > "${VAR_TMP_SECRET}/safe.txt"
chmod 0400 "${VAR_TMP_SECRET}/safe.txt"
validate_secret_directory "${VAR_TMP_SECRET}" "test secret root" "false" || fail "safe secret root rejected"
validate_secret_filename "safe.txt" "test secret filename" || fail "safe secret filename rejected"
validate_secret_file "${VAR_TMP_SECRET}/safe.txt" "test secret file" || fail "safe secret file rejected"
validate_secret_absolute_file "${VAR_TMP_SECRET}/safe.txt" "test absolute secret file" \
|| fail "safe absolute secret file rejected"
expect_failure "relative external secret path accepted" \
validate_secret_absolute_file "secret-root/safe.txt" "test absolute secret file"
mkdir -m 0700 "${TEST_TMP}/external-secret-dir"
printf 'external-private-value\n' > "${TEST_TMP}/external-secret-dir/external.txt"
chmod 0400 "${TEST_TMP}/external-secret-dir/external.txt"
ln -s "${TEST_TMP}/external-secret-dir" "${TEST_TMP}/external-secret-dir-link"
expect_failure "external secret file through a symlinked parent accepted" \
validate_secret_absolute_file "${TEST_TMP}/external-secret-dir-link/external.txt" "test absolute secret file"
expect_failure "external secret directory through a symlinked parent accepted" \
validate_secret_absolute_directory "${TEST_TMP}/external-secret-dir-link" "test absolute secret directory"
declare secret_root_fs=""
secret_root_fs="$(secure_stat -f -c '%T' "${VAR_TMP_SECRET}")"
if [[ "${secret_root_fs}" != "tmpfs" && "${secret_root_fs}" != "ramfs" ]]; then
expect_failure "persistent secret staging area accepted" validate_secret_staging_area
fi
expect_failure "secret filename traversal accepted" validate_secret_filename "../safe.txt" "test secret filename"
expect_failure "absolute filename-only secret accepted" validate_secret_filename "/tmp/safe.txt" "test secret filename"
expect_failure "slash in filename-only secret accepted" validate_secret_filename "subdir/safe.txt" "test secret filename"
ln -s "${VAR_TMP_SECRET}" "${TEST_TMP}/secret-root-link"
expect_failure "secret-root symlink accepted" \
validate_secret_directory "${TEST_TMP}/secret-root-link" "test secret root" "false"
mkdir -m 0700 "${TEST_TMP}/unsafe-secret-root-mode"
chmod 0755 "${TEST_TMP}/unsafe-secret-root-mode"
expect_failure "broad secret-root permissions accepted" \
validate_secret_directory "${TEST_TMP}/unsafe-secret-root-mode" "test secret root" "false"
ln -s "${VAR_TMP_SECRET}/safe.txt" "${VAR_TMP_SECRET}/unsafe-link"
expect_failure "secret-file symlink accepted" validate_secret_file "${VAR_TMP_SECRET}/unsafe-link" "test secret file"
rm "${VAR_TMP_SECRET}/unsafe-link"
ln "${VAR_TMP_SECRET}/safe.txt" "${VAR_TMP_SECRET}/unsafe-hardlink"
expect_failure "hardlinked secret file accepted" validate_secret_file "${VAR_TMP_SECRET}/safe.txt" "test secret file"
rm "${VAR_TMP_SECRET}/unsafe-hardlink"
declare fake_secret='CISS-CANARY-[exact]-value'
declare expected_redaction=""
declare sanitisation_status=0
printf -v expected_redaction '%*s' "${#fake_secret}" ''
expected_redaction="${expected_redaction// /*}"
register_secret_value "${fake_secret}"
LOG_DEBUG="${TEST_TMP}/debug.log"
LOG_VAR="${TEST_TMP}/var.log"
LOG_ERROR="${TEST_TMP}/error.log"
printf 'before %s after\nunrelated line\n' "${fake_secret}" > "${LOG_DEBUG}"
printf 'unrelated vars\n' > "${LOG_VAR}"
printf 'unrelated error\n' > "${LOG_ERROR}"
chmod 0600 "${LOG_DEBUG}" "${LOG_VAR}" "${LOG_ERROR}"
sanitize_debug_logs || fail "debug-log sanitisation failed"
grep -Fq "${fake_secret}" "${LOG_DEBUG}" && fail "debug-log canary remained"
grep -Fq "${expected_redaction}" "${LOG_DEBUG}" || fail "expected exact-value redaction missing"
grep -Fq 'unrelated line' "${LOG_DEBUG}" || fail "unrelated debug content changed"
ln -s "${LOG_DEBUG}" "${TEST_TMP}/unsafe-debug-link"
(
LOG_DEBUG="${TEST_TMP}/unsafe-debug-link"
trap_on_exit 73 "test" 1 "test" "false"
) 2>/dev/null || sanitisation_status=$?
[[ ${sanitisation_status} -eq 73 ]] || fail "sanitisation failure masked the original exit status"
expect_failure "empty build-directory path accepted" validate_build_directory_path ""
expect_failure "root build-directory path accepted" validate_build_directory_path "/"
expect_failure "broad parent build-directory path accepted" validate_build_directory_path "/tmp"
expect_failure "secret root accepted as build directory" validate_build_directory_path "${VAR_TMP_SECRET}"
mkdir -m 0700 "${VAR_TMP_SECRET}/unsafe-build-child"
expect_failure "secret-root descendant accepted as build directory" \
validate_build_directory_path "${VAR_TMP_SECRET}/unsafe-build-child"
mkdir -m 0700 "${TEST_TMP}/unmarked"
expect_failure "build directory without marker accepted" validate_build_directory_marker "${TEST_TMP}/unmarked"
printf 'do-not-adopt\n' > "${TEST_TMP}/unmarked/content"
expect_failure "non-empty unmarked build directory adopted" initialize_build_directory "${TEST_TMP}/unmarked" unsafe_result
mkdir -m 0700 "${TEST_TMP}/unsafe-build-mode"
chmod 0777 "${TEST_TMP}/unsafe-build-mode"
expect_failure "unsafe build-directory permissions accepted" \
initialize_build_directory "${TEST_TMP}/unsafe-build-mode" unsafe_result
mkdir -m 0700 "${TEST_TMP}/marker-link-dir"
printf '%s\n' "${TEST_TMP}/marker-link-dir" > "${TEST_TMP}/marker-target"
chmod 0400 "${TEST_TMP}/marker-target"
ln -s "${TEST_TMP}/marker-target" "${TEST_TMP}/marker-link-dir/.ciss-live-builder-owned"
expect_failure "symlinked builder-owned marker accepted" validate_build_directory_marker "${TEST_TMP}/marker-link-dir"
mkdir -m 0700 "${TEST_TMP}/marker-hardlink-dir"
printf '%s\n' "${TEST_TMP}/marker-hardlink-dir" > "${TEST_TMP}/marker-hardlink-target"
chmod 0400 "${TEST_TMP}/marker-hardlink-target"
ln "${TEST_TMP}/marker-hardlink-target" "${TEST_TMP}/marker-hardlink-dir/.ciss-live-builder-owned"
expect_failure "hardlinked builder-owned marker accepted" validate_build_directory_marker "${TEST_TMP}/marker-hardlink-dir"
mkdir -m 0700 "${TEST_TMP}/marker-extra-content-dir"
printf '%s\nunexpected\n' "${TEST_TMP}/marker-extra-content-dir" \
> "${TEST_TMP}/marker-extra-content-dir/.ciss-live-builder-owned"
chmod 0400 "${TEST_TMP}/marker-extra-content-dir/.ciss-live-builder-owned"
expect_failure "builder-owned marker with extra content accepted" \
validate_build_directory_marker "${TEST_TMP}/marker-extra-content-dir"
ln -s "${TEST_TMP}/unmarked" "${TEST_TMP}/build-link"
expect_failure "build-directory symlink accepted" validate_build_directory_path "${TEST_TMP}/build-link"
declare validated_build_dir=""
initialize_build_directory "${TEST_TMP}/owned-build" validated_build_dir || fail "safe builder-owned directory rejected"
validate_build_directory_marker "${validated_build_dir}" || fail "builder marker rejected"
mkdir "${validated_build_dir}/subdir"
printf 'remove me\n' > "${validated_build_dir}/artifact"
printf 'remove me too\n' > "${validated_build_dir}/.hidden-artifact"
printf 'nested\n' > "${validated_build_dir}/subdir/nested"
clean_build_directory_contents "${validated_build_dir}" || fail "safe builder-owned cleanup failed"
validate_build_directory_marker "${validated_build_dir}" || fail "builder marker removed by cleanup"
[[ -z "$(find "${validated_build_dir}" -mindepth 1 ! -name '.ciss-live-builder-owned' -print -quit)" ]] \
|| fail "builder-owned cleanup left unexpected content"
mkdir -m 0700 "${TEST_TMP}/outside-build"
mkdir "${TEST_TMP}/outside-build/includes.chroot"
ln -s "${TEST_TMP}/outside-build" "${validated_build_dir}/config"
expect_failure "cleanup subpath through a symlinked parent accepted" \
validate_build_directory_subpath "${validated_build_dir}" "config/includes.chroot" unsafe_subpath
printf 'PASS: secret validation, debug sanitisation, and build cleanup guards\n'
+1 -1
View File
@@ -25,7 +25,7 @@ declare -grx VAR_GIT_HEAD_FULL="$(git rev-parse HEAD)"
declare -grx VAR_HOST="$(uname -n)" declare -grx VAR_HOST="$(uname -n)"
declare -grx VAR_ISO8601="$(date -u -d "@${VAR_DATE_EPOCH}" '+%Y-%m-%dT%H:%M:%SZ')" declare -grx VAR_ISO8601="$(date -u -d "@${VAR_DATE_EPOCH}" '+%Y-%m-%dT%H:%M:%SZ')"
declare -grx VAR_SYSTEM="$(uname -mnosv)" declare -grx VAR_SYSTEM="$(uname -mnosv)"
declare -grx VAR_VERSION="Master V9.14.020.2026.06.08" declare -grx VAR_VERSION="Master V9.14.022.2026.06.10"
declare -grx VAR_VER_BASH="$(bash --version | head -n1 | awk '{ declare -grx VAR_VER_BASH="$(bash --version | head -n1 | awk '{
# Print $4 and $5; include $6 only if it exists # Print $4 and $5; include $6 only if it exists
out = $4 out = $4
+6
View File
@@ -28,12 +28,16 @@ touch "${LOG_ERROR}" && chmod 0600 "${LOG_ERROR}"
declare -g __umask="" declare -g __umask=""
declare -g VAR_ARCHITECTURE="" declare -g VAR_ARCHITECTURE=""
declare -g VAR_ARG_SANITIZED=""
declare -g VAR_DROPBEAR_VERSION="2026.91" declare -g VAR_DROPBEAR_VERSION="2026.91"
declare -g VAR_HANDLER_BUILD_DIR="" declare -g VAR_HANDLER_BUILD_DIR=""
declare -g VAR_HANDLER_CDI="false" declare -g VAR_HANDLER_CDI="false"
declare -g VAR_HANDLER_NETCUP_IPV6="false" declare -g VAR_HANDLER_NETCUP_IPV6="false"
declare -g VAR_HANDLER_SPLASH="" declare -g VAR_HANDLER_SPLASH=""
declare -g VAR_HASHED_PWD="" declare -g VAR_HASHED_PWD=""
declare -g VAR_PRIMORDIAL_KEY=""
declare -g VAR_PRIMORDIAL_SSH_PORT=""
declare -g VAR_PRIMORDIAL_URL=""
declare -g VAR_SCRIPT_SUCCESS="false" declare -g VAR_SCRIPT_SUCCESS="false"
declare -g VAR_SOPS_VERSION="3.13.1" declare -g VAR_SOPS_VERSION="3.13.1"
declare -g VAR_SSHFP="false" declare -g VAR_SSHFP="false"
@@ -88,6 +92,8 @@ declare -gir ERR__SSH__PORT=212 # --ssh-port MUST be an integer between '1' and
declare -gir ERR_ARG_MSMTCH=213 # Wrong Number of optional Arguments provided declare -gir ERR_ARG_MSMTCH=213 # Wrong Number of optional Arguments provided
declare -gir ERR_DROPBEAR_V=214 # --dropbear-version MUST match the bundled Dropbear tarball version format declare -gir ERR_DROPBEAR_V=214 # --dropbear-version MUST match the bundled Dropbear tarball version format
declare -gir ERR__SOPS__VER=215 # --sops-version MUST match the upstream SOPS semantic version format declare -gir ERR__SOPS__VER=215 # --sops-version MUST match the upstream SOPS semantic version format
declare -gir ERR_SECRET_PATH=216 # Unsafe secret root, filename, or file.
declare -gir ERR_BUILD_PATH=217 # Unsafe build-directory path or marker.
declare -gir ERR_SECRETSSYM=251 # VAR_TMP_SECRET is a symlink. declare -gir ERR_SECRETSSYM=251 # VAR_TMP_SECRET is a symlink.
declare -gir ERR_NOTABSPATH=252 # Not an absolute path declare -gir ERR_NOTABSPATH=252 # Not an absolute path
declare -gir ERR_INVLD_CHAR=253 # Invalid Character declare -gir ERR_INVLD_CHAR=253 # Invalid Character