@@ -6,10 +6,12 @@ import { RooIgnoreController, LOCK_TEXT_SYMBOL } from "../RooIgnoreController"
6
6
import * as vscode from "vscode"
7
7
import * as path from "path"
8
8
import * as fs from "fs/promises"
9
+ import * as fsSync from "fs"
9
10
import { fileExistsAtPath } from "../../../utils/fs"
10
11
11
12
// Mock dependencies
12
13
vi . mock ( "fs/promises" )
14
+ vi . mock ( "fs" )
13
15
vi . mock ( "../../../utils/fs" )
14
16
15
17
// Mock vscode
@@ -66,6 +68,10 @@ describe("RooIgnoreController", () => {
66
68
mockFileExists = fileExistsAtPath as Mock < typeof fileExistsAtPath >
67
69
mockReadFile = fs . readFile as Mock < typeof fs . readFile >
68
70
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
+
69
75
// Create controller
70
76
controller = new RooIgnoreController ( TEST_CWD )
71
77
} )
@@ -217,6 +223,27 @@ describe("RooIgnoreController", () => {
217
223
expect ( emptyController . validateAccess ( "secrets/api-keys.json" ) ) . toBe ( true )
218
224
expect ( emptyController . validateAccess ( ".git/HEAD" ) ) . toBe ( true )
219
225
} )
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
+ } )
220
247
} )
221
248
222
249
describe ( "validateCommand" , ( ) => {
0 commit comments