checkout/__test__/shell-escape.test.ts

44 lines
1.7 KiB
TypeScript

import {describe, it, expect} from '@jest/globals'
import {escapeSingleQuote} from '../src/shell-escape.js'
describe('shell-escape tests', () => {
it('handles empty string', () => {
expect(escapeSingleQuote('')).toBe('')
})
it('leaves strings without single quotes unchanged', () => {
expect(escapeSingleQuote('https://github.com')).toBe('https://github.com')
expect(escapeSingleQuote('git@github.com:')).toBe('git@github.com:')
expect(escapeSingleQuote('core.sshCommand')).toBe('core.sshCommand')
expect(escapeSingleQuote('http.https://github.com/.extraheader')).toBe(
'http.https://github.com/.extraheader'
)
})
it('escapes single quotes with POSIX close-escape-reopen sequence', () => {
expect(escapeSingleQuote("it's")).toBe("it'\\''s")
expect(escapeSingleQuote("'foo'")).toBe("'\\''foo'\\''")
expect(escapeSingleQuote("a'b'c")).toBe("a'\\''b'\\''c")
})
it('escapes single quotes in URLs with decoded percent-encoded characters', () => {
// new URL('https://evil%27$(id)host.com') results in hostname "evil'$(id)host.com"
const decodedUrlKey = "http.https://evil'$(id)host.com/.extraheader"
expect(escapeSingleQuote(decodedUrlKey)).toBe(
"http.https://evil'\\''$(id)host.com/.extraheader"
)
const decodedInsteadOfValue = "git@evil'$(id)host.com:"
expect(escapeSingleQuote(decodedInsteadOfValue)).toBe(
"git@evil'\\''$(id)host.com:"
)
})
it('preserves other shell special characters literally inside single quotes', () => {
const specialChars = '`$(id) && rm -rf /; echo "hello" \\ * ? < > |'
expect(escapeSingleQuote(specialChars)).toBe(
'`$(id) && rm -rf /; echo "hello" \\ * ? < > |'
)
})
})