Files
rclone-jav/bugs-candidates-host.md
admin f7fc15b17c Sync working tree before initial Gitea push
Includes:
- cli.py path fix (parents[1]) for config/catalog resolution
- Library cleanup feature design docs (TODO.md, mockup)
- Audit + bug-queue markdowns from May 2026 reliability pass
- .gitignore expanded for transient artifacts
2026-05-26 22:35:42 +02:00

8.6 KiB

Candidate Findings — Native host — audit-snapshot-2026-05-24T15-55Z.md

Scope: rcjav-host.py + rcjav-host.bat + register-host.bat + install-host.ps1 Required-reading: AGENTS.md / mockup / CACHE_CONTRACT.md / bug-audit-plan.md Auditor: fresh Explore agent


Candidate C-1

  • File: D:\DEV\Extensions\Production\rclone-jav\host\rcjav-host.py:1216-1221
  • Hunch: Path allowlist check is case-sensitive; if rclone remote names are case-insensitive, a path with different-case remote could bypass the security check.
  • Trace: _path_in_allowed_prefixes at line 1216 normalizes path slashes but not case. Line 1219 compares path_norm == prefix without .lower(). If extension passes CQ:JAV/file and allowlist has cq:JAV, the check fails.
  • Question for verifier: Are rclone remote names case-insensitive, and can a case-mismatch bypass the allowlist?
  • Suggested severity: M (potential security bypass if rclone treats remotes case-insensitively)
  • Contract refs needed: none

Candidate C-2

  • File: D:\DEV\Extensions\Production\rclone-jav\host\rcjav-host.py:306-316
  • Hunch: ead_message() reads a 4-byte length prefix without validating max size; a sender could cause huge memory allocation.
  • Trace: Line 312 reads length as unsigned int; line 313 reads exactly that many bytes with no cap. If msg_len = 0xFFFFFFFF, attempts to allocate 4 GiB.
  • Question for verifier: Is there a practical max message size enforced by the browser before the host receives it?
  • Suggested severity: M (DoS via huge length prefix; host could crash)
  • Contract refs needed: none

Candidate C-3

  • File: D:\DEV\Extensions\Production\rclone-jav\host\rcjav-host.py:174-217 (post_discord_alert)
  • Hunch: Discord webhook URL validation at line 182 checks format but not reachability; blocking urllib.request.urlopen at line 209 with 5-second timeout could delay RPC response if webhook is unreachable.
  • Trace: Line 182 regex validates URL format. Line 209 calls urllib.request.urlopen with timeout=5. If URL is malformed or unreachable, the attempt blocks for up to 5 seconds.
  • Question for verifier: Are webhook alerts fired on the main message loop, potentially blocking RPC response?
  • Suggested severity: M (RPC delay if alerts fire synchronously on main loop)
  • Contract refs needed: none

Candidate C-4

  • File: D:\DEV\Extensions\Production\rclone-jav\host\rcjav-host.py:2235-2264 (handle_scan)
  • Hunch: handle_scan returns success before spawn thread completes, so if subprocess.Popen fails in _scan_worker, extension incorrectly sees "started": true.
  • Trace: Line 2260-2264 spawns thread with .start() and immediately returns {"ok": True, "started": True}. If Popen fails in _scan_worker (line 2092), exception is caught and logged but message loop already returned.
  • Question for verifier: If subprocess.Popen raises immediately, does extension see success but scan never started?
  • Suggested severity: M (misleading response; race condition on success status)
  • Contract refs needed: none

Candidate C-5

  • File: D:\DEV\Extensions\Production\rclone-jav\host\rcjav-host.py:2053-2227 (_scan_worker)
  • Hunch: Blocking for loop reading stderr (line 2101) with no timeout; if rc-jav hangs, progress updates freeze until 5-second deferred kill.
  • Trace: Line 2101 or raw in proc.stderr: blocks on each line. No timeout. If rc-jav stalls, loop blocks. Deferred kill fires after 5 seconds (line 2297-2302).
  • Question for verifier: Does stderr blocking cause observable 5-second stalls in progress updates if rc-jav hangs mid-output?
  • Suggested severity: M (observable delay; progress freezes up to 5 seconds)
  • Contract refs needed: none

Candidate C-6

  • File: D:\DEV\Extensions\Production\rclone-jav\host\install-host.ps1:47
  • Hunch: Extension ID validation regex ^[a-p]{32}$ silently rejects invalid IDs without warning; user may not notice typos in manually-entered IDs.
  • Trace: Line 47 filters IDs by regex; if ID doesn't match, it's silently skipped. No warning printed.
  • Question for verifier: Should rejected IDs trigger a warning, or is silent skipping acceptable?
  • Suggested severity: L (silent failure; user might not notice ID was rejected)
  • Contract refs needed: none

Candidate C-7

  • File: D:\DEV\Extensions\Production\rclone-jav\host\rcjav-host.py:404-432 (run_rcjav)
  • Hunch: Hardcoded PYTHON = "python" without verifying it exists on PATH; error message is generic if python is not found.
  • Trace: Line 416 uses bare PYTHON string. Line 431 returns generic error str(e) if subprocess fails.
  • Question for verifier: If python is not on PATH, is the error message clear enough to diagnose?
  • Suggested severity: L (error is returned; message could be more specific)
  • Contract refs needed: none

Candidate C-8

  • File: D:\DEV\Extensions\Production\rclone-jav\host\rcjav-host.py:1100-1131 (_patch_cache_remove_paths)
  • Hunch: Orphaned .tmp files from failed cache writes are never cleaned up.
  • Trace: Line 1126-1128 writes temp and replaces. If replace fails at line 1128, OSError caught at line 1129, but .tmp file remains on disk.
  • Question for verifier: Is resource leak of orphaned .tmp files acceptable?
  • Suggested severity: L (resource leak; no data loss)
  • Contract refs needed: none

Candidate C-9

  • File: D:\DEV\Extensions\Production\rclone-jav\host\rcjav-host.py:323-356 (_shrink_response)
  • Hunch: Placeholder "TBD" in line 343 suggests unresolved work, but code later resolves it; confusing but not a functional bug.
  • Trace: Line 343 appends "structured TBD"; line 355 appends actual count. "TBD" is always replaced.
  • Question for verifier: Can "TBD" ever remain in the final truncated_reason?
  • Suggested severity: L (misleading message; no functional bug)
  • Contract refs needed: none

Candidate C-10

  • File: D:\DEV\Extensions\Production\rclone-jav\host\rcjav-host.py:2092-2110
  • Hunch: Partial JSON lines from ungracefully terminated process are silently caught, potentially losing progress data.
  • Trace: Lines 2104-2112 parse SCAN_START JSON; exceptions caught and pass-ed. If process killed mid-line, JSON decoder fails silently.
  • Question for verifier: Can partial JSON lines from forced process termination cause stale progress to persist?
  • Suggested severity: L (error silently caught; scan restarts cleanly on next invocation)
  • Contract refs needed: none

Candidate C-11

  • File: D:\DEV\Extensions\Production\rclone-jav\host\rcjav-host.py:1259-1260 (handle_delete)
  • Hunch: Rclone paths not pre-validated; malformed paths reach rclone command and fail there instead of being rejected early.
  • Trace: Line 1258-1260 validates only local paths with Path.exists(). Rclone paths skip existence check. Allowlist check at line 1267 validates prefix only.
  • Question for verifier: Should rclone path format be pre-validated, or is deferring to rclone error handling acceptable?
  • Suggested severity: L (rclone rejects malformed paths; no silent failure)
  • Contract refs needed: none

Candidate C-12

  • File: D:\DEV\Extensions\Production\rclone-jav\host\rcjav-host.py:589-603 (_load_host_cache)
  • Hunch: In-process cache memoization uses resolved path as key, but if user changes rcjav_path mid-session, stale cache from different cache.json could be served.
  • Trace: Line 584 key = str(cache_path.resolve()) — key includes resolved path. If rcjav_path changes, cache_path changes and fresh entry loaded. But logic is subtle.
  • Question for verifier: Can two different cache.json files from different rcjav_path values collide in the memoization key?
  • Suggested severity: N (cache key includes resolved path; no obvious collision)
  • Contract refs needed: none

VERIFIER NOTES (Phase 1 Moderate verification, stricter prompt with external/internal-input rule)

  • C-1 (case-sensitive allowlist) — REFUTED. Gate is fail-SAFE; case-mismatch rejects (no bypass). Usability gap noted but not a bug.
  • C-2 (unbounded msg length) — REFUTED. Chrome NM protocol caps extension-to-host at 64 MiB browser-side. Only Brave can write to host stdin.
  • C-3 (blocking Discord) — CONFIRMED M, high confidence. All 5 callsites on main thread; test bypasses rate limit. Promoted as M-1.
  • C-4 (handle_scan premature success) — CONFIRMED M, very high confidence. 1-2s race window. Promoted as M-2.
  • C-5 (stderr blocking) — PARTIAL → demoted M to L. 5s stale progress max, cancel works delayed, no data loss. Promoted as L-1.

CHUNK 2 CALIBRATION:

  • Severe: 0 (none flagged)
  • Moderate rejection: 2/5 = 40% (pure refute), 1 demoted
  • Combined: 2/5 = 40% (stop condition >30% triggered)
  • Auditor weaknesses: (1) flagging fail-safe gates as if fail-open, (2) ignoring protocol-level caps from upstream layers
  • L candidates NOT verified per stop condition. Same auditor pattern likely affects L list. Revisit only if needed.