Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
26 changes: 26 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
version: 2
updates:
- package-ecosystem: cargo
directory: /
schedule:
interval: weekly
open-pull-requests-limit: 10
groups:
# Keep the closely coupled GUI crates together. The local egui-winit
# patch still needs manual review; see docs/dependency-security.md.
egui:
patterns:
- eframe
- egui*
- epaint*
- emath
- ecolor

- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
groups:
github-actions:
patterns:
- "*"
42 changes: 42 additions & 0 deletions .github/workflows/dependency-security.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: Dependency security

on:
pull_request:
push:
branches: ["**"]
schedule:
# Find newly published advisories even when the lockfile has not changed.
- cron: "23 3 * * *"
workflow_dispatch:
workflow_call:

permissions:
contents: read

jobs:
dependencies:
name: ${{ matrix.tool }}
runs-on: ubuntu-latest
timeout-minutes: 20
strategy:
fail-fast: false
matrix:
include:
- tool: cargo-audit
version: 0.22.2
command: cargo audit --file Cargo.lock
- tool: cargo-deny
version: 0.20.2
command: cargo deny --locked check
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
with:
persist-credentials: false

- uses: dtolnay/rust-toolchain@6bed0761d98439e5a578e2877258200ad565ba87 # stable

- name: Install ${{ matrix.tool }}
run: cargo install --locked ${{ matrix.tool }} --version ${{ matrix.version }}

- name: Check dependencies
run: ${{ matrix.command }}
8 changes: 7 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,13 @@ env:
WINGET_PACKAGE_ID: CodeZeno.ClaudeCodeUsageMonitor

jobs:
dependency-security:
uses: ./.github/workflows/dependency-security.yml
permissions:
contents: read

build:
needs: dependency-security
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
Expand All @@ -26,7 +32,7 @@ jobs:
run: cargo test --locked updater

- name: Build release binary
run: cargo build --release
run: cargo build --release --locked

- name: Create GitHub Release
uses: softprops/action-gh-release@v2
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,9 @@ cargo build --release

The executable will be created at `target\release\claude-code-usage-monitor.exe`.

See [dependency security](docs/dependency-security.md) for automated dependency
updates, CI security checks, and the commands to run those checks locally.

## License

Licensed under the [MIT License](LICENSE).
49 changes: 49 additions & 0 deletions deny.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Policy for the shipped Windows application, including build/dev dependencies.
# cargo-audit separately checks every package in Cargo.lock on all platforms.
[graph]
targets = ["x86_64-pc-windows-msvc"]

[advisories]
yanked = "deny"
unmaintained = "all"
unsound = "all"
unused-ignored-advisory = "deny"
# Owner: repository maintainers. Review by 2026-10-23, or on an oxifont update.
# Build-time only: oxifont processes font bytes bundled by locked dependencies.
# No patched release exists; migrate/update the subsetter to remove this crate.
# Keep cargo-audit's warning visible. This does not ignore future vulnerabilities.
ignore = [
{ id = "RUSTSEC-2026-0192", reason = "ttf-parser 0.25.1 is unmaintained; required by oxifont-subset/oxifont-parser 0.2.2 for build-time bundled font subsetting. Owner: repository maintainers; review by 2026-10-23. See docs/dependency-security.md." },
]

[licenses]
confidence-threshold = 0.93
allow = [
"Apache-2.0",
"BSL-1.0",
"CDLA-Permissive-2.0",
"ISC",
"MIT",
"Unicode-3.0",
"Zlib",
]

# Limit the existing font and file-level copyleft licenses to these crates.
[[licenses.exceptions]]
name = "epaint_default_fonts"
allow = ["OFL-1.1", "Ubuntu-font-1.0"]

[[licenses.exceptions]]
name = "option-ext"
allow = ["MPL-2.0"]

[bans]
# The GUI/Windows dependency graph currently needs multiple crate versions.
multiple-versions = "warn"
wildcards = "deny"

[sources]
unknown-registry = "deny"
unknown-git = "deny"
allow-registry = ["https://github.com/rust-lang/crates.io-index"]
allow-git = []
68 changes: 68 additions & 0 deletions docs/dependency-security.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Dependency security

Dependabot checks Cargo dependencies and GitHub Actions weekly and opens update
pull requests. Review the manifest and lockfile diff and run the Windows tests
before merging. The egui family is grouped because its versions are coupled.

The `Dependency security` workflow runs on pull requests, branch pushes, a daily
schedule, and manual dispatch. The release workflow calls the same checks and
waits for them before building or publishing. Checks use read-only repository
permissions and do not require secrets.

- `cargo audit` checks the entire committed `Cargo.lock` against the current
RustSec advisory database and fails on known vulnerabilities. Informational
warnings remain visible in its output.
- `cargo deny --locked check` checks advisories, licenses, bans, and sources for
`x86_64-pc-windows-msvc`, including build and development dependencies. Known
vulnerabilities, unsound or unmaintained dependencies, yanked versions,
unapproved licenses, wildcard requirements, and unapproved registry/Git
sources fail the check. Multiple crate versions produce warnings.

The scanners fetch current advisory data on each run. Fix a finding by updating
or replacing the dependency where possible. Any necessary exception must be
narrow and document the advisory, applicability, owner, and review date; do not
disable a category of checks to make CI pass. License exceptions in `deny.toml`
are limited to the existing bundled fonts and `option-ext`.

### Current advisory exception

[`RUSTSEC-2026-0192`](https://rustsec.org/advisories/RUSTSEC-2026-0192.html)
reports that `ttf-parser` is unmaintained, with no patched release. Version
0.25.1 is pulled in by `oxifont-subset`/`oxifont-parser` 0.2.2, the latest
available releases when this policy was added. This is a build dependency:
`build.rs` subsets the Ubuntu and Lucide font bytes bundled by locked crates;
it does not parse user-provided fonts at runtime through this dependency.

`deny.toml` temporarily excepts only this advisory. `cargo audit` still displays
its warning, and future vulnerability advisories remain blocking. The repository
maintainers own reviewing this exception by **2026-10-23**, or sooner when
oxifont updates. Update or replace the subsetter to remove `ttf-parser`, then
remove the exception; cargo-deny rejects unused advisory exceptions. The review
date is a maintenance reminder, not an automatically enforced expiration.

## Run locally

Use the same scanner versions as `.github/workflows/dependency-security.yml`:

```powershell
cargo install --locked cargo-audit --version 0.22.2
cargo install --locked cargo-deny --version 0.20.2
cargo audit --file Cargo.lock
cargo deny --locked check
```

Scanner versions are pinned in the workflow and must be updated there and in
these commands together; Dependabot's Cargo updates cover application manifests,
not `cargo install` commands. The security workflow's GitHub Action revisions
are pinned to commits and covered by the GitHub Actions updater. Require both
scanner checks in branch protection if merges must be blocked; that repository
setting is separate from the workflow files.

## Vendored dependency

`vendor/egui-winit` is a local patch and is not automatically refreshed by
Dependabot. When the egui/eframe family changes, follow
[`vendor/egui-winit/PATCH.md`](../vendor/egui-winit/PATCH.md) to update the matching
upstream source, reapply the text-only clipboard changes, and verify the feature
graph. Review upstream security fixes for this copy explicitly: registry
advisories and source allowlists do not validate locally modified source code.
Loading