Skip to content

Commit

Permalink
fix: Forbid mutation queries
Browse files Browse the repository at this point in the history
  • Loading branch information
sergeyshevch committed Aug 25, 2023
1 parent fc8f4c0 commit 455994e
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 7 deletions.
30 changes: 28 additions & 2 deletions packages/gitlab-backend/src/service/router.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,11 +197,23 @@ describe('createRouter', () => {
'/api/gitlab/non-existing-example.com/graphql'
);

console.log(method);
expect(response.status).toEqual(404);
expect(response.body).toEqual({});
}
});

it('Mutation queries should be rejected', async () => {
const agent = request.agent(app);
// this is set to let msw pass test requests through the mock server
agent.set('User-Agent', 'supertest');
const response = await agent
.post('/api/gitlab/non-existing-example-2.com/graphql')
.send({
query: 'mutation { createIssue { id } }',
});
expect(response.status).toEqual(404);
expect(response.body).toEqual({});
});
});

describe('Error requests', () => {
Expand Down Expand Up @@ -445,11 +457,25 @@ describe('createRouter with baseUrl', () => {
`${basePath}/api/gitlab/non-existing-example.com/graphql`
);

console.log(method);
expect(response.status).toEqual(404);
expect(response.body).toEqual({});
}
});

it('Mutation queries should be rejected', async () => {
const agent = request.agent(app);
// this is set to let msw pass test requests through the mock server
agent.set('User-Agent', 'supertest');
const response = await agent
.post(
`${basePath}/api/gitlab/non-existing-example-2.com/graphql`
)
.send({
query: 'mutation { createIssue { id } }',
});
expect(response.status).toEqual(404);
expect(response.body).toEqual({});
});
});

describe('Error requests', () => {
Expand Down
20 changes: 15 additions & 5 deletions packages/gitlab-backend/src/service/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import express from 'express';
import Router from 'express-promise-router';
import { Logger } from 'winston';
import { createProxyMiddleware } from 'http-proxy-middleware';
import { IncomingMessage } from 'http';
import { Request } from 'http-proxy-middleware/dist/types';
import bodyParser from 'body-parser';

function getBasePath(config: Config) {
const baseUrl = config.getOptionalString('backend.baseUrl');
Expand Down Expand Up @@ -37,25 +38,34 @@ export async function createRouter(

const router = Router();

// Add body parser middleware because we need to parse the body in the graphqlFilter
router.use(bodyParser.json());
router.use(bodyParser.urlencoded({ extended: true }));
router.use(bodyParser.text());

// We are filtering the proxy request headers here rather than in
// `onProxyReq` because when global-agent is enabled then `onProxyReq`
// fires _after_ the agent has already sent the headers to the proxy
// target, causing a ERR_HTTP_HEADERS_SENT crash
const filter = (_pathname: string, req: IncomingMessage): boolean => {
const filter = (_pathname: string, req: Request): boolean => {
if (req.headers['authorization']) delete req.headers['authorization'];
return req.method === 'GET';
};

const postFilter = (_pathname: string, req: IncomingMessage): boolean => {
const graphqlFilter = (_pathname: string, req: Request): boolean => {
if (req.headers['authorization']) delete req.headers['authorization'];
return req.method === 'POST';

return (
req.method === 'POST' &&
!JSON.stringify(req.body).includes('mutation')
);
};

for (const { host, apiBaseUrl, baseUrl, token } of gitlabIntegrations) {
const graphqlBaseUrl = new URL(baseUrl);
router.use(
`/${host}/graphql`,
createProxyMiddleware(postFilter, {
createProxyMiddleware(graphqlFilter, {
target: graphqlBaseUrl.origin,
changeOrigin: true,
headers: {
Expand Down

0 comments on commit 455994e

Please sign in to comment.