Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit09777c5

Browse files
committed
fix: SSHConfig: check for multiple start/end blocks
1 parent31b8b33 commit09777c5

File tree

3 files changed

+206
-3
lines changed

3 files changed

+206
-3
lines changed

‎src/sshConfig.test.ts

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,189 @@ Host coder-vscode.dev.coder.com--*
249249
})
250250
})
251251

252+
it("throws an error if there is a mismatched start and end block count",async()=>{
253+
// The below config contains two start blocks and one end block.
254+
// This is a malformed config and should throw an error.
255+
// Previously were were simply taking the first occurrences of the start and
256+
// end blocks, which would potentially lead to loss of any content between the
257+
// missing end block and the next start block.
258+
constexistentSSHConfig=`Host beforeconfig
259+
HostName before.config.tld
260+
User before
261+
262+
# --- START CODER VSCODE dev.coder.com ---
263+
Host coder-vscode.dev.coder.com--*
264+
ConnectTimeout 0
265+
LogLevel ERROR
266+
ProxyCommand some-command-here
267+
StrictHostKeyChecking no
268+
UserKnownHostsFile /dev/null
269+
# missing END CODER VSCODE dev.coder.com ---
270+
271+
Host donotdelete
272+
HostName dont.delete.me
273+
User please
274+
275+
# --- START CODER VSCODE dev.coder.com ---
276+
Host coder-vscode.dev.coder.com--*
277+
ConnectTimeout 0
278+
LogLevel ERROR
279+
ProxyCommand some-command-here
280+
StrictHostKeyChecking no
281+
UserKnownHostsFile /dev/null
282+
# --- END CODER VSCODE dev.coder.com ---
283+
284+
Host afterconfig
285+
HostName after.config.tld
286+
User after`
287+
288+
constsshConfig=newSSHConfig(sshFilePath,mockFileSystem)
289+
mockFileSystem.readFile.mockResolvedValueOnce(existentSSHConfig)
290+
awaitsshConfig.load()
291+
292+
// When we try to update the config, it should throw an error.
293+
awaitexpect(
294+
sshConfig.update("dev.coder.com",{
295+
Host:"coder-vscode.dev.coder.com--*",
296+
ProxyCommand:"some-command-here",
297+
ConnectTimeout:"0",
298+
StrictHostKeyChecking:"no",
299+
UserKnownHostsFile:"/dev/null",
300+
LogLevel:"ERROR",
301+
}),
302+
).rejects.toThrow(
303+
`Malformed config: ssh config has 2 dev.coder.com START comments but 1 dev.coder.com END comments. Each START must have a matching END.`,
304+
)
305+
})
306+
307+
it("throws an error if there are more than one sections with the same label",async()=>{
308+
constexistentSSHConfig=`Host beforeconfig
309+
HostName before.config.tld
310+
User before
311+
312+
# --- START CODER VSCODE dev.coder.com ---
313+
Host coder-vscode.dev.coder.com--*
314+
ConnectTimeout 0
315+
LogLevel ERROR
316+
ProxyCommand some-command-here
317+
StrictHostKeyChecking no
318+
UserKnownHostsFile /dev/null
319+
# --- END CODER VSCODE dev.coder.com ---
320+
321+
Host donotdelete
322+
HostName dont.delete.me
323+
User please
324+
325+
# --- START CODER VSCODE dev.coder.com ---
326+
Host coder-vscode.dev.coder.com--*
327+
ConnectTimeout 0
328+
LogLevel ERROR
329+
ProxyCommand some-command-here
330+
StrictHostKeyChecking no
331+
UserKnownHostsFile /dev/null
332+
# --- END CODER VSCODE dev.coder.com ---
333+
334+
Host afterconfig
335+
HostName after.config.tld
336+
User after`
337+
338+
constsshConfig=newSSHConfig(sshFilePath,mockFileSystem)
339+
mockFileSystem.readFile.mockResolvedValueOnce(existentSSHConfig)
340+
awaitsshConfig.load()
341+
342+
// When we try to update the config, it should throw an error.
343+
awaitexpect(
344+
sshConfig.update("dev.coder.com",{
345+
Host:"coder-vscode.dev.coder.com--*",
346+
ProxyCommand:"some-command-here",
347+
ConnectTimeout:"0",
348+
StrictHostKeyChecking:"no",
349+
UserKnownHostsFile:"/dev/null",
350+
LogLevel:"ERROR",
351+
}),
352+
).rejects.toThrow(`Malformed config: ssh config has 2 dev.coder.com sections, please remove all but one.`)
353+
})
354+
355+
it("correctly handles interspersed blocks with and without label",async()=>{
356+
constexistentSSHConfig=`Host beforeconfig
357+
HostName before.config.tld
358+
User before
359+
360+
# --- START CODER VSCODE ---
361+
Host coder-vscode.dev.coder.com--*
362+
ConnectTimeout 0
363+
LogLevel ERROR
364+
ProxyCommand some-command-here
365+
StrictHostKeyChecking no
366+
UserKnownHostsFile /dev/null
367+
# --- END CODER VSCODE ---
368+
369+
Host donotdelete
370+
HostName dont.delete.me
371+
User please
372+
373+
# --- START CODER VSCODE dev.coder.com ---
374+
Host coder-vscode.dev.coder.com--*
375+
ConnectTimeout 0
376+
LogLevel ERROR
377+
ProxyCommand some-command-here
378+
StrictHostKeyChecking no
379+
UserKnownHostsFile /dev/null
380+
# --- END CODER VSCODE dev.coder.com ---
381+
382+
Host afterconfig
383+
HostName after.config.tld
384+
User after`
385+
386+
constsshConfig=newSSHConfig(sshFilePath,mockFileSystem)
387+
mockFileSystem.readFile.mockResolvedValueOnce(existentSSHConfig)
388+
awaitsshConfig.load()
389+
390+
constexpectedOutput=`Host beforeconfig
391+
HostName before.config.tld
392+
User before
393+
394+
# --- START CODER VSCODE ---
395+
Host coder-vscode.dev.coder.com--*
396+
ConnectTimeout 0
397+
LogLevel ERROR
398+
ProxyCommand some-command-here
399+
StrictHostKeyChecking no
400+
UserKnownHostsFile /dev/null
401+
# --- END CODER VSCODE ---
402+
403+
Host donotdelete
404+
HostName dont.delete.me
405+
User please
406+
407+
# --- START CODER VSCODE dev.coder.com ---
408+
Host coder-vscode.dev.coder.com--*
409+
ConnectTimeout 0
410+
LogLevel ERROR
411+
ProxyCommand some-command-here
412+
StrictHostKeyChecking no
413+
UserKnownHostsFile /dev/null
414+
# --- END CODER VSCODE dev.coder.com ---
415+
416+
Host afterconfig
417+
HostName after.config.tld
418+
User after`
419+
420+
awaitsshConfig.update("dev.coder.com",{
421+
Host:"coder-vscode.dev.coder.com--*",
422+
ProxyCommand:"some-command-here",
423+
ConnectTimeout:"0",
424+
StrictHostKeyChecking:"no",
425+
UserKnownHostsFile:"/dev/null",
426+
LogLevel:"ERROR",
427+
})
428+
429+
expect(mockFileSystem.writeFile).toBeCalledWith(sshFilePath,expectedOutput,{
430+
encoding:"utf-8",
431+
mode:384,
432+
})
433+
})
434+
252435
it("override values",async()=>{
253436
mockFileSystem.readFile.mockRejectedValueOnce("No file found")
254437
constsshConfig=newSSHConfig(sshFilePath,mockFileSystem)

‎src/sshConfig.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import{mkdir,readFile,writeFile}from"fs/promises"
22
importpathfrom"path"
3+
import{escapeRegexpString}from"./util"
34

45
classSSHConfigBadFormatextendsError{}
56

@@ -123,14 +124,29 @@ export class SSHConfig {
123124
*/
124125
privategetBlock(label:string):Block|undefined{
125126
constraw=this.getRaw()
126-
conststartBlockIndex=raw.indexOf(this.startBlockComment(label))
127-
constendBlockIndex=raw.indexOf(this.endBlockComment(label))
127+
conststartBlock=this.startBlockComment(label)
128+
constendBlock=this.endBlockComment(label)
129+
conststartBlockCount=raw.match(newRegExp(escapeRegexpString(startBlock),"g"))?.length||0
130+
constendBlockCount=raw.match(newRegExp(escapeRegexpString(endBlock),"g"))?.length||0
131+
conststartBlockIndex=raw.indexOf(startBlock)
132+
constendBlockIndex=raw.indexOf(endBlock)
128133
consthasBlock=startBlockIndex>-1&&endBlockIndex>-1
129134

130135
if(!hasBlock){
131136
return
132137
}
133138

139+
if(startBlockCount!==endBlockCount){
140+
thrownewSSHConfigBadFormat(
141+
`Malformed config: ssh config has${startBlockCount}${label} START comments but${endBlockCount}${label} END comments. Each START must have a matching END.`,
142+
)
143+
}
144+
if(startBlockCount>1||endBlockCount>1){
145+
thrownewSSHConfigBadFormat(
146+
`Malformed config: ssh config has${startBlockCount}${label} sections, please remove all but one.`,
147+
)
148+
}
149+
134150
if(startBlockIndex===-1){
135151
thrownewSSHConfigBadFormat("Start block not found")
136152
}
@@ -144,7 +160,7 @@ export class SSHConfig {
144160
}
145161

146162
return{
147-
raw:raw.substring(startBlockIndex,endBlockIndex+this.endBlockComment(label).length),
163+
raw:raw.substring(startBlockIndex,endBlockIndex+endBlock.length),
148164
}
149165
}
150166

‎src/util.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,3 +120,7 @@ export function expandPath(input: string): string {
120120
constuserHome=os.homedir()
121121
returninput.replace(/\${userHome}/g,userHome)
122122
}
123+
124+
exportfunctionescapeRegexpString(str:string):string{
125+
returnstr.replace(/\./g,"\\.").replace(/\*/g,".*").replace(/\?/g,".")
126+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp