Repository navigation
Fix v1.5.0 startup, safe create_ap lifecycle, passphrase off the command line (phase 1 of #1) - #2
Merged
Merged
Conversation
A Windows checkout with core.autocrlf=true converts every script to CRLF, which breaks them on Linux and makes ShellCheck report ~1,400 errors. .gitattributes pins LF for every text file; .editorconfig keeps editors consistent with the existing indentation. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
v1.5.0 set PrivateTmp=false while keeping ProtectSystem=strict. Per systemd.exec(5), /tmp is only writable under ProtectSystem=strict when PrivateTmp= is enabled, so create_ap's `mktemp -d /tmp/create_ap.*` fails and the hotspot cannot start. - PrivateTmp=true again (also wipes stale create_ap dirs on stop) - RuntimeDirectory=fiero-hotspot (0700) for per-instance state - ReadWritePaths=-/etc/NetworkManager so create_ap can mark the virtual AP interface unmanaged - restore CAP_CHOWN and CAP_SYS_RESOURCE (dnsmasq; pam_limits in the sudo session used for notifications) - drop RestrictRealtime=true, which the README documents as breaking PAM Client lease lookup (the reason PrivateTmp was disabled) is reworked in the following commit so it no longer needs a shared /tmp. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Cleanup used to send `create_ap --stop` (which only signals and returns) and then immediately rm -rf every /tmp/create_ap* and delete every ap* interface on the system. That raced create_ap's own cleanup - which restores ip_forward from /tmp/create_ap.common.conf - and could leave the laptop routing packets after the hotspot was "off". It also killed hotspots started by other tools. Now Fiero tracks its own instance in /run/fiero-hotspot (PID, create_ap confdir, AP interface): - stop sends USR1 (create_ap's clean-exit signal) and waits up to 15s; only if create_ap hangs is it killed, then its own hostapd/dnsmasq (matched by confdir) are stopped and ip_forward is restored - only a leftover virtual ap* interface of ours is removed, never the physical card or another tool's interface - a create_ap already running on the interface (e.g. the linux-wifi-hotspot GUI) is left alone and start exits with a message - readiness uses the confdir's wifi_iface, so the --no-virt fallback (AP on the physical card, no ap* interface) is no longer torn down - `stop` run by hand while the systemd service owns the hotspot now delegates to `systemctl stop`, keeping the unit state correct - a failing `iw dev link` (driver reset, card removed) counts as "not connected" instead of looping forever - status/clients read the AP interface from the state dir; clients reads create_ap's lease file via /proc/<pid>/root so it works with the service's PrivateTmp; status shows foreground runs - clients: iw prints "signal: \t-45 [-47, -46] dBm"; the old regex expected a single space, so no client rows were ever printed - help/version no longer need root, the config or create_ap installed Verified with a create_ap/iw test double in a Debian container: start, status, clients, graceful stop, channel-drift restart, foreign instance, --no-virt and forced stop (27/27). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… file create_ap received the passphrase as a command-line argument, so any local user could read it with `ps aux` or /proc/<pid>/cmdline while the hotspot was up. create_ap supports `--config <file>`: with no positional arguments it takes WIFI_IFACE, INTERNET_IFACE, SSID and PASSPHRASE from the file. Fiero now writes /run/fiero-hotspot/create_ap.conf (umask 077) and deletes it as soon as the AP is live. create_ap reads that file with `read` without -r, which drops backslashes and trims surrounding whitespace. For an SSID/passphrase affected by that, Fiero keeps the old command-line behaviour and logs a warning instead of silently changing the password. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…eout Two behaviour bugs in fiero-prompt.sh, both reproduced with a fake notify-send/charger in a container (old code fails them, new passes): 1. The prompt held its flock for the whole 10s notification, so a second udev event (charger unplugged while "Start?" is open) could not get the lock and exited before the code that kills the stale prompt. That code was unreachable and the user could still start the hotspot on battery. The lock now only guards the debounce/state update, and the "nothing to do" early exits run after it, so the stale prompt is always cancelled. A prompt that was superseded while open also re-checks before acting. 2. When nobody answered, the hotspot started on its own, so a Wi-Fi network could begin broadcasting without consent (and right after install, because install.sh triggers udev). Timeout/dismiss now does nothing unless AUTO_START_ON_TIMEOUT='true' is set in the config. The unplug prompt still stops on timeout, which is the safe choice. Also drops an unused local (ShellCheck SC2034). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The sudoers rule was written straight into /etc/sudoers.d and only checked afterwards; if `visudo -c` failed, `set -e` stopped the script with the broken file in place and sudo stopped working system-wide. It is now written to /etc/sudoers.d/.fiero-hotspot.tmp (sudo ignores names containing a dot), validated, then renamed into place. - Refuse to run from a root shell: TARGET_USER used to fall back to root, routing prompts and sudoers to root. - Re-running the installer offers to keep /etc/fiero-hotspot.conf instead of asking for everything again and overwriting it. - Several Wi-Fi interfaces: ask which one is the upstream instead of silently taking the first. - Reject SSIDs/passwords with a backslash or surrounding spaces (create_ap cannot read them from the config file that keeps the password out of `ps`) and passwords outside printable ASCII (WPA2 requirement). - Replace `grep -P` (not available everywhere) with `LC_ALL=C grep`. - Works from any working directory (files are taken from the script's dir). - Writes AUTO_START_ON_TIMEOUT='false' and explains the new prompt default. Verified in a Debian container with fake iw/udevadm/systemctl and the real visudo (19/19 scenarios). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e other tools' files alone - stop a hotspot started by hand (not a systemd unit) through `fiero-hotspot stop`, so create_ap can restore ip_forward/NetworkManager - --keep-config keeps /etc/fiero-hotspot.conf for a later reinstall - remove /run/fiero-hotspot and the sudoers temp file - no longer rm -rf every /tmp/create_ap*: create_ap cleans its own dirs, the service's live in its private /tmp, the rest may belong to the linux-wifi-hotspot GUI or another create_ap Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
test_harness.sh: - when upstream is on an unsupported channel the start/stop lifecycle was skipped, teardown was set to PASS and the run exited 0 - a release could go out without the hotspot ever being started (this is how the v1.5.0 PrivateTmp regression slipped through). A skipped lifecycle is now reported as INCOMPLETE with exit code 2. - phase 9 tests the installed /usr/local/bin/fiero-hotspot; it now fails loudly when that copy differs from the repository copy. audit.sh: - printed "Zero defects found" even when shellcheck/systemd-analyze/ gitleaks were not installed. Skipped checks now make the result INCOMPLETE (exit 2); a missing or EXPOSED/UNSAFE systemd score fails. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- version badge, lifecycle diagram (systemd-run, create_ap --config), stop/cleanup behaviour, prompt lock and timeout default - hardening: 4.2 OK exposure, why PrivateTmp=true and ReadWritePaths=-/etc/NetworkManager are needed; CAP_NET_ADMIN is not for namespaces (create_ap uses none) - passphrase handling (config file, when it falls back to argv) - AUTO_START_ON_TIMEOUT, uninstall --keep-config, harness exit code 2 - SECURITY.md: supported 1.5.x, fiero-prompt sources the config as the user (not root), sudoers validation - CHANGELOG.md in Keep a Changelog format Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Sep 27, 2026
Fiero1186
approved these changes
Sep 27, 2026
Fiero1186
left a comment
Owner
There was a problem hiding this comment.
Approved Phase 1 critical fixes and lifecycle hardening.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #1 (phase 1: fix what's broken).
This PR fixes the critical and high findings from the audit in #1. Each commit covers one topic, so it can be reviewed commit by commit.
What changes and why
chore: enforce LF line endings.gitattributes+.editorconfig. A Windows clone no longer turns every script into CRLF (which breaks them on Linux).fix(service)PrivateTmp=false+ProtectSystem=strictmade/tmpread-only, socreate_apcould not create its working folder. Brings backPrivateTmp=trueand theCAP_CHOWN/CAP_SYS_RESOURCEcapabilities, dropsRestrictRealtime, addsReadWritePaths=-/etc/NetworkManagerandRuntimeDirectory=fiero-hotspot. Exposure score: 4.2 OK (v1.4.1: 5.7).fix(daemon)create_ap(state in/run/fiero-hotspot). Stop sendsUSR1and waits forcreate_ap's own cleanup (which restoresip_forward), instead of deleting its files immediately. Other tools' hotspots are never touched. The--no-virtfallback is detected correctly. A failingiwcounts as "disconnected".help/versionwork without root or config. Also fixesclients, which never listed any device (realiwprintssignal: <tab>-45 [...] dBm).fix(security)create_ap --configvia a0600file that is deleted once the AP is up, so it is no longer visible inps.fix(prompt)AUTO_START_ON_TIMEOUT='true'.fix(installer)sudo. The installer refuses to run from a root shell, offers to keep an existing config, asks which Wi-Fi card to use when there are several, and dropsgrep -P.fix(uninstall)--keep-config, stops a manually started hotspot cleanly, and no longer deletes other tools'/tmp/create_ap*.test:2, "incomplete"), and warns if the installed copy is older than the repo.audit.shno longer says "Zero defects" when tools are missing.docs:CHANGELOG.md.Behaviour changes users will notice
AUTO_START_ON_TIMEOUT='true'in/etc/fiero-hotspot.conffor the old behaviour. (The "Stop?" prompt still stops on timeout.)sudo fiero-hotspot startexits with a message if anothercreate_apis already running on the interface, instead of killing it.create_ap's config reader would silently change them. An existing config like that still works, but falls back to the command line with a warning.sudo ./install.shmust be run withsudofrom the desktop user, not from a root shell.How it was verified
systemd-analyze --offline security: 4.2 OK.clientsbug, I also ran the same scenarios against the currentmain, where they fail as described in Full audit: v1.5.0 likely can't start the hotspot + a plan to make Fiero production-ready (happy to send PRs) #1.create_apbehaviour Fiero relies on (--config,USR1clean exit,<confdir>/pidandwifi_iface,--no-virtfallback,ip_forwardrestore) was checked in the upstream source (linux-wifi-hotspotcreate_ap).🧪 Hardware test checklist (please run on your laptop before merging)
Then by hand:
sudo systemctl start fiero-hotspot→ phone connects and has internetps aux | grep create_apdoes not show the passphrasesudo fiero-hotspot statusshows the AP interface and client countsudo fiero-hotspot clientslists the phone (MAC, signal, IP)sudo systemctl stop fiero-hotspot→cat /proc/sys/net/ipv4/ip_forwardis back to what it was before (usually0)iw devshows no leftoverap0journalctl -u fiero-hotspot -bhas no errorsIf anything fails, paste the journal here and I'll fix it on this branch.
🤖 Generated with Claude Code