Add CRLF injection protection for header values
Implement security validation to prevent HTTP header injection attacks: - Reject header values containing \r or \n characters - Add comprehensive test coverage for CRLF protection - Replace multiline YAML test with proper rejection test Security improvements: - Validates header values to prevent header injection - Clear warning messages when values are rejected - Four new test cases covering LF, CR, CRLF, and multiline scenarios This addresses a critical security concern where malicious headers could be injected via newline characters in header values. All 84 tests passing.
This commit is contained in:
@@ -283,7 +283,52 @@ valid123: value5`
|
||||
})
|
||||
})
|
||||
|
||||
it('handles multiline YAML values', () => {
|
||||
it('rejects header values with newline characters (LF)', () => {
|
||||
const jsonInput = '{"X-Custom-Header": "value\\nwith\\nnewline", "header1": "safe-value"}'
|
||||
|
||||
const result = parseCustomHeaders(jsonInput)
|
||||
|
||||
// Only the safe header should be accepted
|
||||
expect(result).toEqual({
|
||||
header1: 'safe-value',
|
||||
})
|
||||
|
||||
expect(core.warning).toHaveBeenCalledWith(
|
||||
'Skipping header "X-Custom-Header" because its value contains newline characters, which are not allowed in HTTP header values.',
|
||||
)
|
||||
})
|
||||
|
||||
it('rejects header values with carriage return characters (CR)', () => {
|
||||
const jsonInput = '{"X-Injected": "value\\rwith\\rcarriage", "X-Safe": "safe-value"}'
|
||||
|
||||
const result = parseCustomHeaders(jsonInput)
|
||||
|
||||
// Only the safe header should be accepted
|
||||
expect(result).toEqual({
|
||||
'X-Safe': 'safe-value',
|
||||
})
|
||||
|
||||
expect(core.warning).toHaveBeenCalledWith(
|
||||
'Skipping header "X-Injected" because its value contains newline characters, which are not allowed in HTTP header values.',
|
||||
)
|
||||
})
|
||||
|
||||
it('rejects header values with CRLF sequences', () => {
|
||||
const jsonInput = '{"X-Attack": "value\\r\\nInjected-Header: malicious", "X-Valid": "normal"}'
|
||||
|
||||
const result = parseCustomHeaders(jsonInput)
|
||||
|
||||
// Only the valid header should be accepted
|
||||
expect(result).toEqual({
|
||||
'X-Valid': 'normal',
|
||||
})
|
||||
|
||||
expect(core.warning).toHaveBeenCalledWith(
|
||||
'Skipping header "X-Attack" because its value contains newline characters, which are not allowed in HTTP header values.',
|
||||
)
|
||||
})
|
||||
|
||||
it('rejects multiline YAML values for security', () => {
|
||||
const yamlInput = `header1: value1
|
||||
header2: |
|
||||
multiline
|
||||
@@ -292,8 +337,14 @@ header2: |
|
||||
|
||||
const result = parseCustomHeaders(yamlInput)
|
||||
|
||||
expect(result.header1).toBe('value1')
|
||||
expect(result.header2).toContain('multiline')
|
||||
// header2 should be rejected because it contains newlines
|
||||
expect(result).toEqual({
|
||||
header1: 'value1',
|
||||
})
|
||||
|
||||
expect(core.warning).toHaveBeenCalledWith(
|
||||
'Skipping header "header2" because its value contains newline characters, which are not allowed in HTTP header values.',
|
||||
)
|
||||
})
|
||||
|
||||
it('handles complex real-world Azure APIM example', () => {
|
||||
|
||||
5
dist/index.js
generated
vendored
5
dist/index.js
generated
vendored
@@ -61361,6 +61361,11 @@ function validateAndMaskHeaders(headers) {
|
||||
}
|
||||
// Convert value to string
|
||||
const stringValue = String(value);
|
||||
// Validate header value to prevent CRLF/header injection
|
||||
if (stringValue.includes('\r') || stringValue.includes('\n')) {
|
||||
coreExports.warning(`Skipping header "${name}" because its value contains newline characters, which are not allowed in HTTP header values.`);
|
||||
continue;
|
||||
}
|
||||
validHeaders[name] = stringValue;
|
||||
// Mask sensitive headers in logs
|
||||
const lowerName = name.toLowerCase();
|
||||
|
||||
2
dist/index.js.map
generated
vendored
2
dist/index.js.map
generated
vendored
File diff suppressed because one or more lines are too long
@@ -132,7 +132,9 @@ function validateAndMaskHeaders(headers: Record<string, unknown>): Record<string
|
||||
|
||||
// Validate header value to prevent CRLF/header injection
|
||||
if (stringValue.includes('\r') || stringValue.includes('\n')) {
|
||||
core.warning(`Skipping header "${name}" because its value contains newline characters, which are not allowed in HTTP header values.`)
|
||||
core.warning(
|
||||
`Skipping header "${name}" because its value contains newline characters, which are not allowed in HTTP header values.`,
|
||||
)
|
||||
continue
|
||||
}
|
||||
validHeaders[name] = stringValue
|
||||
|
||||
Reference in New Issue
Block a user