Skip to content

Commit

Permalink
fix: 🐛 security improvements
Browse files Browse the repository at this point in the history
The servers listen only on specific IP. The create template is updated
for whitelisting CORS request by origin. The possibilites XSS
vulnerability is fixed for playground page and in plugin custom element.
  • Loading branch information
mjancarik committed Jul 18, 2024
1 parent a275b46 commit 42212a5
Show file tree
Hide file tree
Showing 10 changed files with 50 additions and 22 deletions.
3 changes: 3 additions & 0 deletions docs/docs/merkur-cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ export default function ({ cliConfig, emitter, }) {
origin: 'http://localhost:4444'
},
HMR: true,
constant: {
HOST: 'localhost',
}
onCliConfig, Function, //extending hook for cli config,
onMerkurConfig: Function, // extending hook for merkur config,
onTaskConfig: Function, // extending hook for task config,
Expand Down
7 changes: 6 additions & 1 deletion packages/cli/src/devServer.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ import express from 'express';
import { createLogger } from './logger.mjs';
import { COMMAND_NAME } from './commands/constant.mjs';

function escapeToJSON(object) {
return JSON.stringify(object).replace(/<\/script/gi, '<\\/script');
}

function asyncMiddleware(fn) {
return (req, res, next) => {
Promise.resolve(fn(req, res, next)).catch(next);
Expand Down Expand Up @@ -135,6 +139,7 @@ export async function runDevServer({ context, merkurConfig, cliConfig }) {
merkurConfig,
devClient,
html,
escapeToJSON,
}),
);
}),
Expand Down Expand Up @@ -167,7 +172,7 @@ export async function runDevServer({ context, merkurConfig, cliConfig }) {
},
});
})
.listen(port, () => {
.listen({ port, host: merkurConfig.constant.HOST }, () => {
logger.info(`Playground: ${chalk.green(`${protocol}//${host}`)}`);
resolve(app);
});
Expand Down
16 changes: 14 additions & 2 deletions packages/cli/src/merkurConfig.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -253,8 +253,20 @@ emitter.on(
return merkurConfig;
},
);
emitter.on(EMITTER_EVENTS.MERKUR_CONFIG, function devServer({ merkurConfig }) {
merkurConfig.HMR = merkurConfig?.HMR ?? true;

emitter.on(EMITTER_EVENTS.MERKUR_CONFIG, function hmr({ merkurConfig }) {
merkurConfig.HMR = merkurConfig.HMR ?? true;

return merkurConfig;
});

emitter.on(EMITTER_EVENTS.MERKUR_CONFIG, function constant({ merkurConfig }) {
merkurConfig.constant = {
...{
HOST: 'localhost',
},
...merkurConfig.constant,
};

return merkurConfig;
});
2 changes: 1 addition & 1 deletion packages/cli/src/templates/body.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<div class="merkur-view"><%- html %></div>
<script>
window.addEventListener('load', function () {
__merkur__.create(<%- JSON.stringify(widgetProperties) %>)
__merkur__.create(<%- escapeToJSON(widgetProperties) %>)
.then(function (widget) {
widget.containerSelector = '.merkur-view';
if (widget?.slot?.headline) {
Expand Down
6 changes: 3 additions & 3 deletions packages/cli/src/templates/head.ejs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<script>
window.__merkur_dev__ = window.__merkur_dev__ || {};
window.__merkur_dev__.merkurConfig = <%- JSON.stringify(merkurConfig) %>;
window.__merkur_dev__.assets = <%- JSON.stringify(assets) %>;
window.__merkur_dev__.widgetProperties = <%- JSON.stringify(widgetProperties) %>;
window.__merkur_dev__.merkurConfig = <%- escapeToJSON(merkurConfig) %>;
window.__merkur_dev__.assets = <%- escapeToJSON(assets) %>;
window.__merkur_dev__.widgetProperties = <%- escapeToJSON(widgetProperties) %>;
<%- devClient %>
</script>
<% assets.forEach((asset)=> { %>
Expand Down
1 change: 1 addition & 0 deletions packages/cli/src/websocket.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export async function runSocketServer({ merkurConfig, context }) {
try {
const server = new WebSocketServer({
port: merkurConfig.socketServer.port,
host: merkurConfig.constant.HOST,
});

server.on('connection', function connection(ws) {
Expand Down
5 changes: 5 additions & 0 deletions packages/cli/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,13 @@ export interface WidgetServer {
clusters: number;
}

export interface Constant {
HOST: string;
}

export interface MerkurConfig {
HMR: boolean;
constant: Constant;
cliConfig: CLIConfig;
extends: Extend[];
task: {
Expand Down
21 changes: 11 additions & 10 deletions packages/create-widget/template/server/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ const morgan = require('morgan');

const { resolveConfig } = require('@merkur/cli/server');

const { merkurConfig } = resolveConfig();
const {
merkurConfig: { widgetServer, devServer },
} = resolveConfig();

const {
apiErrorMiddleware,
Expand Down Expand Up @@ -38,18 +40,17 @@ app
crossOriginEmbedderPolicy: false,
}),
)
.use(cors())
.use(compression())
.use(
merkurConfig.widgetServer.staticPath,
express.static(merkurConfig.widgetServer.staticFolder),
cors({
origin: devServer.origin,
optionsSuccessStatus: 200, // some legacy browsers (IE11, various SmartTVs) choke on 204
}),
)
.use(compression())
.use(widgetServer.staticPath, express.static(widgetServer.staticFolder))
.use(
merkurConfig.widgetServer.staticPath,
expressStaticGzip(
merkurConfig.widgetServer.staticFolder,
expressStaticConfig,
),
widgetServer.staticPath,
expressStaticGzip(widgetServer.staticFolder, expressStaticConfig),
)
.use(widgetAPI.router)
.use(error.router)
Expand Down
4 changes: 2 additions & 2 deletions packages/create-widget/template/server/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const { merkurConfig } = resolveConfig();

const { app } = require('./app');

const { widgetServer } = merkurConfig;
const { widgetServer, constant } = merkurConfig;

process.on('uncaughtException', (error) => {
console.error(error);
Expand All @@ -17,7 +17,7 @@ process.on('unhandledRejection', (error) => {
});

if (!widgetServer.clusters || !cluster.isMaster) {
const server = app.listen(widgetServer.port);
const server = app.listen({ port: widgetServer.port, host: constant.HOST });

const handleExit = () => {
server.close(() => {
Expand Down
7 changes: 4 additions & 3 deletions packages/integration-custom-element/cli/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,15 @@ export function merkurCustomElementCssBundlePlugin({ cliConfig, config }) {
encoding: 'utf8',
flag: 'r',
});
css = css.replace(/\n/g, ' ');
css = JSON.stringify(css.replace(/\n/g, ' '));

let js = fs.readFileSync(`${projectFolder}/${key}`, {
encoding: 'utf8',
flag: 'r',
});
js = js.replace('{__bundle__:""}', `\`${css}\``);
js = js.replace('{ __bundle__: "" };', `\`${css}\``);

js = js.replace('{__bundle__:""}', `${css}`);
js = js.replace('{ __bundle__: "" };', `${css}`);

fs.writeFileSync(`${projectFolder}/${key}`, js);
} catch (error) {
Expand Down

0 comments on commit 42212a5

Please sign in to comment.