mirror of
https://github.com/verdaccio/verdaccio.git
synced 2024-12-16 21:56:25 -05:00
feat: add some security headers for web UI (#1295) @juanpicado
* feat: add some security headers for web UI The idea behind this is have more control over the content is rendered mostly via README. * chore: rename header for frame options * chore: rename method better name
This commit is contained in:
parent
5ee485e984
commit
615db0affb
4 changed files with 16 additions and 6 deletions
|
@ -22,9 +22,15 @@ export function match(regexp: RegExp) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function securityIframe(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer) {
|
export function setSecurityWebHeaders(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer) {
|
||||||
// disable loading in frames (clickjacking, etc.)
|
// disable loading in frames (clickjacking, etc.)
|
||||||
res.header('X-Frame-Options', 'deny');
|
res.header(HEADERS.FRAMES_OPTIONS, 'deny');
|
||||||
|
// avoid stablish connections outside of domain
|
||||||
|
res.header(HEADERS.CSP, "connect-src 'self'");
|
||||||
|
// https://stackoverflow.com/questions/18337630/what-is-x-content-type-options-nosniff
|
||||||
|
res.header(HEADERS.CTO, 'nosniff');
|
||||||
|
// https://stackoverflow.com/questions/9090577/what-is-the-http-header-x-xss-protection
|
||||||
|
res.header(HEADERS.XSS, '1; mode=block');
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ import addPackageWebApi from './endpoint/package';
|
||||||
import addSearchWebApi from './endpoint/search';
|
import addSearchWebApi from './endpoint/search';
|
||||||
|
|
||||||
import Search from '../../lib/search';
|
import Search from '../../lib/search';
|
||||||
import { match, validateName, validatePackage, securityIframe } from '../middleware';
|
import { match, validateName, validatePackage, setSecurityWebHeaders } from '../middleware';
|
||||||
import type { Config } from '@verdaccio/types';
|
import type { Config } from '@verdaccio/types';
|
||||||
import type { IAuth, IStorageHandler } from '../../../types';
|
import type { IAuth, IStorageHandler } from '../../../types';
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ export default function(config: Config, auth: IAuth, storage: IStorageHandler) {
|
||||||
|
|
||||||
route.use(bodyParser.urlencoded({ extended: false }));
|
route.use(bodyParser.urlencoded({ extended: false }));
|
||||||
route.use(auth.webUIJWTmiddleware());
|
route.use(auth.webUIJWTmiddleware());
|
||||||
route.use(securityIframe);
|
route.use(setSecurityWebHeaders);
|
||||||
|
|
||||||
addPackageWebApi(route, storage, auth, config);
|
addPackageWebApi(route, storage, auth, config);
|
||||||
addSearchWebApi(route, storage, auth);
|
addSearchWebApi(route, storage, auth);
|
||||||
|
|
|
@ -13,7 +13,7 @@ import Search from '../../lib/search';
|
||||||
import { HEADERS, HTTP_STATUS, WEB_TITLE } from '../../lib/constants';
|
import { HEADERS, HTTP_STATUS, WEB_TITLE } from '../../lib/constants';
|
||||||
import loadPlugin from '../../lib/plugin-loader';
|
import loadPlugin from '../../lib/plugin-loader';
|
||||||
|
|
||||||
const { securityIframe } = require('../middleware');
|
const { setSecurityWebHeaders } = require('../middleware');
|
||||||
const pkgJSON = require('../../../package.json');
|
const pkgJSON = require('../../../package.json');
|
||||||
|
|
||||||
export function loadTheme(config) {
|
export function loadTheme(config) {
|
||||||
|
@ -49,7 +49,7 @@ module.exports = function(config, auth, storage) {
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
|
||||||
router.use(auth.webUIJWTmiddleware());
|
router.use(auth.webUIJWTmiddleware());
|
||||||
router.use(securityIframe);
|
router.use(setSecurityWebHeaders);
|
||||||
const themePath = loadTheme(config) || require('@verdaccio/ui-theme')();
|
const themePath = loadTheme(config) || require('@verdaccio/ui-theme')();
|
||||||
const indexTemplate = path.join(themePath, 'index.html');
|
const indexTemplate = path.join(themePath, 'index.html');
|
||||||
const template = fs.readFileSync(indexTemplate).toString();
|
const template = fs.readFileSync(indexTemplate).toString();
|
||||||
|
|
|
@ -24,6 +24,10 @@ export const HEADERS = {
|
||||||
TEXT_PLAIN: 'text/plain',
|
TEXT_PLAIN: 'text/plain',
|
||||||
TEXT_HTML: 'text/html',
|
TEXT_HTML: 'text/html',
|
||||||
FORWARDED_PROTO: 'X-Forwarded-Proto',
|
FORWARDED_PROTO: 'X-Forwarded-Proto',
|
||||||
|
FRAMES_OPTIONS: 'X-Frame-Options',
|
||||||
|
CSP: 'Content-Security-Policy',
|
||||||
|
CTO: 'X-Content-Type-Options',
|
||||||
|
XSS: 'X-XSS-Protection',
|
||||||
ETAG: 'ETag',
|
ETAG: 'ETag',
|
||||||
JSON_CHARSET: 'application/json; charset=utf-8',
|
JSON_CHARSET: 'application/json; charset=utf-8',
|
||||||
OCTET_STREAM: 'application/octet-stream; charset=utf-8',
|
OCTET_STREAM: 'application/octet-stream; charset=utf-8',
|
||||||
|
|
Loading…
Reference in a new issue