@@ -6,10 +6,12 @@ import { RooIgnoreController, LOCK_TEXT_SYMBOL } from "../RooIgnoreController"
66import * as vscode from "vscode"
77import * as path from "path"
88import * as fs from "fs/promises"
9+ import * as fsSync from "fs"
910import { fileExistsAtPath } from "../../../utils/fs"
1011
1112// Mock dependencies
1213vi . mock ( "fs/promises" )
14+ vi . mock ( "fs" )
1315vi . mock ( "../../../utils/fs" )
1416
1517// Mock vscode
@@ -66,6 +68,10 @@ describe("RooIgnoreController", () => {
6668 mockFileExists = fileExistsAtPath as Mock < typeof fileExistsAtPath >
6769 mockReadFile = fs . readFile as Mock < typeof fs . readFile >
6870
71+ // Setup fsSync mocks with default behavior (return path as-is, like regular files)
72+ const mockRealpathSync = vi . mocked ( fsSync . realpathSync )
73+ mockRealpathSync . mockImplementation ( ( filePath ) => filePath . toString ( ) )
74+
6975 // Create controller
7076 controller = new RooIgnoreController ( TEST_CWD )
7177 } )
@@ -217,6 +223,27 @@ describe("RooIgnoreController", () => {
217223 expect ( emptyController . validateAccess ( "secrets/api-keys.json" ) ) . toBe ( true )
218224 expect ( emptyController . validateAccess ( ".git/HEAD" ) ) . toBe ( true )
219225 } )
226+
227+ /**
228+ * Tests symlink resolution
229+ */
230+ it ( "should block symlinks pointing to ignored files" , ( ) => {
231+ // Mock fsSync.realpathSync to simulate symlink resolution
232+ const mockRealpathSync = vi . mocked ( fsSync . realpathSync )
233+ mockRealpathSync . mockImplementation ( ( filePath ) => {
234+ // Simulate "config.json" being a symlink to "node_modules/package.json"
235+ if ( filePath . toString ( ) . endsWith ( "config.json" ) ) {
236+ return path . join ( TEST_CWD , "node_modules/package.json" )
237+ }
238+ return filePath . toString ( )
239+ } )
240+
241+ // Direct access to ignored file should be blocked
242+ expect ( controller . validateAccess ( "node_modules/package.json" ) ) . toBe ( false )
243+
244+ // Symlink to ignored file should also be blocked
245+ expect ( controller . validateAccess ( "config.json" ) ) . toBe ( false )
246+ } )
220247 } )
221248
222249 describe ( "validateCommand" , ( ) => {
0 commit comments