Repository navigation
0.3.5: persistence AV engine, host persistence targets, Security removal, 153 recipes - #15
Merged
Merged
Conversation
…oval Bugs 2-6 from the 0.3.5 list, plus scanner coverage and the background resource helper. Antivirus - New `persistence` engine (10th): inspects launchd plists, shell startup files, cron drops, and systemd user units for payloads that run again later. Fires only on the payload (temp/hidden executables, download-exec, decode-exec, launchctl load, @reboot beacons), never on existence. - New `SecurityTargetKind::HostPersistence` so the engine sees real host state: ~/Library/LaunchAgents, ~/.config/systemd/user, and the shell-rc names in $HOME. Those rows are deliberately not removable, and get an "edit the line, not the file" remedy. Security removal (both UIs, same policy) - `SecurityRemoval` in cleanton-engine is now the single source of truth for which flagged packages are removable and how. The Slint app and the TUI both drive it, so they cannot disagree. - Slint: two-step arm/confirm/cancel, npm/pip via PackageManagers, else the executor's reviewed Trash path. ActionButton gains a `danger` tint. - TUI: [r] arms, [y] runs, [n] cancels; moving the cursor disarms. Background helper - Fix the whitespace-mangled disk/memory suggestions. A pressure event now names the top-3 reclaimable directories plus the Trash, measured against a 20k-entry budget so the walk can never stall the watcher. Recipes (141 -> 153) - 22 macOS-only recipes gain Linux ~/.cache alternatives. - 12 new: Edge/Brave/Vivaldi HTTP caches, Discord, node bundler caches, thumbnails, Trivy/Grype/Snyk, apt/snap/flatpak, Helm, Firebase emulators, Nim, Dune. All documented in doc/RECIPES.md. Slint fixes - Centring uses cross-axis-alignment (1.17) or a wrapper layout; `cross-axis-self-alignment` does not exist until Slint 1.18 and the tree pins 1.17.1. - Transient spinners/activity bar are conditional `if`, not `visible:false` (which still occupies layout). - Duplicate sets render per-copy rows with a set header, capped. Version 0.3.5. `scripts/check-ui-copy.py` guards user-visible copy and is wired into CI. Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
rustfmt (run as a parser check) found two things CI would have rejected: - persistence.rs: the download/decode-exec regexes used `r"..."` delimiters but their character classes contain a bare `"`, which terminated the raw string early. They are `r#"..."#` now. - security.rs: `PERSISTENCE_REMEDY` put the line-continuation backslash after `=` instead of inside the string literal. Then `cargo fmt` over every touched file. Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
- background.rs: drop the redundant `.into_iter()`; replace `push_str(&format!(..))` with plain appends. - security.rs: fold the two identical `return None` arms into one; move the host-persistence roots into `push_host_persistence_targets` so `discover_default_targets` stays under the line limit; compare file extensions with `Path::extension()` rather than a case-sensitive `ends_with`. Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
`builtin_recipe_self_tests_are_valid` pins the number of registered recipes so an unregistered recipe file (or a dangling registration) fails loudly. Adding 12 recipes invalidated it; the count is bumped by hand, as intended. Also removes the temporary workflow that mirrored clippy/test output into check annotations: the gates are readable now. Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
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.
Summary
Ninth pass at the 0.3.5 list. The headline is a new antivirus detection engine, wired so it actually inspects the machine, plus Security-tab removal that now exists in both UIs with one shared policy.
Nothing here has been compiled (no Rust toolchain in this sandbox) - this PR is the CI gateway:
cargo fmt --check,cargo clippy --workspace --all-targets --all-features -- -D warnings,cargo test --workspace --all-features,cargo audit.Antivirus: new
persistenceengineEvery other engine asks is this code malicious? This one asks has something already made itself at home? It inspects the four families of files whose only job is to run something later (launchd plists, shell startup files, cron drops, systemd user units) and fires only on the payload, never on existence:
PERSIST_LAUNCHD_DOWNLOAD_EXEC/_DECODE_EXEC- agent fetches or decodes and runs codePERSIST_LAUNCHD_TEMP_EXEC[_RUNATLOAD]- executable in/tmpor a hidden dirPERSIST_LAUNCHD_INLINE_SCRIPT--c/-ebody that downloads, decodes, or hidesPERSIST_SHELLRC_*-curl|sh, base64-eval,launchctl load, detachednohupPERSIST_CRON_*/PERSIST_SYSTEMD_*-@rebootand short-interval beacons24 unit tests, including the true negatives that matter: a normal LaunchAgent, an ordinary
.zshrc, a commented-out payload, a normal crontab, and a binary plist all stay clean. Dot-directories that are the ordinary home for user tooling (~/.local,~/.cargo,~/.cache) are explicitly not treated as hidden, which is where a naive version of this check produces false positives.Crucially it is wired to real host state: new
SecurityTargetKind::HostPersistencescans~/Library/LaunchAgents,~/.config/systemd/user, and the nine shell-rc names in$HOME. Without this the engine would only ever fire on packages that ship persistence files.Security removal, in both UIs from one policy
SecurityRemovalnow lives incleanton-engineas the single source of truth for what is removable and how, so the Slint app and the TUI cannot drift:PackageManagers::uninstall, everything else through the executor's reviewedtrash_suggestion.ActionButtongained adangertint so a destructive control never reads as an ordinary secondary button.[r]arms,[y]runs,[n]cancels; moving the cursor disarms. Same two paths, same engine copy.Host persistence files get no Remove button and an "open it and delete the flagged line" remedy. Trashing a user's
.zshrcto fix one line would be the wrong fix, so Cleanton refuses it in both UIs, with a defence-in-depth guard in the removal runner too.Background helper: disk/memory cleanup
resource_pressure_eventswas emitting whitespace-mangled strings ("...and clean <many spaces> caches") from broken string continuations. Replaced with a real measurement: a bounded (20k-entry budget) walk names the top-3 reclaimable directories plus the Trash.Edge-triggered as before, and the budget means it can never stall the watcher.
Recipes: 141 to 153
~/.cache/*alternatives (pip, poetry, Go, Deno, Cypress, Playwright, Yarn, Coursier, JetBrains, Firefox, Slack, Zoom, Spotify, Android Studio...). This is the biggest single fix for "the scanner misses things on Ubuntu".doc/RECIPES.md.Slint UI fixes
cross-axis-self-alignmentonly exists in Slint 1.18; this tree pins 1.17.1. Centring now usescross-axis-alignmenton the container or a wrapperHorizontalLayout { alignment: center; }.if, notvisible: false(which still occupies layout and shifts rows).Also
scripts/check-ui-copy.py(em-dash guard for user-visible copy) is wired into CI as acopyjob ahead ofaudit; it passes.Known gaps
walker.rs/metadata.rs, and guessing at them without a profiler seemed worse than leaving them.doc/*.mdprose still carries em dashes (the guard covers shipped UI copy, not developer docs).cleanton-antivirusis vendored fromrb-antivirus. The new engine is a self-containedengines/persistence.rstouching only three lines of upstreamengines/mod.rs, so it should sync cleanly in either direction.