Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
82aea2e
feat(rules): match patterns as anchored globs
Muawiya-contact Sep 5, 2026
f93d791
fix(rules): point the Firefox rule at cache2, not the whole profile
Muawiya-contact Sep 5, 2026
92d6f90
docs(rules): describe glob matching instead of substrings
Muawiya-contact Sep 5, 2026
fcba04c
docs(rules): show the rule-format example as globs
Muawiya-contact Sep 5, 2026
2457e41
fix(scanner): match excludes on normalized path components
Muawiya-contact Sep 5, 2026
eaa837b
feat(dedup): let callers restrict which entries are eligible
Muawiya-contact Sep 5, 2026
63ec0e0
fix(scanner): stop applying the dedup size floor to the whole walk
Muawiya-contact Sep 5, 2026
3885aba
refactor(dedup): give the eligibility predicate the entry index
Muawiya-contact Sep 5, 2026
3ebc255
fix(report): stop counting duplicated and protected bytes as reclaimable
Muawiya-contact Sep 5, 2026
03db5e6
fix(actions): fall back to copy+remove when restoring across filesystems
Muawiya-contact Sep 5, 2026
5027ae7
feat(actions): record every quarantine in a manifest
Muawiya-contact Sep 5, 2026
79dbd69
fix(app): stop the progress ticker from a guard that can't be skipped
Muawiya-contact Sep 5, 2026
e538dbb
feat(app): expose the quarantine manifest as commands
Muawiya-contact Sep 5, 2026
a06ba8a
feat(app): add a Quarantine panel with restore and purge
Muawiya-contact Sep 5, 2026
b2ca91b
style(app): style the quarantine panel
Muawiya-contact Sep 5, 2026
0e35ab3
feat(graph): build an impact graph from the scanned entries
Muawiya-contact Sep 5, 2026
5b8b4f1
feat(report): put the graph stage into the pipeline it was drawn in
Muawiya-contact Sep 5, 2026
7681893
chore(audit): document and ignore the advisories Tauri owns
Muawiya-contact Sep 5, 2026
2601ce8
docs(changelog): record the issue sweep
Muawiya-contact Sep 5, 2026
79d6df4
style: apply rustfmt to the issue sweep
Muawiya-contact Sep 5, 2026
1893d9c
feat(cli): print every reason, not just the matched rule
Muawiya-contact Sep 5, 2026
5076a8c
feat(app): show every reason on a finding row
Muawiya-contact Sep 5, 2026
62b999d
test(actions): tear the manifest fixture somewhere the spellchecker a…
Muawiya-contact Sep 5, 2026
4446b2f
fix(actions): record the quarantine before moving the file, not after
Muawiya-contact Sep 5, 2026
f953f27
fix(actions): refuse to restore over a file that is already there
Muawiya-contact Sep 5, 2026
1dbd9d0
fix(actions): serialize manifest access so a concurrent write isn't lost
Muawiya-contact Sep 5, 2026
0cbea3c
fix(actions): make purging an unused quarantine a no-op, not an error
Muawiya-contact Sep 5, 2026
f1dc89e
fix(graph): let a directory be more than one kind of project
Muawiya-contact Sep 5, 2026
0d576f2
fix(graph): answer a cancel during the graph stage
Muawiya-contact Sep 5, 2026
4e8d7c8
fix(report): keep risky bytes out of the reclaimable headline entirely
Muawiya-contact Sep 5, 2026
433b5c9
perf(scanner): fold the path while comparing instead of normalizing it
Muawiya-contact Sep 5, 2026
b9954f2
docs(changelog): note the two behaviours the review changed
Muawiya-contact Sep 5, 2026
bdcdbfa
test(actions): use a non-UTF-8 fixture the spellchecker can read
Muawiya-contact Sep 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions .cargo/audit.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# cargo-audit configuration.
#
# Everything listed below is an *informational* advisory (unmaintained or
# unsound), not a vulnerability. `cargo audit` reports zero vulnerabilities
# in this lockfile and this file does not change that: it only suppresses
# the ids named here, so a real advisory — including a new one against any
# of these same crates — still fails the run.
#
# Every id here reaches the lockfile through `tauri`, is a Linux-desktop
# dependency, and has no version that clears it. Diskern cannot fix them by
# updating; Tauri has to move off GTK3 first. Keeping them permanently red
# would train everyone to ignore a red audit, which is a worse security
# outcome than an explicit, reviewed list.
#
# The reasoning, the review cadence, and how to check whether an entry can
# be dropped are in docs/DEPENDENCY-AUTOMATION.md.
#
# Reviewed: 2026-09-05. Re-check when Tauri ships a GTK4/webkit6 runtime.

[advisories]
ignore = [
# ---------------------------------------------------------------
# gtk-rs GTK3 bindings — archived upstream, no successor at 0.18.
# tauri 2.11 -> gtk 0.18 / webkit2gtk / tao / muda. The successor
# (gtk4-rs) is not what Tauri v2 links against on Linux.
# ---------------------------------------------------------------
"RUSTSEC-2024-0413", # atk
"RUSTSEC-2024-0416", # atk-sys
"RUSTSEC-2024-0412", # gdk
"RUSTSEC-2024-0418", # gdk-sys
"RUSTSEC-2024-0411", # gdkwayland-sys
"RUSTSEC-2024-0417", # gdkx11
"RUSTSEC-2024-0414", # gdkx11-sys
"RUSTSEC-2024-0415", # gtk
"RUSTSEC-2024-0420", # gtk-sys
"RUSTSEC-2024-0419", # gtk3-macros

# glib 0.18.5 — unsound VariantStrIter. The fix landed in the 0.19
# line, which the archived GTK3 bindings above never moved to. The
# unsound function is glib's own GVariant iteration; nothing in
# Diskern calls it, and the GTK3 stack that does is the one Tauri
# drives.
"RUSTSEC-2024-0429",

# proc-macro-error 1.0.4 — unmaintained, pulled in by glib-macros
# 0.18.5, so it leaves with the GTK3 bindings above. Build-time
# proc macro: it does not ship in the binary.
"RUSTSEC-2024-0370",

# unic-* 0.9.0 — unmaintained, all five via urlpattern 0.3 ->
# tauri-utils. Pure Unicode tables, no network or filesystem
# surface, and replacing urlpattern is Tauri's call not ours.
"RUSTSEC-2025-0081", # unic-char-property
"RUSTSEC-2025-0075", # unic-char-range
"RUSTSEC-2025-0080", # unic-common
"RUSTSEC-2025-0100", # unic-ucd-ident
"RUSTSEC-2025-0098", # unic-ucd-version
]
33 changes: 32 additions & 1 deletion .github/workflows/audit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ on:
push:
branches: [main, master]
pull_request:
paths: [Cargo.lock]
# The ignore list is part of what the audit means, so editing it has to
# re-run the audit just as moving the lockfile does.
paths: [Cargo.lock, .cargo/audit.toml]

jobs:
# PR-time advisory check: annotates the changed lockfile inline so the
Expand All @@ -26,9 +28,23 @@ jobs:
checks: write # the action reports advisories as a check run
steps:
- uses: actions/checkout@v7

# `rustsec/audit-check` does not read .cargo/audit.toml — it only
# takes an `ignore` input — while the plain `cargo audit` in the job
# below does. Reading the ids out of the file keeps one source of
# truth instead of a second list that drifts from the first.
- name: Read the ignored advisories
id: ignored
run: |
ids=$(sed -n '/ignore *= *\[/,/^]/p' .cargo/audit.toml \
| grep -oE 'RUSTSEC-[0-9]{4}-[0-9]{4}' | paste -sd,)
echo "ids=$ids" >> "$GITHUB_OUTPUT"
echo "Ignoring: ${ids:-nothing}"

- uses: rustsec/audit-check@v2
with:
token: ${{ secrets.GITHUB_TOKEN }}
ignore: ${{ steps.ignored.outputs.ids }}

# Off-PR runs own a single tracking issue for the whole lockfile: one
# issue, kept current, rather than a fresh one every Monday.
Expand Down Expand Up @@ -57,6 +73,21 @@ jobs:
gh label create automated-issue --force \
--color C5DEF5 --description "Filed by a workflow, not a human"

# Visible, not silent: an ignore list nobody ever reads is how a
# suppressed advisory outlives the reason it was suppressed.
- name: Report the ignored advisories
run: |
{
echo "### Ignored advisories"
echo
sed -n '/ignore *= *\[/,/^]/p' .cargo/audit.toml \
| grep -oE 'RUSTSEC-[0-9]{4}-[0-9]{4}' | sed 's/^/- /'
echo
echo "Rationale and review cadence: docs/DEPENDENCY-AUTOMATION.md"
} >> "$GITHUB_STEP_SUMMARY"

# Reads .cargo/audit.toml from the working directory, so the ids
# above are already excluded from these counts.
- name: Run cargo audit
id: audit
run: |
Expand Down
34 changes: 34 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,44 @@ All notable changes to Diskern are documented here. The format follows
dependency-update PR when an advisory lands
- Community docs: contributing guide, code of conduct, security policy
- Per-section READMEs and an architecture overview
- Quarantine keeps a manifest, so a quarantined file can be restored
after the app is closed. The desktop app gained a Quarantine panel with
per-file restore and an explicit purge
- The impact graph reaches the report: a dependency store a live project
depends on is now marked more cautiously than an abandoned one, with
"referenced by N projects" as the evidence

### Changed

- Licensed under MIT
- Rule patterns are globs rather than substrings, so a rule stays inside
the directory it names. The Firefox rule covers `cache2` rather than
the whole profile, and `/tmp` no longer matches `~/tmp`
- Excludes are matched on whole path components after normalization, so
`/run` stops excluding `/runtime-data` and a differently-cased Windows
root still matches
- `min_file_size` moved from `ScanOptions` to `ReportOptions` as
`dedup_min_size`: it is a dedup knob and was hiding small files from
the whole report
- The reclaimable headline no longer counts the same bytes twice, and no
longer counts bytes on files the app refuses to act on
- `cargo audit` ignores seventeen unfixable transitive advisories from
Tauri's Linux GTK3 stack, listed with a reason each in
`.cargo/audit.toml`

### Fixed

- Restoring a quarantined file across filesystems no longer fails with
`EXDEV`
- Restore refuses when something is already at the original path, rather
than overwriting it — quarantine a cache, keep using the app, change
your mind, and the file the app rebuilt survives
- A file whose path can't be recorded in the manifest is not moved at
all, instead of being moved and then losing its record
- The scan progress ticker thread stops from a guard, so a panicking or
cancelled scan can't leave it emitting for the rest of the process
- Two files that flatten to the same quarantine name no longer overwrite
each other

## [0.1.0]

Expand Down
24 changes: 24 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ rayon = "1"
petgraph = "0.8"
dashmap = "6"

# Path matching for the rules database
globset = "0.4"

[profile.release]
lto = "thin"
strip = true
Loading
Loading