{"record":{"id":"296e9035d74cea09","repo":"Hmbown/CodeWhale","slug":"external-credential-file-exceeds-the-byte","errorCode":null,"errorMessage":"external {} credential file {} exceeds the {} byte safety limit","messagePattern":"external (.+?) credential file (.+?) exceeds the (.+?) byte safety limit","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/external_credentials.rs","lineNumber":80,"sourceCode":"        }\n    };\n\n    #[cfg(test)]\n    increment_side_effect(1);\n\n    let mut bytes = Vec::new();\n    file.by_ref()\n        .take(MAX_EXTERNAL_CREDENTIAL_BYTES + 1)\n        .read_to_end(&mut bytes)\n        .with_context(|| {\n            format!(\n                \"reading external {} credential file {}\",\n                grant.source().as_str(),\n                codewhale_config::quote_os_path(grant.path())\n            )\n        })?;\n    if bytes.len() as u64 > MAX_EXTERNAL_CREDENTIAL_BYTES {\n        bail!(\n            \"external {} credential file {} exceeds the {} byte safety limit\",\n            grant.source().as_str(),\n            codewhale_config::quote_os_path(grant.path()),\n            MAX_EXTERNAL_CREDENTIAL_BYTES\n        );\n    }\n    let contents = String::from_utf8(bytes).with_context(|| {\n        format!(\n            \"external {} credential file {} is not valid UTF-8\",\n            grant.source().as_str(),\n            codewhale_config::quote_os_path(grant.path())\n        )\n    })?;\n    Ok(Some(contents))\n}\n\n/// Open the exact granted file through the secure boundary (regular file\n/// only, no symlink/reparse leaf) without requiring UTF-8. Used by binary","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/tui/src/external_credentials.rs#L62-L98","documentation":"Thrown by external_credentials::read_to_string when the granted credential file is larger than MAX_EXTERNAL_CREDENTIAL_BYTES (1 MiB, crates/tui/src/external_credentials.rs:18). The read is deliberately bounded with take(limit + 1) so a replaced regular file cannot turn read-only consent into unbounded memory use; exceeding the cap fails closed.","triggerScenarios":"The grant path resolves to a large file — e.g. a database (state.vscdb), a log, or a bundled export — instead of the small credentials document expected. Any source (dsh_cli or other) goes through this boundary.","commonSituations":"Consenting to the wrong path when creating the grant; a symlinked credentials file replaced by something big; tooling writing a huge JSON blob where a tiny KEY: value doc was expected.","solutions":["Verify the granted path really is the credentials document, not a database or log","Regenerate the credential file so it is a small text/JSON document under 1 MiB","Re-create the grant pointing at the corrected path and retry the import"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const MAX_CREDENTIAL_BYTES: u64 = 1024 * 1024;\n\n// Check the granted file before importing:\nlet meta = std::fs::metadata(grant.path())?;\nif meta.len() > MAX_CREDENTIAL_BYTES {\n    return Err(anyhow::anyhow!(\n        \"granted file {} is {} bytes; expected a small credentials document\",\n        grant.path().display(),\n        meta.len()\n    ));\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Double-check the consented path points at the credentials text file, not a database or log","Keep credential documents minimal; a KEY: value file is a few hundred bytes","Regenerate grants after any tool changes what it stores at the granted path"],"tags":["rust","tui","credentials","file-size","security","fail-closed"],"backgroundTag":"file-size-limit-exceeded","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}