Account for SVG/XML files too.
Signed-off-by: Eric Peterson <ericpeterson@spotify.com>
This commit is contained in:
@@ -287,10 +287,11 @@ describe('AwsS3Publish', () => {
|
||||
mockFs({
|
||||
[entityRootDir]: {
|
||||
html: {
|
||||
'file.html': '<html></html>',
|
||||
'unsafe.html': '<html></html>',
|
||||
},
|
||||
img: {
|
||||
'with spaces.png': 'found it',
|
||||
'unsafe.svg': '<svg></svg>',
|
||||
},
|
||||
'some folder': {
|
||||
'also with spaces.js': 'found it too',
|
||||
@@ -328,11 +329,19 @@ describe('AwsS3Publish', () => {
|
||||
metadata: { namespace, name },
|
||||
} = entity;
|
||||
|
||||
const response = await request(app).get(
|
||||
`/${namespace}/${kind}/${name}/html/file.html`,
|
||||
const htmlResponse = await request(app).get(
|
||||
`/${namespace}/${kind}/${name}/html/unsafe.html`,
|
||||
);
|
||||
expect(response.text).toEqual('<html></html>');
|
||||
expect(response.header).toMatchObject({
|
||||
expect(htmlResponse.text).toEqual('<html></html>');
|
||||
expect(htmlResponse.header).toMatchObject({
|
||||
'content-type': 'text/plain; charset=utf-8',
|
||||
});
|
||||
|
||||
const svgResponse = await request(app).get(
|
||||
`/${namespace}/${kind}/${name}/img/unsafe.svg`,
|
||||
);
|
||||
expect(svgResponse.text).toEqual('<svg></svg>');
|
||||
expect(svgResponse.header).toMatchObject({
|
||||
'content-type': 'text/plain; charset=utf-8',
|
||||
});
|
||||
});
|
||||
|
||||
@@ -344,10 +344,11 @@ describe('publishing with valid credentials', () => {
|
||||
mockFs({
|
||||
[entityRootDir]: {
|
||||
html: {
|
||||
'file.html': '<html></html>',
|
||||
'unsafe.html': '<html></html>',
|
||||
},
|
||||
img: {
|
||||
'with spaces.png': 'found it',
|
||||
'unsafe.svg': '<svg></svg>',
|
||||
},
|
||||
'some folder': {
|
||||
'also with spaces.js': 'found it too',
|
||||
@@ -385,11 +386,19 @@ describe('publishing with valid credentials', () => {
|
||||
metadata: { namespace, name },
|
||||
} = entity;
|
||||
|
||||
const response = await request(app).get(
|
||||
`/${namespace}/${kind}/${name}/html/file.html`,
|
||||
const htmlResponse = await request(app).get(
|
||||
`/${namespace}/${kind}/${name}/html/unsafe.html`,
|
||||
);
|
||||
expect(response.text).toEqual('<html></html>');
|
||||
expect(response.header).toMatchObject({
|
||||
expect(htmlResponse.text).toEqual('<html></html>');
|
||||
expect(htmlResponse.header).toMatchObject({
|
||||
'content-type': 'text/plain; charset=utf-8',
|
||||
});
|
||||
|
||||
const svgResponse = await request(app).get(
|
||||
`/${namespace}/${kind}/${name}/img/unsafe.svg`,
|
||||
);
|
||||
expect(svgResponse.text).toEqual('<svg></svg>');
|
||||
expect(svgResponse.header).toMatchObject({
|
||||
'content-type': 'text/plain; charset=utf-8',
|
||||
});
|
||||
});
|
||||
|
||||
@@ -286,10 +286,11 @@ describe('GoogleGCSPublish', () => {
|
||||
mockFs({
|
||||
[entityRootDir]: {
|
||||
html: {
|
||||
'file.html': '<html></html>',
|
||||
'unsafe.html': '<html></html>',
|
||||
},
|
||||
img: {
|
||||
'with spaces.png': 'found it',
|
||||
'unsafe.svg': '<svg></svg>',
|
||||
},
|
||||
'some folder': {
|
||||
'also with spaces.js': 'found it too',
|
||||
@@ -318,6 +319,7 @@ describe('GoogleGCSPublish', () => {
|
||||
const jsResponse = await request(app).get(
|
||||
`/${namespace}/${kind}/${name}/some%20folder/also%20with%20spaces.js`,
|
||||
);
|
||||
expect(jsResponse.text).toEqual('found it too');
|
||||
});
|
||||
|
||||
it('should pass text/plain content-type for html', async () => {
|
||||
@@ -326,11 +328,19 @@ describe('GoogleGCSPublish', () => {
|
||||
metadata: { namespace, name },
|
||||
} = entity;
|
||||
|
||||
const response = await request(app).get(
|
||||
`/${namespace}/${kind}/${name}/html/file.html`,
|
||||
const htmlResponse = await request(app).get(
|
||||
`/${namespace}/${kind}/${name}/html/unsafe.html`,
|
||||
);
|
||||
expect(response.text).toEqual('<html></html>');
|
||||
expect(response.header).toMatchObject({
|
||||
expect(htmlResponse.text).toEqual('<html></html>');
|
||||
expect(htmlResponse.header).toMatchObject({
|
||||
'content-type': 'text/plain; charset=utf-8',
|
||||
});
|
||||
|
||||
const svgResponse = await request(app).get(
|
||||
`/${namespace}/${kind}/${name}/img/unsafe.svg`,
|
||||
);
|
||||
expect(svgResponse.text).toEqual('<svg></svg>');
|
||||
expect(svgResponse.header).toMatchObject({
|
||||
'content-type': 'text/plain; charset=utf-8',
|
||||
});
|
||||
});
|
||||
|
||||
@@ -25,7 +25,7 @@ describe('getHeadersForFileExtension', () => {
|
||||
['.png', 'image/png'],
|
||||
['.jpg', 'image/jpeg'],
|
||||
['.jpeg', 'image/jpeg'],
|
||||
['.svg', 'image/svg+xml'],
|
||||
['.svg', 'text/plain; charset=utf-8'],
|
||||
['.json', 'application/json; charset=utf-8'],
|
||||
['.this-in-not-an-extension', 'text/plain; charset=utf-8'],
|
||||
];
|
||||
|
||||
@@ -34,8 +34,8 @@ export const getHeadersForFileExtension = (
|
||||
};
|
||||
|
||||
// Prevent sanitization bypass by preventing browers from directly rendering
|
||||
// the contents of HTML files kept in storage.
|
||||
if (headerType['Content-Type'].match(/html/)) {
|
||||
// the contents of untrusted content.
|
||||
if (headerType['Content-Type'].match(/html|xml/)) {
|
||||
headerType['Content-Type'] = 'text/plain; charset=utf-8';
|
||||
}
|
||||
|
||||
|
||||
@@ -84,7 +84,8 @@ describe('local publisher', () => {
|
||||
mockFs.restore();
|
||||
mockFs({
|
||||
[resolvedDir]: {
|
||||
'some-file.html': 'found it',
|
||||
'unsafe.html': '<html></html>',
|
||||
'unsafe.svg': '<svg></svg>',
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -93,10 +94,16 @@ describe('local publisher', () => {
|
||||
mockFs.restore();
|
||||
});
|
||||
|
||||
it('should pass text/plain content-type for html', async () => {
|
||||
const response = await request(app).get(`/some-file.html`);
|
||||
expect(response.text).toEqual('found it');
|
||||
expect(response.header).toMatchObject({
|
||||
it('should pass text/plain content-type for unsafe types', async () => {
|
||||
const htmlResponse = await request(app).get(`/unsafe.html`);
|
||||
expect(htmlResponse.text).toEqual('<html></html>');
|
||||
expect(htmlResponse.header).toMatchObject({
|
||||
'content-type': 'text/plain; charset=utf-8',
|
||||
});
|
||||
|
||||
const svgResponse = await request(app).get(`/unsafe.svg`);
|
||||
expect(svgResponse.text).toEqual('<svg></svg>');
|
||||
expect(svgResponse.header).toMatchObject({
|
||||
'content-type': 'text/plain; charset=utf-8',
|
||||
});
|
||||
});
|
||||
|
||||
@@ -292,9 +292,10 @@ describe('OpenStackSwiftPublish', () => {
|
||||
mockFs({
|
||||
[entityRootDir]: {
|
||||
html: {
|
||||
'file.html': '<html></html>',
|
||||
'unsafe.html': '<html></html>',
|
||||
},
|
||||
img: {
|
||||
'unsafe.svg': '<svg></svg>',
|
||||
'with spaces.png': 'found it',
|
||||
},
|
||||
'some folder': {
|
||||
@@ -327,17 +328,25 @@ describe('OpenStackSwiftPublish', () => {
|
||||
expect(jsResponse.text).toEqual('found it too');
|
||||
});
|
||||
|
||||
it('should pass text/plain content-type for html', async () => {
|
||||
it('should pass text/plain content-type for unsafe types', async () => {
|
||||
const {
|
||||
kind,
|
||||
metadata: { namespace, name },
|
||||
} = entity;
|
||||
|
||||
const response = await request(app).get(
|
||||
`/${namespace}/${kind}/${name}/html/file.html`,
|
||||
const htmlResponse = await request(app).get(
|
||||
`/${namespace}/${kind}/${name}/html/unsafe.html`,
|
||||
);
|
||||
expect(response.text).toEqual('<html></html>');
|
||||
expect(response.header).toMatchObject({
|
||||
expect(htmlResponse.text).toEqual('<html></html>');
|
||||
expect(htmlResponse.header).toMatchObject({
|
||||
'content-type': 'text/plain; charset=utf-8',
|
||||
});
|
||||
|
||||
const svgResponse = await request(app).get(
|
||||
`/${namespace}/${kind}/${name}/img/unsafe.svg`,
|
||||
);
|
||||
expect(svgResponse.text).toEqual('<svg></svg>');
|
||||
expect(svgResponse.header).toMatchObject({
|
||||
'content-type': 'text/plain; charset=utf-8',
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user