{"record":{"id":"29a436f7c7b66dc4","repo":"gitbutlerapp/gitbutler","slug":"refusing-to-read-git-ignored-path","errorCode":null,"errorMessage":"Refusing to read Git-ignored path '{}'","messagePattern":"Refusing to read Git-ignored path '(.+?)'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/gitbutler-repo/src/commands.rs","lineNumber":485,"sourceCode":"        &index,\n        None,\n        gix::worktree::stack::state::ignore::Source::WorktreeThenIdMappingIfNotSkipped,\n    )?;\n    if !excludes.at_path(relative_path, None)?.is_excluded() {\n        return Ok(());\n    }\n    // On a case-insensitive filesystem `Tracked` names the tracked file\n    // `tracked`; retry the index lookup case-insensitively before refusing.\n    if repo.filesystem_options()?.ignore_case {\n        let icase_accelerator = index.prepare_icase_backing();\n        if index\n            .entry_by_path_icase(relative_path_bstr.as_ref(), true, &icase_accelerator)\n            .is_some()\n        {\n            return Ok(());\n        }\n    }\n    bail!(\n        \"Refusing to read Git-ignored path '{}'\",\n        relative_path.display()\n    );\n}\n","sourceCodeStart":467,"sourceCodeEnd":490,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/crates/gitbutler-repo/src/commands.rs#L467-L490","documentation":"ensure_not_ignored checks the repository's exclude/ignore rules (gitignore, excludes, global/config includes) and refuses to read files that Git would ignore, via read_worktree_file. This prevents the app from exposing files users deliberately excluded from the repo.","triggerScenarios":"Calling read_worktree_file for a path matched by .gitignore/.git/info/exclude/global ignores when the path isn't present as a worktree entry (the index fast-path didn't apply), e.g. \".env\", \"node_modules/x\", \"build/out.js\".","commonSituations":"Trying to view .env or secrets files; reading files in ignored build or dependency directories; recently-added ignore rules covering files that were previously readable.","solutions":["Read the file directly with std::fs if intentional (bypassing the git-aware API) with proper user consent.","Remove/adjust the .gitignore rule covering the path (e.g. add a negation !pattern).","Track the file in the index (git add -f) if it should be part of the project."],"exampleFix":"// before\nread_file_from_workspace(project, \".env\") // ignored\n// after (allowed via negation in .gitignore)\n!.env\n// then\nread_file_from_workspace(project, \".env\")","handlingStrategy":"validation","validationCode":"let excluded = repo\n    .excludes(Some(&workdir.join(\".gitignore\")))?\n    .pattern_matching_relative_path(rel_path, Default::default())?\n    .is_some();\nif excluded { return Err(\"path is git-ignored\"); }","typeGuard":null,"tryCatchPattern":"match result {\n    Err(e) if e.to_string().contains(\"Git-ignored path\") => {\n        // read via std::fs with explicit user consent, or skip\n    }\n    other => other,\n}","preventionTips":["Check ignore status before requesting workspace files.","Keep .env and secrets ignored and read them only via dedicated secure flows.","Watch for newly added ignore rules affecting previously readable paths."],"tags":["git","gitignore","security","rust"],"backgroundTag":"path-traversal-blocked","analyzedSha":"58e5313667b857ef39a730e380af31816a7b1768","analyzedAt":"2026-09-18T06:50:32.052Z","contentChangedAt":"2026-09-18T06:50:32.052Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}