Skip to content

NeikiDev/jlab-desktop

JLab Desktop

License: MIT or Apache-2.0 Latest release CI Platforms

Native desktop client for the public JLab static JAR scanner. Drop a .jar (or a .zip, .mcpack, or .mrpack that contains one), the app uploads the file to the JLab API and shows the matched signatures grouped by severity. The HTTP upload runs in Rust, so no file bytes leak through the JavaScript layer.

image

Features

  • Drag and drop a .jar, .zip, .mcpack, or .mrpack. For container archives, the largest inner .jar is extracted and scanned.
  • Native multipart upload from Rust (reqwest + rustls). No browser fetch on the hot path.
  • Strict CSP. The webview can only talk to the Rust side. No outbound network from JavaScript.
  • Severity-grouped signature view (critical, high, medium, low, info) with file metadata, family tags, and a copy-friendly card layout.
  • Inline error banner with a live Retry-After countdown for rate limits (HTTP 429).
  • Local size validation (50 MB) and zip-magic check before any network call.
  • Cancellable scans, phase-aware progress UI with a live event log.
  • Local scan history (last 100 scans, summary only). Stored on your device, never uploaded. File bytes and signature payloads are not persisted. Each row also shows the folder the file was scanned from.
  • Optional folder watcher (opt-in): auto-scans new .jar files in folders you choose, with quarantine, system-tray, autostart, and configurable alert thresholds. See Folder watcher below.
  • In-app notification history. A bell icon in the top bar lists every native toast the watcher fires, so events the OS dropped or suppressed (Do Not Disturb, tray-minimized, AFK) still surface inside the app. Stored locally (last 100 entries, summary only), with mark-read and clear actions.
  • Small (well under 10 MB), starts fast, no analytics, no auth. The header status indicator pings jlab.threat.rip/api/public/heartbeat once on launch and then once a minute while the window is visible. Each scan also fetches jlab.threat.rip/api/public/threat-intel/<sha256> to enrich the report. See SECURITY.md for the full list of outbound endpoints.

Download

Pre-built installers are published on the GitHub Releases page on every push to main.

  • macOS (universal, Apple Silicon and Intel): JLab.Desktop_x.y.z_universal.dmg
  • Windows (setup, recommended for personal use): JLab.Desktop_x.y.z_x64-setup.exe
  • Windows (MSI, for IT-managed deployments): JLab.Desktop_x.y.z_x64_en-US.msi
  • Linux (Debian / Ubuntu): JLab.Desktop_x.y.z_amd64.deb
  • Linux (Fedora / RHEL / openSUSE): JLab.Desktop-x.y.z-1.x86_64.rpm
  • Linux (universal): JLab.Desktop_x.y.z_amd64.AppImage

On Windows the .exe setup is the easy path: per-user install, no admin prompt, normal wizard. Pick the .msi only if your IT department deploys it via Group Policy, Intune, or SCCM.

Download the latest release.

First run on macOS

The current builds are not yet signed with an Apple Developer ID. macOS Gatekeeper will warn that the app is from an unidentified developer or that the app is "damaged". This is expected for an unsigned binary downloaded from the internet.

Use one of these to allow the app:

  1. Right-click the app in Applications, choose Open, then confirm the dialog. macOS remembers the choice.

  2. Or remove the quarantine attribute from a terminal:

    xattr -dr com.apple.quarantine "/Applications/JLab Desktop.app"

Signed builds will land in a later release.

First run on Windows

The current builds are not signed with a code-signing certificate. Windows SmartScreen will show "Windows protected your PC". Click More info, then Run anyway. Windows remembers the choice for that file.

Signed builds will land in a later release.

First run on Linux

The Linux bundles are built on Ubuntu 24.04 against webkit2gtk-4.1 and target x86_64. Pick the format that matches your distro:

  • Debian / Ubuntu (and derivatives like Mint, Pop!_OS):

    sudo apt install ./JLab.Desktop_x.y.z_amd64.deb
  • Fedora / RHEL / openSUSE:

    sudo dnf install ./JLab.Desktop-x.y.z-1.x86_64.rpm
    # or, on openSUSE:
    sudo zypper install ./JLab.Desktop-x.y.z-1.x86_64.rpm
  • Anything else (Arch, NixOS, immutable distros, etc.) via AppImage:

    chmod +x JLab.Desktop_x.y.z_amd64.AppImage
    ./JLab.Desktop_x.y.z_amd64.AppImage

    AppImage needs FUSE on the host. On Ubuntu 24.04 install libfuse2t64; on older distros install libfuse2. On systems without FUSE you can extract and run instead:

    ./JLab.Desktop_x.y.z_amd64.AppImage --appimage-extract-and-run

The Linux builds are not signed. There is no Linux-equivalent of Gatekeeper or SmartScreen, so installs proceed normally, but verify the SHA-256 against the GitHub Release page if you want a signature-style check.

Updates

Updates are manual. The app checks the GitHub releases API once on startup and, if a newer version is available, shows a small "Update to vX" button in the header that opens the release page in your browser. Nothing is downloaded or installed automatically. To update, grab the new installer from the Releases page and run it. You can dismiss the update notice; it stays hidden until the next release.

How it works

  1. You pick a file (or drop one on the window).
  2. The Rust side validates the extension and reads the first bytes to confirm the file is really a zip archive.
  3. For container archives (.zip, .mcpack, .mrpack), the largest inner .jar by uncompressed size is extracted in memory. Inner jars over 50 MB are rejected up front, which guards against zip bombs.
  4. Rust uploads the jar to https://jlab.threat.rip/api/public/static-scan via multipart/form-data. No file bytes cross the IPC boundary into the webview.
  5. The frontend renders the response, grouped by severity.

The desktop client keeps the JavaScript side from making network calls. The Content Security Policy is connect-src ipc: http://ipc.localhost. Both sources are Tauri 2's IPC handler, neither is a public network egress, so any future fetch() to an external URL would fail at runtime.

Folder watcher

The folder watcher is an opt-in subsystem that auto-scans new .jar files (or supported containers) that appear in folders you choose. It is off by default and explicitly is not an antivirus: no driver, no kernel hooks, no on-access blocking. It is a plain user-space filesystem subscriber that reuses the same scan_jar HTTP pipeline as the manual scan.

What it does

  • Subscribes to OS filesystem events (FSEvents on macOS, ReadDirectoryChangesW on Windows, inotify on Linux) via the notify crate, with a 500 ms debounce.
  • Snapshots a baseline on watch start. Files that already exist when watching starts are ignored unless you click "scan all now" on a folder.
  • Queues qualifying files through a token-bucket rate limiter capped at 12 uploads per minute (the public API allows 15 / min / IP).
  • Coalesces native notifications inside a 4 s window so multiple hits produce one toast, not a flood.
  • Persists settings atomically as watcher-settings.json next to history.json.

Settings

Open the panel from the "folder watcher" card on the idle dashboard.

  • Notifications (on by default): native OS toast when a scan crosses the alert threshold.
  • Alert threshold: 1 critical, multiple criticals, or families. The multi-critical count is configurable from 2 to 4.
  • Auto-action (default quarantine at multiple criticals): when the threshold is met, the file is either moved to the in-app quarantine folder or sent to the OS trash. Both are recoverable; quarantine keeps the file out of the user's recycle bin.
  • Hold until scanned: rename foo.jar to foo.jar.jlab-pending while the scan is in flight so Java launchers cannot load it. Restored when the scan clears.
  • Rescan after: re-upload files in watched folders on a schedule (off / 7 / 14 / 30 days).
  • Minimize to tray, start minimized, launch at login: optional desktop integration.
  • Reset: wipes all watcher settings (including watched folders) and disables autostart.

File locations

Platform Settings + history Quarantine
macOS ~/Library/Application Support/JLab/ ~/Library/Application Support/JLab/quarantine/
Windows %APPDATA%\JLab\ %APPDATA%\JLab\quarantine\
Linux $XDG_DATA_HOME/JLab/ or ~/.local/share/JLab/ same dir + /quarantine/

Quarantined files are renamed <unix-timestamp>-<original-name>.quarantined. The .quarantined suffix prevents Java launchers from loading them and gives any local AV a clear hint that the file is held intentionally. To restore, rename back to the original extension or move the file out of the folder.

Build from source

You need:

Install and run:

npm install
npm run tauri dev

Useful commands:

npm run check                                                # TypeScript type-check
cargo check    --manifest-path src-tauri/Cargo.toml          # Rust type-check
cargo fmt      --manifest-path src-tauri/Cargo.toml          # format Rust
cargo clippy   --manifest-path src-tauri/Cargo.toml -- -D warnings
npm run tauri build                                          # release bundle

The release bundle lands in src-tauri/target/release/bundle/.

Icons

The repo ships with the icons referenced in src-tauri/tauri.conf.json. To regenerate them from a 1024 x 1024 PNG:

npm run tauri icon path/to/source.png

This populates src-tauri/icons/ with all required sizes and formats (.png, .icns, .ico).

API

The app talks to a single endpoint:

POST https://jlab.threat.rip/api/public/static-scan
Content-Type: multipart/form-data
Field:        file (max 50 MB, .jar archive)
Rate limit:   15 requests / minute / IP

For .zip, .mcpack, and .mrpack drops, the desktop client opens the archive locally, picks the largest inner .jar, and uploads only that file. The endpoint itself only accepts .jar.

No authentication is required. See https://jlab.threat.rip/api-docs.html for the full schema.

Contributing

Pull requests welcome. See CONTRIBUTING.md for the branch model, commit style, and how releases are cut. The short version: feature work lands on dev, releases ship from main.

Security

If you find a security issue, please report it privately. See SECURITY.md for the disclosure process. Do not file public issues for vulnerabilities.

License

Licensed under either of

at your option.

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this work, as defined in the Apache-2.0 license, shall be dual-licensed as above, without any additional terms or conditions.

About

Cross-platform desktop client for the public JLab static JAR scanner. Drop a .jar (or .zip / .mcpack / .mrpack), get the matched signatures grouped by severity.

Topics

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors