Continue to meet some requirement in the api security checklist: output with loopback/express.
Some recommendations:
- Send X-Content-Type-Options: nosniff header.
- Send X-Frame-Options: deny header.
- Send Content-Security-Policy: default-src ‘none’ header.
- Remove fingerprinting headers – X-Powered-By, Server, X-AspNet-Version etc.
In nodejs territory, with loopback/express area, we can control the header with helmet.
What’s helmetjs doing? It controls https header which help us meet some requirements above.
Lets do it with this loopback middleware setting.
{ "initial": { ... "helmet-csp": { "params": { "directives": { "defaultSrc": [ "\"none\"" ] } } }, "helmet#xssFilter": {}, "helmet#frameguard": { "params": { "action": "deny" } }, "helmet#hsts": { "params": { "maxAge": 0, "includeSubdomains": true } }, "helmet#hidePoweredBy": {}, "helmet#ieNoOpen": {}, "helmet#noSniff": {}, "helmet#noCache": { "enabled": false }, ... }
For Content-Security-Policy
setting, helmet dont enable it by default, so I will need to install another package helmet-csp
, which explains why the middleware setting has item helmet-csp
instead of helmet#...
like the others.
Cool, lets double check it. You can use curl to verify, but I love everything to be automatic. Lets do it with mocha and suppertest.
const request = require('supertest') const app = require('../../server/server') const faker = require('faker') const expect = require('chai').expect function req (verb, url) { return request(app)[verb](url) .set('Content-Type', 'application/json') .set('Accept', 'application/json') .expect('Content-Type', /json/) } describe('HTTP header', () => { describe('should send login request, and returned headers', () => { let headers before(done => { req('post', '/api/users/login') .send({ email: faker.internet.email(), password: faker.internet.password() }) .expect(401, function (err, res) { expect(err).to.be.null headers = res.header done() }) }) it('Content-Security-Policy: default-src none header', done => { expect(headers['content-security-policy']).to.be.eq('default-src "none"') done() }) it('X-Content-Type-Options: nosniff', done => { expect(headers['x-content-type-options']).to.be.eq('nosniff') done() }) it('X-Frame-Options: deny', done => { expect(headers['x-frame-options']).to.be.eq('DENY') done() }) it('remove header X-Powered-By, Server', done => { expect(headers['x-powered-by']).to.be.null expect(headers['server']).to.be.null done() }) }) })
Actually the middleware.json setting doing more than the API-Security-Checklist list on http header output. Read more at Loopback block on security practice