mirror of https://github.com/actions/toolkit
fix command escaping (#302)
parent
ab5bd9d696
commit
8b0300129f
|
@ -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}`])
|
||||||
|
|
|
@ -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}`
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -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')
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue