Skip to content

NanoTorrent 0.3.3

Latest

Choose a tag to compare

@github-actions github-actions released this 04 Sep 21:49
478b03b

What's Changed

Security

  • Torrent path escape (Windows) — a .torrent whose filename carried a drive prefix (C:evil.txt) passed librqbit's traversal check, then discarded the save folder entirely because PathBuf::push replaces the buffer on a prefix; demonstrated writing into the process working directory. Engine patch 0015 (safe_join) refuses any relative path whose components are not all Component::Normal, at the storage layer, so magnets are covered too.
  • Proxy leak inventory — all HTTP now goes through one client factory (src/core/http.rs); plugin http_get/fetch/add_url use it rather than building their own. SOCKS uses socks5h:// so names resolve at the proxy.
  • Dependency audit — RUSTSEC-2026-0258 (h2 0.3, low, DoS) documented in Cargo.toml: unreachable to fix, since actix-web's rustls-0_23 implies http2 and actix-http prepends h2 to ALPN; no newer actix exists.

Network / privacy

  • Strict network mode (network.strict) — switches off whatever the proxy or bound interface cannot cover (DHT, uTP, LSD, UPnP, IPv6), refuses to start when the named interface is absent, pauses every torrent if it disappears while running. Decision logic in src/core/netguard.rs.
  • Bind-to-interface on Windows — was a #[cfg(windows)] stub returning BindDeviceNotSupported, making the whole feature Linux/macOS-only. Engine patch 0014 binds the interface's address instead (strong host model); verified listening on 192.168.178.251:6881 rather than [::].
  • ListenerOptions.ipv4_only — the peer listener has its own copy and SessionOptions::ipv4_only never reached it, so it bound [::] regardless.
  • SOCKS5 credentials — username/password were read by the session but settable from no surface; now in Preferences, CLI and the web drawer.
  • New settingsnetwork.strict, network.bind_interface, translated across all 41 locales.

Desktop UI

  • Status bar — icons for torrents, DHT nodes, down/up, plus port reachability, proxy-in-use and interface-bound indicators (red when the binding is lost).
  • Dialog height clampclamp_to_screen ran before the window was realised, so scale_factor() returned 1 and position() (0,0); on a 200% display it computed a 2024px limit for a 984px screen and never engaged. Now deferred one event-loop turn, and measures the monitor the window is on rather than the primary.
  • Preferences sizes to the current tab — was max(tb1..tb7), so every tab inherited the tallest one's height.
  • Ten-row lists — labels, filters and plugins lists stand ten rows tall instead of collapsing.
  • Plugin window — the only window in the codebase with no screen-limit; now clamped, and re-clamped on every open.

Web interface

  • Toolbar parity — add magnet, add torrent, remove, resume, pause, with row selection (which the table had none of).
  • Multi-select — ctrl/cmd-click toggles, shift-click ranges; resume/pause act only on the rows they apply to, so a mixed selection does the sensible thing.
  • Speed charts — both directions, sharing the desktop's own keys, 96px default, 48–320 range, per-chart grip, double-click resets.
  • Resizable columns — persisted server-side in the same column_state table the desktop uses (list id webui), so widths follow the person rather than one browser.
  • Drag-and-drop adding — hands files to the existing picker, so the batch panes come up unchanged. (Multi-torrent add already worked; it just wasn't findable.)
  • Brute-force lockout — configurable attempts / window / block (5 / 60s / 3600s), counted per address; the window and the block are now separate settings rather than one number serving as both.
  • Plugins — full folder listing with enabled state, error and permissions; enable/disable with a live host reload; plugin surfaces rendered in the browser from the same state the desktop window uses, so the shipped rss.rhai works there unchanged. The web deliberately cannot approve permissions.
  • Language sync — changing it in the browser now retranslates the GUI on its next tick.
  • Fixesapi() threw on any empty body (this blanked the plugin panel); duplicate top-level let selected was a SyntaxError that killed the whole script; undefined --ctl-h broke the header height; progress bar and Actions buttons overflowed their columns; favicon 404.
  • Cosmetic — boolean settings as lit toggle buttons, setting keys moved to tooltips, app icon in the header, wider add/plugin panels, full-width layout.

Engine patches

  • 0014 Windows bind-to-interface (-sockets, 3 files) — supersedes and retires the old cosmetic 0014.
  • 0015 torrent path escape (security).
  • Series consolidated — 15 numbered features across 20 files and four vendored crates; the whole stack now reverse-applies to pristine crates.io sources with zero markers left (it did not before: 0014's baseline was wrong).
  • Docs unstaledPATCHES.md listed two vendored crates (there are four) and "apply 0001 → 0007"; README claimed "13 features across 16 files".