{"record":{"id":"f9159c5fba7be120","repo":"astrid-runtime/astrid","slug":"winfsp-daemon-lease-exceeds-limit","errorCode":null,"errorMessage":"WinFsp daemon lease exceeds limit","messagePattern":"WinFsp daemon lease exceeds limit","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-storage-provider-winfsp/src/win.rs","lineNumber":57,"sourceCode":"const DAEMON_STOP_TIMEOUT: Duration = Duration::from_secs(30);\nconst MOUNTPOINT_READY_TIMEOUT: Duration = Duration::from_secs(10);\nconst MAX_LEASE_BYTES: u64 = 64 * 1024;\n\n#[derive(serde::Deserialize, serde::Serialize)]\nstruct DaemonStart {\n    lease: StorageMountLeaseV1,\n    mountpoint: PathBuf,\n}\n\npub(crate) fn daemon_main() -> Result<()> {\n    let mut bytes = Vec::new();\n    std::io::stdin()\n        .lock()\n        .take(MAX_LEASE_BYTES + 1)\n        .read_to_end(&mut bytes)\n        .context(\"read WinFsp daemon lease\")?;\n    if bytes.len() as u64 > MAX_LEASE_BYTES {\n        bail!(\"WinFsp daemon lease exceeds limit\");\n    }\n    let start: DaemonStart =\n        serde_json::from_slice(&bytes).context(\"decode WinFsp daemon lease\")?;\n    let lease = start.lease;\n    if (!start.mountpoint.is_absolute() && !is_drive_designator(&start.mountpoint))\n        || !lease.callback_path.is_absolute()\n    {\n        bail!(\"WinFsp daemon lease contains a relative endpoint\");\n    }\n\n    let runtime = Arc::new(\n        tokio::runtime::Builder::new_multi_thread()\n            .enable_all()\n            .build()\n            .context(\"start WinFsp callback runtime\")?,\n    );\n    let callback = CallbackFs::new(lease.clone(), Arc::clone(&runtime))\n        .map_err(|failure| anyhow::anyhow!(\"build WinFsp callback filesystem: {failure:?}\"))?;","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-storage-provider-winfsp/src/win.rs#L39-L75","documentation":"The WinFsp daemon reads its startup lease (JSON with lease, mountpoint, callback_path) from stdin, capped at MAX_LEASE_BYTES via take(MAX_LEASE_BYTES + 1). If the byte count read exceeds the cap, daemon_main bails rather than parsing an unbounded payload. This is a defensive bound against oversized or malformed IPC input from the parent process.","triggerScenarios":"The parent process (or any writer to the daemon's stdin) writes a lease document larger than MAX_LEASE_BYTES, e.g. a lease containing huge tokens, deeply nested or extraneous fields, or corrupted/non-JSON garbage of excessive length.","commonSituations":"Embedding very long control paths or auth tokens into the lease; a parent/child version mismatch where the child expects a leaner lease schema; a bug causing stdin to receive data beyond the lease (e.g. logging written to stdin).","solutions":["Shrink the lease payload the parent writes to stdin (trim large fields, keep only schema-required data)","Ensure the parent writes exactly one bounded JSON document and closes stdin","Verify parent and WinFsp crate versions match so lease layout is what daemon_main expects","If the workload legitimately needs larger leases, raise MAX_LEASE_BYTES in the crate and rebuild both sides together"],"exampleFix":"// before (parent)\nwrite_all(serde_json::to_vec(&lease_with_huge_token)?)\n// after\nlease.parent.token = compact_token(); // trim to the minimum needed\nwrite_all(serde_json::to_vec(&lease)?)","handlingStrategy":"validation","validationCode":"let bytes = serde_json::to_vec(&lease)?;\nif bytes.len() as u64 > MAX_LEASE_BYTES {\n    return Err(format!(\"lease payload {} bytes exceeds limit {}\", bytes.len(), MAX_LEASE_BYTES));\n}","typeGuard":"fn lease_within_limit(lease: &DaemonStart, max: u64) -> bool {\n    serde_json::to_vec(lease).map(|b| (b.len() as u64) <= max).unwrap_or(false)\n}","tryCatchPattern":"match daemon_err {\n    Err(e) if e.to_string().contains(\"lease exceeds limit\") => {\n        eprintln!(\"shrink lease payload or raise MAX_LEASE_BYTES\");\n    }\n    other => other?,\n}","preventionTips":["Serialize the lease and size-check it before writing to stdin","Keep tokens/paths in the lease minimal","Pin parent and daemon crate versions together"],"tags":["windows","winfsp","ipc","payload-size"],"backgroundTag":"payload-too-large","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}