Test for sanitization bypass

Signed-off-by: Eric Peterson <ericpeterson@spotify.com>
This commit is contained in:
Eric Peterson
2021-05-28 14:06:44 +02:00
parent f2b339a30c
commit dc6cf3b14f
5 changed files with 114 additions and 8 deletions
@@ -286,6 +286,9 @@ describe('AwsS3Publish', () => {
mockFs.restore();
mockFs({
[entityRootDir]: {
html: {
'file.html': '<html></html>',
},
img: {
'with spaces.png': 'found it',
},
@@ -318,5 +321,20 @@ describe('AwsS3Publish', () => {
);
expect(jsResponse.text).toEqual('found it too');
});
it('should pass text/plain content-type for html', async () => {
const {
kind,
metadata: { namespace, name },
} = entity;
const response = await request(app).get(
`/${namespace}/${kind}/${name}/html/file.html`,
);
expect(response.text).toEqual('<html></html>');
expect(response.header).toMatchObject({
'content-type': 'text/plain; charset=utf-8',
});
});
});
});
@@ -343,6 +343,9 @@ describe('publishing with valid credentials', () => {
mockFs.restore();
mockFs({
[entityRootDir]: {
html: {
'file.html': '<html></html>',
},
img: {
'with spaces.png': 'found it',
},
@@ -375,5 +378,20 @@ describe('publishing with valid credentials', () => {
);
expect(jsResponse.text).toEqual('found it too');
});
it('should pass text/plain content-type for html', async () => {
const {
kind,
metadata: { namespace, name },
} = entity;
const response = await request(app).get(
`/${namespace}/${kind}/${name}/html/file.html`,
);
expect(response.text).toEqual('<html></html>');
expect(response.header).toMatchObject({
'content-type': 'text/plain; charset=utf-8',
});
});
});
});
@@ -285,6 +285,9 @@ describe('GoogleGCSPublish', () => {
mockFs.restore();
mockFs({
[entityRootDir]: {
html: {
'file.html': '<html></html>',
},
img: {
'with spaces.png': 'found it',
},
@@ -315,7 +318,21 @@ 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 () => {
const {
kind,
metadata: { namespace, name },
} = entity;
const response = await request(app).get(
`/${namespace}/${kind}/${name}/html/file.html`,
);
expect(response.text).toEqual('<html></html>');
expect(response.header).toMatchObject({
'content-type': 'text/plain; charset=utf-8',
});
});
});
});
@@ -16,8 +16,11 @@
import {
getVoidLogger,
PluginEndpointDiscovery,
resolvePackagePath,
} from '@backstage/backend-common';
import { ConfigReader } from '@backstage/config';
import express from 'express';
import request from 'supertest';
import mockFs from 'mock-fs';
import * as os from 'os';
import { LocalPublish } from './local';
@@ -35,11 +38,21 @@ const createMockEntity = (annotations = {}) => {
};
};
const testDiscovery: jest.Mocked<PluginEndpointDiscovery> = {
getBaseUrl: jest.fn().mockResolvedValue('http://localhost:7000/api/techdocs'),
getExternalBaseUrl: jest.fn(),
};
const logger = getVoidLogger();
const tmpDir =
os.platform() === 'win32' ? 'C:\\tmp\\generatedDir' : '/tmp/generatedDir';
const resolvedDir = resolvePackagePath(
'@backstage/plugin-techdocs-backend',
'static/docs',
);
describe('local publisher', () => {
it('should publish generated documentation dir', async () => {
mockFs({
@@ -48,13 +61,6 @@ describe('local publisher', () => {
},
});
const testDiscovery: jest.Mocked<PluginEndpointDiscovery> = {
getBaseUrl: jest
.fn()
.mockResolvedValue('http://localhost:7000/api/techdocs'),
getExternalBaseUrl: jest.fn(),
};
const mockConfig = new ConfigReader({});
const publisher = new LocalPublish(mockConfig, logger, testDiscovery);
@@ -66,4 +72,33 @@ describe('local publisher', () => {
mockFs.restore();
});
describe('docsRouter', () => {
const mockConfig = new ConfigReader({});
const publisher = new LocalPublish(mockConfig, logger, testDiscovery);
let app: express.Express;
beforeEach(() => {
app = express().use(publisher.docsRouter());
mockFs.restore();
mockFs({
[resolvedDir]: {
'some-file.html': 'found it',
},
});
});
afterEach(() => {
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({
'content-type': 'text/plain; charset=utf-8',
});
});
});
});
@@ -291,6 +291,9 @@ describe('OpenStackSwiftPublish', () => {
mockFs.restore();
mockFs({
[entityRootDir]: {
html: {
'file.html': '<html></html>',
},
img: {
'with spaces.png': 'found it',
},
@@ -323,5 +326,20 @@ describe('OpenStackSwiftPublish', () => {
);
expect(jsResponse.text).toEqual('found it too');
});
it('should pass text/plain content-type for html', async () => {
const {
kind,
metadata: { namespace, name },
} = entity;
const response = await request(app).get(
`/${namespace}/${kind}/${name}/html/file.html`,
);
expect(response.text).toEqual('<html></html>');
expect(response.header).toMatchObject({
'content-type': 'text/plain; charset=utf-8',
});
});
});
});