Skip to content

Commit

Permalink
fix: properly replace integrity tags inside script resources when exp…
Browse files Browse the repository at this point in the history
…erimentalModifyObstructiveThirdPartyCode is true
  • Loading branch information
AtofStryker committed Sep 17, 2022
1 parent 702f1b1 commit d87af9a
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 9 deletions.
25 changes: 19 additions & 6 deletions packages/proxy/lib/http/util/regex-rewriter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,22 @@ const topOrParentLocationOrFramesRe = /([^\da-zA-Z\(\)])?(\btop\b|\bparent\b)([.
const jiraTopWindowGetterRe = /(!function\s*\((\w{1})\)\s*{\s*return\s*\w{1}\s*(?:={2,})\s*\w{1}\.parent)(\s*}\(\w{1}\))/g
const jiraTopWindowGetterUnMinifiedRe = /(function\s*\w{1,}\s*\((\w{1})\)\s*{\s*return\s*\w{1}\s*(?:={2,})\s*\w{1}\.parent)(\s*;\s*})/g

const integrityTagReplacementRe = new RegExp(`(${STRIPPED_INTEGRITY_TAG}|integrity)((=|["|'], )(?:"|')sha(?:256|384|512)-.*?(?:"|'))`, 'g')
const buildIntegrityReplacementRe = (isHtml = true) => {
if (!isHtml) {
// only replace integrity if a trailing period (.) or string exists inside JS/Other resources
return new RegExp(`(${STRIPPED_INTEGRITY_TAG}|[\\.|"|']integrity)((\\s?=\\s?|["|'], )(?:"|')sha(?:256|384|512)-.*?(?:"|'))`, 'g')
}

return new RegExp(`(${STRIPPED_INTEGRITY_TAG}|integrity)((=|["|'], )(?:"|')sha(?:256|384|512)-.*?(?:"|'))`, 'g')
}

const returnReplacedIntegrityExpression = (isHtml = true) => {
return isHtml ? `${STRIPPED_INTEGRITY_TAG}$2` : `['${STRIPPED_INTEGRITY_TAG}']$2`
}

export function strip (html: string, { modifyObstructiveThirdPartyCode }: Partial<SecurityOpts> = {
export function strip (html: string, { modifyObstructiveThirdPartyCode, isHtml = true }: Partial<SecurityOpts> = {
modifyObstructiveThirdPartyCode: false,
isHtml: true,
}) {
let rewrittenHTML = html
.replace(modifyObstructiveThirdPartyCode ? topOrParentExpandedEqualityBeforeRe : topOrParentEqualityBeforeRe, '$1self')
Expand All @@ -30,14 +42,15 @@ export function strip (html: string, { modifyObstructiveThirdPartyCode }: Partia
.replace(jiraTopWindowGetterUnMinifiedRe, '$1 || $2.parent.__Cypress__$3')

if (modifyObstructiveThirdPartyCode) {
rewrittenHTML = rewrittenHTML.replace(integrityTagReplacementRe, `${STRIPPED_INTEGRITY_TAG}$2`)
rewrittenHTML = rewrittenHTML.replace(buildIntegrityReplacementRe(isHtml), returnReplacedIntegrityExpression(isHtml))
}

return rewrittenHTML
}

export function stripStream ({ modifyObstructiveThirdPartyCode }: Partial<SecurityOpts> = {
export function stripStream ({ modifyObstructiveThirdPartyCode, isHtml = true }: Partial<SecurityOpts> = {
modifyObstructiveThirdPartyCode: false,
isHtml: true,
}) {
return pumpify(
utf8Stream(),
Expand All @@ -49,7 +62,7 @@ export function stripStream ({ modifyObstructiveThirdPartyCode }: Partial<Securi
jiraTopWindowGetterRe,
jiraTopWindowGetterUnMinifiedRe,
...(modifyObstructiveThirdPartyCode ? [
integrityTagReplacementRe,
buildIntegrityReplacementRe(isHtml),
] : []),
],
[
Expand All @@ -59,7 +72,7 @@ export function stripStream ({ modifyObstructiveThirdPartyCode }: Partial<Securi
'$1 || $2.parent.__Cypress__$3',
'$1 || $2.parent.__Cypress__$3',
...(modifyObstructiveThirdPartyCode ? [
`${STRIPPED_INTEGRITY_TAG}$2`,
returnReplacedIntegrityExpression(isHtml),
] : []),
],
),
Expand Down
25 changes: 22 additions & 3 deletions packages/proxy/test/unit/http/util/regex-rewriter.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -398,9 +398,25 @@ const expectedWithModifyObstructiveThirdPartyCode = `\
</html>\
`

const originalScriptWithModifyObstructiveThirdPartyCode = `(function(){var d=document,po=d.createElement('script');po.type='text/javascript';po.async=true;po.src='https://www.foobar.com/foobar.js';po.crossOrigin='anonymous';po.integrity='sha384-XiV6bRRw9OEpsWSumtD1J7rElgTrNQro4MY/O4IYjhH+YGCf1dHaNGZ3A2kzYi/C';var e=d.querySelector('script[nonce]'),n=e&&(e['nonce']||e.getAttribute('nonce'));if(n){po.setAttribute('nonce',n);}var s=d.getElementsByTagName('script')[0];s.parentNode.insertBefore(po, s);})();`
const originalScriptWithModifyObstructiveThirdPartyCode = `\
(function(){var d=document,po=d.createElement('script');po.type='text/javascript';po.async=true;po.src='https://www.foobar.com/foobar.js';po.crossOrigin='anonymous';po.integrity='sha384-XiV6bRRw9OEpsWSumtD1J7rElgTrNQro4MY/O4IYjhH+YGCf1dHaNGZ3A2kzYi/C';var e=d.querySelector('script[nonce]'),n=e&&(e['nonce']||e.getAttribute('nonce'));if(n){po.setAttribute('nonce',n);}var s=d.getElementsByTagName('script')[0];s.parentNode.insertBefore(po, s);})();
var integrity = 'sha384-XiV6bRRw9OEpsWSumtD1J7rElgTrNQro4MY/O4IYjhH+YGCf1dHaNGZ3A2kzYi/C'
foo.integrity = 'foo-bar'
foo.integrity = 'sha384-XiV6bRRw9OEpsWSumtD1J7rElgTrNQro4MY/O4IYjhH+YGCf1dHaNGZ3A2kzYi/C'
var integrity='sha256-XiV6bRRw9OEpsWSumtD1J7rElgTrNQro4MY/O4IYjhH+YGCf1dHaNGZ3A2kzYi/C'
foo.integrity='foo-bar'
foo.integrity='sha256-XiV6bRRw9OEpsWSumtD1J7rElgTrNQro4MY/O4IYjhH+YGCf1dHaNGZ3A2kzYi/C'\
`

const expectedScriptWithModifyObstructiveThirdPartyCode = `(function(){var d=document,po=d.createElement('script');po.type='text/javascript';po.async=true;po.src='https://www.foobar.com/foobar.js';po.crossOrigin='anonymous';po['cypress-stripped-integrity']='sha384-XiV6bRRw9OEpsWSumtD1J7rElgTrNQro4MY/O4IYjhH+YGCf1dHaNGZ3A2kzYi/C';var e=d.querySelector('script[nonce]'),n=e&&(e['nonce']||e.getAttribute('nonce'));if(n){po.setAttribute('nonce',n);}var s=d.getElementsByTagName('script')[0];s.parentNode.insertBefore(po, s);})();`
const expectedScriptWithModifyObstructiveThirdPartyCode = `\
(function(){var d=document,po=d.createElement('script');po.type='text/javascript';po.async=true;po.src='https://www.foobar.com/foobar.js';po.crossOrigin='anonymous';po['cypress-stripped-integrity']='sha384-XiV6bRRw9OEpsWSumtD1J7rElgTrNQro4MY/O4IYjhH+YGCf1dHaNGZ3A2kzYi/C';var e=d.querySelector('script[nonce]'),n=e&&(e['nonce']||e.getAttribute('nonce'));if(n){po.setAttribute('nonce',n);}var s=d.getElementsByTagName('script')[0];s.parentNode.insertBefore(po, s);})();
var integrity = 'sha384-XiV6bRRw9OEpsWSumtD1J7rElgTrNQro4MY/O4IYjhH+YGCf1dHaNGZ3A2kzYi/C'
foo.integrity = 'foo-bar'
foo['cypress-stripped-integrity'] = 'sha384-XiV6bRRw9OEpsWSumtD1J7rElgTrNQro4MY/O4IYjhH+YGCf1dHaNGZ3A2kzYi/C'
var integrity='sha256-XiV6bRRw9OEpsWSumtD1J7rElgTrNQro4MY/O4IYjhH+YGCf1dHaNGZ3A2kzYi/C'
foo.integrity='foo-bar'
foo['cypress-stripped-integrity']='sha256-XiV6bRRw9OEpsWSumtD1J7rElgTrNQro4MY/O4IYjhH+YGCf1dHaNGZ3A2kzYi/C'\
`

describe('http/util/regex-rewriter', () => {
context('.strip', () => {
Expand All @@ -417,6 +433,7 @@ describe('http/util/regex-rewriter', () => {
it('replaces additional obstructive code with the "modifyObstructiveThirdPartyCode" set (javascript)', () => {
expect(regexRewriter.strip(originalScriptWithModifyObstructiveThirdPartyCode, {
modifyObstructiveThirdPartyCode: true,
isHtml: false,
})).to.eq(expectedScriptWithModifyObstructiveThirdPartyCode)
})

Expand Down Expand Up @@ -624,6 +641,7 @@ while (!isTopMostWindow(parentOf) && satisfiesSameOrigin(parentOf.parent)) {

const replacer = regexRewriter.stripStream({
modifyObstructiveThirdPartyCode: true,
isHtml: true,
})

replacer.pipe(concatStream({ encoding: 'string' }, (str) => {
Expand All @@ -645,11 +663,12 @@ while (!isTopMostWindow(parentOf) && satisfiesSameOrigin(parentOf.parent)) {
replacer.end()
})

it('replaces additional obstructive code with the "modifyObstructiveThirdPartyCode" set (script)', (done) => {
it('replaces additional obstructive code with the "modifyObstructiveThirdPartyCode" set (js)', (done) => {
const haystacks = originalScriptWithModifyObstructiveThirdPartyCode.split('\n')

const replacer = regexRewriter.stripStream({
modifyObstructiveThirdPartyCode: true,
isHtml: false,
})

replacer.pipe(concatStream({ encoding: 'string' }, (str) => {
Expand Down

0 comments on commit d87af9a

Please sign in to comment.