Conversation
Just a test
|
/gemini review this PR |
This is to test auto code review
|
@gemini-code-assist can you help review? |
| @@ -0,0 +1 @@ | |||
| To test auto code review in PRs | |||
There was a problem hiding this comment.
There was a problem hiding this comment.
Code Review
This pull request introduces several utility modules, including Windows-specific path handling and conversion, a polyfill for Promise.withResolvers, and a random word slug generator. The review feedback focuses on improving performance and reliability in windowsPaths.ts by using the native fs module instead of spawning shell processes for file existence checks. Additionally, it is recommended to throw errors instead of calling process.exit in utility functions and to define the PromiseWithResolvers interface locally to ensure type safety in environments where the native implementation is missing.
| @@ -0,0 +1,173 @@ | |||
| import memoize from 'lodash-es/memoize.js' | |||
| import * as path from 'path' | |||
| function checkPathExists(path: string): boolean { | ||
| try { | ||
| execSync_DEPRECATED(`dir "${path}"`, { stdio: 'pipe' }) | ||
| return true | ||
| } catch { | ||
| return false | ||
| } | ||
| } |
| `Claude Code was unable to find CLAUDE_CODE_GIT_BASH_PATH path "${process.env.CLAUDE_CODE_GIT_BASH_PATH}"`, | ||
| ) | ||
| // eslint-disable-next-line custom-rules/no-process-exit | ||
| process.exit(1) |
| * Polyfill for Promise.withResolvers() (ES2024, Node 22+). | ||
| * package.json declares "engines": { "node": ">=18.0.0" } so we can't use the native one. | ||
| */ | ||
| export function withResolvers<T>(): PromiseWithResolvers<T> { |
There was a problem hiding this comment.
Since this polyfill is for environments where Promise.withResolvers is not natively available, the PromiseWithResolvers type might also be missing from the global scope. Defining it locally ensures type safety and compatibility.
| export function withResolvers<T>(): PromiseWithResolvers<T> { | |
| export interface PromiseWithResolvers<T> { | |
| promise: Promise<T> | |
| resolve: (value: T | PromiseLike<T>) => void | |
| reject: (reason?: any) => void | |
| } | |
| export function withResolvers<T>(): PromiseWithResolvers<T> { |
There was a problem hiding this comment.
Code Review
This pull request adds utilities for Windows path manipulation, a Promise.withResolvers polyfill, and a random word slug generator. The review identifies security concerns regarding command injection and process execution in path utilities, suggesting the use of native Node.js functions instead. Other feedback includes improving the robustness of line-ending handling, replacing process exits with errors, defining missing types for the Promise polyfill, and addressing modulo bias in random number generation.
| const result = execSync_DEPRECATED(`where.exe ${executable}`, { | ||
| stdio: 'pipe', | ||
| encoding: 'utf8', | ||
| }).trim() |
There was a problem hiding this comment.
Potential command injection vulnerability. The executable variable is interpolated directly into a shell command string. If the input is not strictly controlled, an attacker could execute arbitrary commands by including shell metacharacters. Consider using execFileSync or another method that avoids shell execution.
| import memoize from 'lodash-es/memoize.js' | ||
| import * as path from 'path' | ||
| import * as pathWin32 from 'path/win32' | ||
| import { getCwd } from './cwd.js' | ||
| import { logForDebugging } from './debug.js' | ||
| import { execSync_DEPRECATED } from './execSyncWrapper.js' | ||
| import { memoizeWithLRU } from './memoize.js' | ||
| import { getPlatform } from './platform.js' |
There was a problem hiding this comment.
Add existsSync to the imports to support a more efficient and secure path existence check in checkPathExists.
| import memoize from 'lodash-es/memoize.js' | |
| import * as path from 'path' | |
| import * as pathWin32 from 'path/win32' | |
| import { getCwd } from './cwd.js' | |
| import { logForDebugging } from './debug.js' | |
| import { execSync_DEPRECATED } from './execSyncWrapper.js' | |
| import { memoizeWithLRU } from './memoize.js' | |
| import { getPlatform } from './platform.js' | |
| import memoize from 'lodash-es/memoize.js' | |
| import { existsSync } from 'node:fs' | |
| import * as path from 'path' | |
| import * as pathWin32 from 'path/win32' | |
| import { getCwd } from './cwd.js' | |
| import { logForDebugging } from './debug.js' | |
| import { execSync_DEPRECATED } from './execSyncWrapper.js' | |
| import { memoizeWithLRU } from './memoize.js' | |
| import { getPlatform } from './platform.js' |
| function checkPathExists(path: string): boolean { | ||
| try { | ||
| execSync_DEPRECATED(`dir "${path}"`, { stdio: 'pipe' }) | ||
| return true | ||
| } catch { | ||
| return false | ||
| } | ||
| } |
There was a problem hiding this comment.
The checkPathExists function is inefficient and insecure. Spawning a shell process (dir) to check for file existence is significantly slower than using Node.js built-in functions and is vulnerable to command injection if the path contains double quotes (e.g., " & calc). Additionally, the parameter name path shadows the imported path module. Use existsSync from node:fs instead.
function checkPathExists(filePath: string): boolean {
return existsSync(filePath)
}|
|
||
| // SECURITY: Filter out any results from the current directory | ||
| // to prevent executing malicious git.bat/cmd/exe files | ||
| const paths = result.split('\r\n').filter(Boolean) |
There was a problem hiding this comment.
Splitting by \r\n specifically may fail if the environment returns only \n (LF). Using a regex like /\r?\n/ is more robust for handling different line ending conventions on Windows.
| const paths = result.split('\r\n').filter(Boolean) | |
| const paths = result.split(/\r?\n/).filter(Boolean) |
| `Claude Code was unable to find CLAUDE_CODE_GIT_BASH_PATH path "${process.env.CLAUDE_CODE_GIT_BASH_PATH}"`, | ||
| ) | ||
| // eslint-disable-next-line custom-rules/no-process-exit | ||
| process.exit(1) |
There was a problem hiding this comment.
Using process.exit(1) in a utility function is discouraged as it terminates the entire application, making it difficult for callers to handle errors or for the code to be unit tested. Consider throwing an error instead.
| process.exit(1) | |
| throw new Error(`Claude Code was unable to find CLAUDE_CODE_GIT_BASH_PATH path "${process.env.CLAUDE_CODE_GIT_BASH_PATH}"`) |
| * Polyfill for Promise.withResolvers() (ES2024, Node 22+). | ||
| * package.json declares "engines": { "node": ">=18.0.0" } so we can't use the native one. | ||
| */ | ||
| export function withResolvers<T>(): PromiseWithResolvers<T> { |
There was a problem hiding this comment.
The type PromiseWithResolvers<T> is likely missing in the targeted Node environments (>=18). You should define the interface locally to ensure type safety and successful compilation.
| export function withResolvers<T>(): PromiseWithResolvers<T> { | |
| export interface PromiseWithResolvers<T> { | |
| promise: Promise<T> | |
| resolve: (value: T | PromiseLike<T>) => void | |
| reject: (reason?: any) => void | |
| } | |
| export function withResolvers<T>(): PromiseWithResolvers<T> { |
| // Use crypto.randomBytes for better randomness than Math.random | ||
| const bytes = randomBytes(4) | ||
| const value = bytes.readUInt32BE(0) | ||
| return value % max |
There was a problem hiding this comment.
Just a test