1
0
Fork 0

fix command escaping (#302)

pull/320/head
eric sciple 2020-01-18 23:52:44 -05:00 committed by GitHub
parent ab5bd9d696
commit 8b0300129f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 64 additions and 23 deletions

View File

@ -27,6 +27,51 @@ describe('@actions/core/src/command', () => {
assertWriteCalls([`::some-command::${os.EOL}`]) assertWriteCalls([`::some-command::${os.EOL}`])
}) })
it('command escapes message', () => {
// Verify replaces each instance, not just first instance
command.issueCommand(
'some-command',
{},
'percent % percent % cr \r cr \r lf \n lf \n'
)
assertWriteCalls([
`::some-command::percent %25 percent %25 cr %0D cr %0D lf %0A lf %0A${os.EOL}`
])
// Verify literal escape sequences
process.stdout.write = jest.fn()
command.issueCommand('some-command', {}, '%25 %25 %0D %0D %0A %0A')
assertWriteCalls([
`::some-command::%2525 %2525 %250D %250D %250A %250A${os.EOL}`
])
})
it('command escapes property', () => {
// Verify replaces each instance, not just first instance
command.issueCommand(
'some-command',
{
name:
'percent % percent % cr \r cr \r lf \n lf \n colon : colon : comma , comma ,'
},
''
)
assertWriteCalls([
`::some-command name=percent %25 percent %25 cr %0D cr %0D lf %0A lf %0A colon %3A colon %3A comma %2C comma %2C::${os.EOL}`
])
// Verify literal escape sequences
process.stdout.write = jest.fn()
command.issueCommand(
'some-command',
{},
'%25 %25 %0D %0D %0A %0A %3A %3A %2C %2C'
)
assertWriteCalls([
`::some-command::%2525 %2525 %250D %250D %250A %250A %253A %253A %252C %252C${os.EOL}`
])
})
it('command with message', () => { it('command with message', () => {
command.issueCommand('some-command', {}, 'some message') command.issueCommand('some-command', {}, 'some message')
assertWriteCalls([`::some-command::some message${os.EOL}`]) assertWriteCalls([`::some-command::some message${os.EOL}`])

View File

@ -41,10 +41,10 @@ describe('@actions/core', () => {
}) })
it('exportVariable escapes variable names', () => { it('exportVariable escapes variable names', () => {
core.exportVariable('special char var \r\n];', 'special val') core.exportVariable('special char var \r\n,:', 'special val')
expect(process.env['special char var \r\n];']).toBe('special val') expect(process.env['special char var \r\n,:']).toBe('special val')
assertWriteCalls([ assertWriteCalls([
`::set-env name=special char var %0D%0A%5D%3B::special val${os.EOL}` `::set-env name=special char var %0D%0A%2C%3A::special val${os.EOL}`
]) ])
}) })

View File

@ -10,11 +10,11 @@ interface CommandProperties {
* Commands * Commands
* *
* Command Format: * Command Format:
* ##[name key=value;key=value]message * ::name key=value,key=value::message
* *
* Examples: * Examples:
* ##[warning]This is the user warning message * ::warning::This is the message
* ##[set-secret name=mypassword]definitelyNotAPassword! * ::set-env name=MY_VAR::some value
*/ */
export function issueCommand( export function issueCommand(
command: string, command: string,
@ -62,33 +62,29 @@ class Command {
cmdStr += ',' cmdStr += ','
} }
// safely append the val - avoid blowing up when attempting to cmdStr += `${key}=${escapeProperty(val)}`
// call .replace() if message is not a string for some reason
cmdStr += `${key}=${escape(`${val || ''}`)}`
} }
} }
} }
} }
cmdStr += CMD_STRING cmdStr += `${CMD_STRING}${escapeData(this.message)}`
// safely append the message - avoid blowing up when attempting to
// call .replace() if message is not a string for some reason
const message = `${this.message || ''}`
cmdStr += escapeData(message)
return cmdStr return cmdStr
} }
} }
function escapeData(s: string): string { function escapeData(s: string): string {
return s.replace(/\r/g, '%0D').replace(/\n/g, '%0A') return (s || '')
} .replace(/%/g, '%25')
function escape(s: string): string {
return s
.replace(/\r/g, '%0D') .replace(/\r/g, '%0D')
.replace(/\n/g, '%0A') .replace(/\n/g, '%0A')
.replace(/]/g, '%5D') }
.replace(/;/g, '%3B')
function escapeProperty(s: string): string {
return (s || '')
.replace(/%/g, '%25')
.replace(/\r/g, '%0D')
.replace(/\n/g, '%0A')
.replace(/:/g, '%3A')
.replace(/,/g, '%2C')
} }