Skip to content

Conversation

@sontoriyama
Copy link

@sontoriyama sontoriyama commented Jan 3, 2026

Refactored to use EAFP pattern (catch EISDIR instead of lstat pre-check). Fixes symlink handling and avoids race conditions. Based on suggestions when testing with gemini-code-assist. Closes #16282

@sontoriyama sontoriyama requested a review from a team as a code owner January 3, 2026 23:47
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @sontoriyama, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request resolves an issue in the memoryDiscovery utility where it would attempt to read directories named "GEMINI.md" as files, resulting in unnecessary warnings. By introducing a preliminary check, the system now gracefully skips these directories, logging a debug message instead of a warning, thereby enhancing the stability and clarity of the memory discovery process.

Highlights

  • Directory Handling: Implemented a check to identify and silently skip directories that match "GEMINI.md" filenames during memory discovery, preventing warnings.
  • Error Prevention: Replaced previous warning messages with debug logs when a directory is encountered where a file was expected, streamlining the memory discovery process.
  • Test Coverage: Added a new test case to ensure that directories are correctly skipped and valid "GEMINI.md" files are still processed as expected.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request aims to prevent warnings when GEMINI.md memory discovery encounters a directory with a matching name by adding a check using lstat. However, a high-severity Path Traversal vulnerability has been identified due to the handling of symbolic links, which could allow an attacker to read arbitrary files. Additionally, the current implementation introduces a potential Time-of-check to time-of-use (TOCTOU) race condition; a more robust approach would be to handle the EISDIR error directly in the catch block.

Comment on lines +257 to 267
const stats = await fs.lstat(filePath);
if (stats.isDirectory()) {
// Skip directories silently - they're valid memory folders
if (debugMode) {
logger.debug(
`Skipping directory ${filePath} (expected file). Using parent directory for memory discovery instead.`,
);
}
return { filePath, content: null };
}

const content = await fs.readFile(filePath, 'utf-8');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-high high

This code is vulnerable to a high-severity Path Traversal attack using symbolic links. The fs.lstat(filePath) check does not verify if the path is a symbolic link, allowing fs.readFile to follow malicious symlinks and potentially read arbitrary files. Furthermore, this pre-check introduces a Time-of-check to time-of-use (TOCTOU) race condition. To fix this, you must explicitly check for and reject symbolic links. For handling directories, a more robust approach would be to attempt readFile directly and handle the specific EISDIR error in the catch block.

          const stats = await fs.lstat(filePath);
          if (stats.isSymbolicLink()) {
            if (debugMode) {
              logger.debug(`Skipping symbolic link: ${filePath}`);
            }
            return { filePath, content: null };
          }
          if (stats.isDirectory()) {
            // Skip directories silently - they're valid memory folders
            if (debugMode) {
              logger.debug(
                `Skipping directory ${filePath} (expected file). Using parent directory for memory discovery instead.`
              );
            }
            return { filePath, content: null };
          }

          const content = await fs.readFile(filePath, 'utf-8');

@sontoriyama
Copy link
Author

Thank you for the thorough review. I appreciate the feedback on both the test logic and the security concern.

Regarding the path traversal warning: I understand your concern, but I believe this may be a false positive for the following reasons:

  1. filePath source: The paths come from setGeminiMdFilename() which uses internal configuration, not external user input. An attacker would need access to the local configuration files.

  2. Context: These are memory filenames defined in the tool's own configuration system, not arbitrary paths from user input.

  3. Defense in depth: I considered adding path traversal validation as suggested, but I'm concerned about introducing regressions without fully understanding all the edge cases in the memory discovery system. I'd prefer the maintainers to guide on whether additional validation is needed here or if it should be handled at the configuration layer.

I'm happy to implement any changes the maintainers recommend for this. Thank you again for the detailed feedback!

@sontoriyama
Copy link
Author

Updated to use EAFP pattern based on code review feedback.

Changes:

  • Replaced lstat() pre-check with try/catch for EISDIR error
  • This properly handles symlinks (stat follows links, lstat does not)
  • Avoids TOCTOU race conditions
  • More efficient (no double syscall)
  • More idiomatic Node.js pattern

Thanks for the feedback - this is definitely cleaner than the pre-check approach!

@sontoriyama sontoriyama force-pushed the fix/gemini-md-directory-clean branch 2 times, most recently from 32c2fcf to 27fab85 Compare January 6, 2026 05:09
When a GEMINI.md filename matches a directory (e.g., user has
.gemini/gemini.md/ as a folder), the code attempted to read it as
a file, causing unnecessary warnings.

This change adds an lstat check before readFile to silently skip
directories with a debug log message.

Fixes #4760
- Remove unused validGeminiMdFile (GEMINI.md.md not discovered)
- Update assertions to match actual behavior of loadServerHierarchicalMemory
- Add clear comments explaining expected behavior
Replace lstat() pre-check with try/catch for EISDIR error based on
code review feedback. This approach:

- Handles symlinks correctly (fs.stat follows links, lstat does not)
- Avoids TOCTOU race conditions
- More efficient (no double syscall)
- More idiomatic Node.js pattern (EAFP)

Fixes #4760

Ref: #15866 (comment)
@sontoriyama sontoriyama force-pushed the fix/gemini-md-directory-clean branch from 27fab85 to 4dc4add Compare January 6, 2026 05:16
sontoriyama and others added 11 commits January 7, 2026 03:52
On non-Debian/Ubuntu Linux distributions, the Antigravity IDE binary is installed as 'antigravity' instead of 'agy'. This commit adds 'antigravity' as a fallback in the editorCommands mapping to enable proper detection on these distributions.

Fixes #15553
When a GEMINI.md filename matches a directory (e.g., user has
.gemini/gemini.md/ as a folder), the code attempted to read it as
a file, causing unnecessary warnings.

This change adds an lstat check before readFile to silently skip
directories with a debug log message.

Fixes #4760
@gemini-cli gemini-cli bot added the status/need-issue Pull requests that need to have an associated issue. label Jan 7, 2026
@mrcabbage972
Copy link
Contributor

Thanks for the PR! Can you please create an Issue and link the PR to it?

@mrcabbage972
Copy link
Contributor

Thanks for the PR! Can you please fix the failing tests?

@sontoriyama
Copy link
Author

Closes #16282

@gemini-cli gemini-cli bot added area/core Issues related to User Interface, OS Support, Core Functionality and removed status/need-issue Pull requests that need to have an associated issue. labels Jan 10, 2026
@sontoriyama sontoriyama closed this by deleting the head repository Jan 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/core Issues related to User Interface, OS Support, Core Functionality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Core] Handle EISDIR error when GEMINI.md is a directory during memory discovery

2 participants