Skip to content

Commit b391ad0

Browse files
committed
Fix comment in PR and add test
1 parent aee5222 commit b391ad0

File tree

2 files changed

+70
-2
lines changed

2 files changed

+70
-2
lines changed

packages/dd-trace/src/appsec/iast/analyzers/hsts-header-missing-analyzer.js

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,37 @@ const { HSTS_HEADER_MISSING } = require('../vulnerabilities')
44
const { MissingHeaderAnalyzer } = require('./missing-header-analyzer')
55

66
const HSTS_HEADER_NAME = 'Strict-Transport-Security'
7-
7+
const HEADER_VALID_PREFIX = 'max-age'
88
class HstsHeaderMissingAnalyzer extends MissingHeaderAnalyzer {
99
constructor () {
1010
super(HSTS_HEADER_MISSING, HSTS_HEADER_NAME)
1111
}
1212
_validateRequestAndResponse (req, res) {
1313
const headerToCheck = res.getHeader(HSTS_HEADER_NAME)
14-
return !headerToCheck && this._isHttpsProtocol(req)
14+
return !this._isHeaderValid(headerToCheck) && this._isHttpsProtocol(req)
15+
}
16+
17+
_isHeaderValid (headerValue) {
18+
if (!headerValue) {
19+
return false
20+
}
21+
headerValue = headerValue.trim()
22+
23+
if (!headerValue.startsWith(HEADER_VALID_PREFIX)) {
24+
return false
25+
}
26+
27+
const semicolonIndex = headerValue.indexOf(';')
28+
let timestampString
29+
if (semicolonIndex > -1) {
30+
timestampString = headerValue.substring(HEADER_VALID_PREFIX.length + 1, semicolonIndex)
31+
} else {
32+
timestampString = headerValue.substring(HEADER_VALID_PREFIX.length + 1)
33+
}
34+
35+
const timestamp = parseInt(timestampString)
36+
// eslint-disable-next-line eqeqeq
37+
return timestamp == timestampString && timestamp > 0
1538
}
1639

1740
_isHttpsProtocol (req) {

packages/dd-trace/test/appsec/iast/analyzers/hsts-header-missing-analyzer.spec.js

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,33 @@ describe('hsts header missing analyzer', () => {
4444
expect(vulnerabilities[0].hash).to.be.equals(analyzer._createHash('HSTS_HEADER_MISSING:mocha'))
4545
}, makeRequestWithXFordwardedProtoHeader)
4646

47+
testThatRequestHasVulnerability((req, res) => {
48+
res.setHeader('content-type', 'text/html')
49+
res.setHeader('Strict-Transport-Security', 'max-age=-100')
50+
res.end('<html><body><h1>Test</h1></body></html>')
51+
}, HSTS_HEADER_MISSING, 1, function (vulnerabilities) {
52+
expect(vulnerabilities[0].evidence.value).to.be.equal('max-age=-100')
53+
expect(vulnerabilities[0].hash).to.be.equals(analyzer._createHash('HSTS_HEADER_MISSING:mocha'))
54+
}, makeRequestWithXFordwardedProtoHeader)
55+
56+
testThatRequestHasVulnerability((req, res) => {
57+
res.setHeader('content-type', 'text/html')
58+
res.setHeader('Strict-Transport-Security', 'max-age=-100; includeSubDomains')
59+
res.end('<html><body><h1>Test</h1></body></html>')
60+
}, HSTS_HEADER_MISSING, 1, function (vulnerabilities) {
61+
expect(vulnerabilities[0].evidence.value).to.be.equal('max-age=-100; includeSubDomains')
62+
expect(vulnerabilities[0].hash).to.be.equals(analyzer._createHash('HSTS_HEADER_MISSING:mocha'))
63+
}, makeRequestWithXFordwardedProtoHeader)
64+
65+
testThatRequestHasVulnerability((req, res) => {
66+
res.setHeader('content-type', 'text/html')
67+
res.setHeader('Strict-Transport-Security', 'invalid')
68+
res.end('<html><body><h1>Test</h1></body></html>')
69+
}, HSTS_HEADER_MISSING, 1, function (vulnerabilities) {
70+
expect(vulnerabilities[0].evidence.value).to.be.equal('invalid')
71+
expect(vulnerabilities[0].hash).to.be.equals(analyzer._createHash('HSTS_HEADER_MISSING:mocha'))
72+
}, makeRequestWithXFordwardedProtoHeader)
73+
4774
testThatRequestHasNoVulnerability((req, res) => {
4875
res.setHeader('content-type', 'application/json')
4976
res.end('{"key": "test}')
@@ -54,5 +81,23 @@ describe('hsts header missing analyzer', () => {
5481
res.setHeader('Strict-Transport-Security', 'max-age=100')
5582
res.end('{"key": "test}')
5683
}, HSTS_HEADER_MISSING, makeRequestWithXFordwardedProtoHeader)
84+
85+
testThatRequestHasNoVulnerability((req, res) => {
86+
res.setHeader('content-type', 'text/html')
87+
res.setHeader('Strict-Transport-Security', ' max-age=100 ')
88+
res.end('{"key": "test}')
89+
}, HSTS_HEADER_MISSING, makeRequestWithXFordwardedProtoHeader)
90+
91+
testThatRequestHasNoVulnerability((req, res) => {
92+
res.setHeader('content-type', 'text/html')
93+
res.setHeader('Strict-Transport-Security', 'max-age=100;includeSubDomains')
94+
res.end('{"key": "test}')
95+
}, HSTS_HEADER_MISSING, makeRequestWithXFordwardedProtoHeader)
96+
97+
testThatRequestHasNoVulnerability((req, res) => {
98+
res.setHeader('content-type', 'text/html')
99+
res.setHeader('Strict-Transport-Security', 'max-age=100 ;includeSubDomains')
100+
res.end('{"key": "test}')
101+
}, HSTS_HEADER_MISSING, makeRequestWithXFordwardedProtoHeader)
57102
})
58103
})

0 commit comments

Comments
 (0)