{"record":{"id":"96764c1280623a3c","repo":"astrid-runtime/astrid","slug":"winfsp-lease-manifest-exceeds-the-bounded-size","errorCode":null,"errorMessage":"WinFsp lease manifest exceeds the bounded size","messagePattern":"WinFsp lease manifest exceeds the bounded size","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-storage-provider-winfsp/src/win.rs","lineNumber":283,"sourceCode":"    if lease.lease_token.len() < 16 || lease.lease_token.len() > 4096 {\n        bail!(\"WinFsp lease callback token is invalid\");\n    }\n    if !lease.resource_path.is_absolute()\n        || !lease.callback_path.is_absolute()\n        || lease.callback_path != lease.resource_path.join(\"control.endpoint\")\n    {\n        bail!(\"WinFsp lease paths are malformed\");\n    }\n    platform_fs::validate_private_directory(&lease.resource_path)\n        .context(\"validate private WinFsp lease resource\")?;\n    platform_fs::verify_no_redirects(&lease.resource_path)\n        .context(\"reject redirected WinFsp lease resource\")?;\n    let manifest_path = lease.resource_path.join(\"lease.json\");\n    platform_fs::validate_private_file(&manifest_path)\n        .context(\"validate private WinFsp lease manifest\")?;\n    let manifest = std::fs::read(&manifest_path).context(\"read WinFsp lease manifest\")?;\n    if manifest.len() > 64 * 1024 {\n        bail!(\"WinFsp lease manifest exceeds the bounded size\");\n    }\n    let admitted: StorageMountLeaseV1 =\n        serde_json::from_slice(&manifest).context(\"decode WinFsp lease manifest\")?;\n    if admitted != *lease {\n        bail!(\"WinFsp launch lease does not match the kernel manifest\");\n    }\n    if !launch.mountpoint.is_absolute()\n        || launch\n            .mountpoint\n            .components()\n            .any(|component| matches!(component, std::path::Component::ParentDir))\n    {\n        bail!(\"WinFsp service mountpoint is malformed\");\n    }\n    if is_public_mountpoint(&launch.mountpoint)\n        || launch.mountpoint.parent().is_none()\n        || launch.mountpoint == lease.resource_path\n        || launch.mountpoint.starts_with(&lease.resource_path)","sourceCodeStart":265,"sourceCodeEnd":301,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-storage-provider-winfsp/src/win.rs#L265-L301","documentation":"Before trusting a launch, the service reads lease.json from the lease resource directory and enforces a hard cap of 64 KiB on the manifest. A larger file is rejected because lease manifests are small structured documents; anything bigger indicates corruption, accidental embedding of payload data, or a tampering attempt (bloat to exhaust parser resources).","triggerScenarios":"service_main -> validate_service_launch where std::fs::read(lease.resource_path.join(\"lease.json\")) returns more than 65536 bytes.","commonSituations":"A writer accidentally serializes the whole launch bundle (including tokens, buffers, or debug dumps) into lease.json instead of just StorageMountLeaseV1; a crash/partial write concatenated two documents; a user or sync tool (Dropbox/OneDrive conflict copy) grew the file; an attacker or buggy process padded the file.","solutions":["Delete the bad lease.json and let the issuer regenerate it containing only the StorageMountLeaseV1 struct.","Fix the code that writes lease.json — serialize exactly the StorageMountLeaseV1 value (serde_json::to_writer), not a wrapper with extra fields or embedded data.","Check for file-sync conflict copies or appended content in the resource directory and restore a clean copy.","If legitimately more data is needed, move it to separate files and reference it from the manifest rather than growing the manifest."],"exampleFix":"// before\nserde_json::to_writer(&file, &bundle)?; // bundle includes logs + lease\n// after\nlet manifest: StorageMountLeaseV1 = lease_struct_from(bundle);\nserde_json::to_writer(&file, &manifest)?;","handlingStrategy":"validation","validationCode":"let meta = std::fs::metadata(manifest_path)?;\nif meta.len() > 64 * 1024 {\n    return Err(anyhow!(\"lease.json is {} bytes; regenerate it (limit 64 KiB)\", meta.len()));\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Serialize exactly StorageMountLeaseV1 into lease.json — no wrappers or embedded data","Keep large artifacts in separate files referenced by the manifest","Watch for file-sync conflict copies inside resource directories","Check file size at write time in the issuer and fail fast if over budget"],"tags":["winfsp","lease","file-size","validation"],"backgroundTag":"file-size-limit-exceeded","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"}