Skip to content

Commit

Permalink
Fix CSP handling (#4449)
Browse files Browse the repository at this point in the history
* Change incompatible module and fix a memory leak in the process

* Fix fonts, allow websocket

* Oops fix a brainfart with using the hostname

* Don't inlude null hostname

* Update the shrinkwrap

* Instantiate new cache if new instance of profile code is created. Calculate IOB with three digit precision to keep tests happy (and this is roughly the precision we're operating at anyway).

* - implement @jweismann suggestions #4449 (comment)
- add frameAncestors, baseUri and formAction protection

* update README and run doctoc

* fix reportOnly

* add objectSrc

* Use modern CSS loading

* Change CSS to use the "official" async loading across the board (which hopefully plays nicer with CSP)

* first release candiate for 0.11.2 with Minimed EU Server and Guardian Connect integration

- integrates mddub/minimed-connect-to-nightscout#11 into Nightscout

* bump node 10 LTS version

* increase logging, fix /swagger.yaml

* fix typo

* set version to rc2, update mongodb to 3.2.2

* add SECURE_CSP_REPORT_ONLY (default false).

* npm update and revert to requiring Node versions without security issues.
  • Loading branch information
sulkaharo authored and PieterGit committed Apr 6, 2019
1 parent db5d8fe commit d73958d
Show file tree
Hide file tree
Showing 20 changed files with 2,213 additions and 276 deletions.
3 changes: 2 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
**Table of Contents**

- [Contributing to cgm-remote-monitor](#contributing-to-cgm-remote-monitor)
- [Design](#design)
- [Design & new features](#design--new-features)
- [Develop on `dev`](#develop-on-dev)
- [Style Guide](#style-guide)
- [Create a prototype](#create-a-prototype)
- [Submit a pull request](#submit-a-pull-request)
- [Bug fixing](#bug-fixing)
- [Comments and issues](#comments-and-issues)
- [Co-ordination](#co-ordination)
- [Other Dev Tips](#other-dev-tips)
Expand Down
34 changes: 24 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ Community maintained fork of the
**Table of Contents**

- [Install](#install)
- [Supported configurations:](#supported-configurations)
- [Minimum browser requirements for viewing the site:](#minimum-browser-requirements-for-viewing-the-site)
- [Windows installation software requirements:](#windows-installation-software-requirements)
- [Installation notes for users with nginx or Apache reverse proxy for SSL/TLS offloading:](#installation-notes-for-users-with-nginx-or-apache-reverse-proxy-for-ssltls-offloading)
- [Installation notes for Microsoft Azure, Windows:](#installation-notes-for-microsoft-azure-windows)
- [Usage](#usage)
- [Updating my version?](#updating-my-version)
- [What is my mongo string?](#what-is-my-mongo-string)
Expand All @@ -60,7 +65,7 @@ Community maintained fork of the
- [Alarms](#alarms)
- [Core](#core)
- [Predefined values for your browser settings (optional)](#predefined-values-for-your-browser-settings-optional)
- [Views](#views)
- [Predefined values for your server settings (optional)](#predefined-values-for-your-server-settings-optional)
- [Plugins](#plugins)
- [Default Plugins](#default-plugins)
- [`delta` (BG Delta)](#delta-bg-delta)
Expand Down Expand Up @@ -108,7 +113,7 @@ Community maintained fork of the

# Install

Supported configurations:
## Supported configurations:

If you plan to use Nightscout, we recommend using [Heroku](http://www.nightscout.info/wiki/welcome/set-up-nightscout-using-heroku), as Nightscout can reach the usage limits of the free Azure plan and cause it to shut down for hours or days. If you end up needing a paid tier, the $7/mo Heroku plan is also much cheaper than the first paid tier of Azure. Currently, the only added benefit to choosing the $7/mo Heroku plan vs the free Heroku plan is a section showing site use metrics for performance (such as response time). This has limited benefit to the average Nightscout user. In short, Heroku is the free and best option for Nightscout hosting.

Expand All @@ -118,7 +123,7 @@ If you plan to use Nightscout, we recommend using [Heroku](http://www.nightscout
- Linux based install (Debian, Ubuntu, Raspbian) install with own Node.JS and MongoDB install (see software requirements below)
- Windows based install with own Node.JS and MongoDB install (see software requirements below)

Minimum browser requirements for viewing the site:
## Minimum browser requirements for viewing the site:

- Android 4
- Chrome 68
Expand All @@ -129,9 +134,9 @@ Minimum browser requirements for viewing the site:
- Safari 11
- Opera: 54

Windows installation software requirements:
## Windows installation software requirements:

- [Node.js](http://nodejs.org/) Latest Node 8 LTS (Node 8.15.1 or later) or Node 10 LTS (Node 10.15.3 or later; Node 10.14.1 works for Azure). Use [Install instructions for Node](https://nodejs.org/en/download/package-manager/) or use `setup.sh`)
- [Node.js](http://nodejs.org/) Latest Node 8 LTS (Node 8.15.1 or later) or Node 10 LTS (Node 10.15.2 or later; Node 10.14.1 works for Azure). Node versions that do not have the latest security patches will not work. Use [Install instructions for Node](https://nodejs.org/en/download/package-manager/) or use `setup.sh`)
- [MongoDB](https://www.mongodb.com/download-center?jmp=nav#community) 3.x or later. MongoDB 2.4 is only supported for Raspberry Pi.

As a non-root user clone this repo then install dependencies into the root of the project:
Expand All @@ -140,7 +145,15 @@ As a non-root user clone this repo then install dependencies into the root of th
$ npm install
```

Installation notes for Microsoft Azure, Windows:
## Installation notes for users with nginx or Apache reverse proxy for SSL/TLS offloading:

- Set `INSECURE_USE_HTTP` to `false`, to be able to use non secure HTTP connections to Nightscout server
- Your site redirects insecure connections to `https` by default. If you don't want that and use a Nginx or Apache proxy, set `INSECURE_USE_HTTP` to `true`. This will allow (unsafe) http traffic.
- In case you use a proxy. Do not use an external network interfaces for hosting Nightscout. Make sure the unsecure port is not available from a remote network connection
- HTTP Strict Transport Security (HSTS) headers are enabled by default, use settings `SECURE_HSTS_HEADER` and `SECURE_HSTS_HEADER_*`
- See [Predefined values for your server settings](#predefined-values-for-your-server-settings-optional) for more details

## Installation notes for Microsoft Azure, Windows:

- If deploying the software to Microsoft Azure, you must set ** in the app settings for *WEBSITE_NODE_DEFAULT_VERSION* and *SCM_COMMAND_IDLE_TIMEOUT* **before** you deploy the latest Nightscout or the site deployment will likely fail. Other hosting environments do not require this setting. Please use:
```
Expand Down Expand Up @@ -279,13 +292,14 @@ To learn more about the Nightscout API, visit https://YOUR-SITE.com/api-docs.htm
* `EDIT_MODE` (`on`) - possible values `on` or `off`. Enable or disable icon allowing enter treatments edit mode

### Predefined values for your server settings (optional)
* `INSECURE_USE_HTTP` (`false`) - Redirect http url's to https. Possible values `false`, or `true`.
* `INSECURE_USE_HTTP` (`false`) - Redirect unsafe http traffic to https. Possible values `false`, or `true`. Your site redirects to `https` by default. If you don't want that from Nightscout, but want to implement that with a Nginx or Apache proxy, set `INSECURE_USE_HTTP` to `true`. Note: This will allow (unsafe) http traffic to your Nightscout instance and is not recommended.
* `SECURE_HSTS_HEADER` (`true`) - Add HTTP Strict Transport Security (HSTS) header. Possible values `false`, or `true`.
* `SECURE_HSTS_HEADER_INCLUDESUBDOMAINS` (`false`) - includeSubdomains options for HSTS. Possible values `false`, or `true`.
* `SECURE_HSTS_HEADER_PRELOAD` (`false`) - ask for preload in browsers for HSTS. Possible values `false`, or `true`.
* `SECURE_CSP` (`false`) - Add Content Security Policy headers. Possible values `false`, or `true`. Currently Nightscout is not yet compatible with CSP.

### Views
* `SECURE_CSP` (`false`) - Add Content Security Policy headers. Possible values `false`, or `true`.
* `SECURE_CSP_REPORT_ONLY` (`false`) - If set to `true` allows to experiment with policies by monitoring (but not enforcing) their effects. Possible values `false`, or `true`.

### Views

There are a few alternate web views available that display a simplified BG stream. Append any of these to your Nightscout URL:
* `/clock.html` - Shows current BG. Grey text on a black background.
Expand Down
42 changes: 38 additions & 4 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ function create(env, ctx) {
app.enable('trust proxy'); // Allows req.secure test on heroku https connections.
var insecureUseHttp = env.insecureUseHttp;
var secureHstsHeader = env.secureHstsHeader;
console.info('Security settings: INSECURE_USE_HTTP=',insecureUseHttp,', SECURE_HSTS_HEADER=',secureHstsHeader);
if (!insecureUseHttp) {
console.info('Redirecting http traffic to https because INSECURE_USE_HTTP=', insecureUseHttp);
app.use((req, res, next) => {
if (req.header('x-forwarded-proto') == 'https' || req.secure) {
next();
Expand All @@ -26,6 +26,7 @@ function create(env, ctx) {
}
})
if (secureHstsHeader) { // Add HSTS (HTTP Strict Transport Security) header
console.info('Enabled SECURE_HSTS_HEADER (HTTP Strict Transport Security)');
const helmet = require('helmet');
var includeSubDomainsValue = env.secureHstsHeaderIncludeSubdomains;
var preloadValue = env.secureHstsHeaderPreload;
Expand All @@ -35,19 +36,46 @@ function create(env, ctx) {
includeSubDomains: includeSubDomainsValue,
preload: preloadValue
}
}))
}));
if (env.secureCsp) {
var secureCspReportOnly= env.secureCspReportOnly;
if (secureCspReportOnly) {
console.info( 'Enabled SECURE_CSP (Content Security Policy header). Not enforcing. Report only.' );
} else {
console.info( 'Enabled SECURE_CSP (Content Security Policy header). Enforcing.' );
}
app.use(helmet.contentSecurityPolicy({ //TODO make NS work without 'unsafe-inline'
directives: {
defaultSrc: ["'self'"],
styleSrc: ["'self'", 'https://fonts.googleapis.com/',"'unsafe-inline'"],
scriptSrc: ["'self'", "'unsafe-inline'"],
fontSrc: [ "'self'", 'https://fonts.gstatic.com/']
}
fontSrc: [ "'self'", 'https://fonts.gstatic.com/', 'data:'],
imgSrc: [ "'self'", 'data:'],
objectSrc: ["'none'"], // Restricts <object>, <embed>, and <applet> elements
reportUri: '/report-violation',
frameAncestors: ["'none'"], // Clickjacking protection, using frame-ancestors
baseUri: ["'none'"], // Restricts use of the <base> tag
formAction: ["'self'"], // Restricts where <form> contents may be submitted
},
reportOnly: secureCspReportOnly
}));
app.use(helmet.referrerPolicy({ policy: 'no-referrer' }));
app.use(helmet.featurePolicy({ features: { payment: ["'none'"], } }));
app.use(bodyParser.json({type: ['json', 'application/csp-report'] }))
app.post('/report-violation', (req, res) => {
if (req.body) {
console.log('CSP Violation: ', req.body) }
else {
console.log('CSP Violation: No data received!')
}
res.status(204).end()
})
}
}
}
else {
console.info('Security settings: INSECURE_USE_HTTP=',insecureUseHttp,', SECURE_HSTS_HEADER=',secureHstsHeader);
}

app.set('view engine', 'ejs');
// this allows you to render .html files as templates in addition to .ejs
Expand Down Expand Up @@ -140,6 +168,12 @@ function create(env, ctx) {
res.sendFile(__dirname + '/swagger.json');
});

// expose swagger.yaml
app.get('/swagger.yaml', function(req, res) {
res.sendFile(__dirname + '/swagger.yaml');
});


/*
if (env.settings.isEnabled('dumps')) {
var heapdump = require('heapdump');
Expand Down
21 changes: 21 additions & 0 deletions docs/plugins/maker-setup.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,24 @@
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*

- [Nightscout/IFTTT Maker](#nightscoutifttt-maker)
- [Overview](#overview)
- [Note: There have been some recent reports of the IFTTT service delaying Nightscout alarms. Be sure to test your implementation before relying solely on its alerts. Pushover is an alternate push notification service that might be worth considering as well.](#note-there-have-been-some-recent-reports-of-the-ifttt-service-delaying-nightscout-alarms-be-sure-to-test-your-implementation-before-relying-solely-on-its-alerts-pushover-is-an-alternate-push-notification-service-that-might-be-worth-considering-as-well)
- [Events](#events)
- [Creating an Applet](#creating-an-applet)
- [1. Choose a Service](#1-choose-a-service)
- [2. Choose a Trigger](#2-choose-a-trigger)
- [3. Complete the Trigger field](#3-complete-the-trigger-field)
- [4. Create an Action](#4-create-an-action)
- [5. Complete Action Fields](#5-complete-action-fields)
- [6. Review and Finish](#6-review-and-finish)
- [7. Get your Maker Key](#7-get-your-maker-key)
- [8. Configure your Nightscout site](#8-configure-your-nightscout-site)
- [9. Configure the IFTTT mobile app](#9-configure-the-ifttt-mobile-app)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->

**Table of Contents**

- [Nightscout/IFTTT Maker](#nightscoutifttt-maker)
Expand Down
2 changes: 1 addition & 1 deletion env.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ function setSSL() {
env.secureHstsHeaderIncludeSubdomains = readENVTruthy("SECURE_HSTS_HEADER_INCLUDESUBDOMAINS", false);
env.secureHstsHeaderPreload= readENVTruthy("SECURE_HSTS_HEADER_PRELOAD", false);
env.secureCsp = readENVTruthy("SECURE_CSP", false);

env.secureCspReportOnly = readENVTruthy("SECURE_CSP_REPORT_ONLY", false);
}

// A little ugly, but we don't want to read the secret into a var
Expand Down
6 changes: 3 additions & 3 deletions lib/plugins/iob.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ function init(ctx) {
if (_.isEmpty(result)) {
result = treatmentResult;
} else if (treatmentResult.iob) {
result.treatmentIob = treatmentResult.iob;
result.treatmentIob = +(Math.round(treatmentResult.iob + "e+3") + "e-3");
}

if (result.iob) result.iob = +(Math.round(result.iob + "e+3") + "e-3");
return addDisplay(result);
};

Expand Down Expand Up @@ -162,7 +162,7 @@ function init(ctx) {
});

return {
iob: totalIOB
iob: +(Math.round(totalIOB + "e+3") + "e-3")
, activity: totalActivity
, lastBolus: lastBolus
, source: translate('Care Portal')
Expand Down
17 changes: 9 additions & 8 deletions lib/profilefunctions.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,19 @@

var _ = require('lodash');
var moment = require('moment-timezone');
var NodeCache = require('node-cache');
var c = require('memory-cache');
var times = require('./times');
var crypto = require('crypto');

var cacheTTL = 600;

var prevBasalTreatment = null;

function init (profileData) {

var profile = { };
var cache = new c.Cache();

profile.timeValueCache = new NodeCache({ stdTTL: 600, checkperiod: 600 });

profile.loadData = function loadData (profileData) {
if (profileData && profileData.length) {
profile.data = profile.convertToProfileStore(profileData);
Expand Down Expand Up @@ -86,7 +87,7 @@ function init (profileData) {
var minuteTime = Math.round(time / 60000) * 60000;

var cacheKey = (minuteTime + valueType + spec_profile + profile.profiletreatments_hash);
var returnValue = profile.timeValueCache[cacheKey];
var returnValue = cache.get(cacheKey);

if (returnValue) {
return returnValue;
Expand Down Expand Up @@ -132,7 +133,7 @@ function init (profileData) {
}
}

profile.timeValueCache[cacheKey] = returnValue;
cache.put(cacheKey, returnValue, cacheTTL);

return returnValue;
};
Expand Down Expand Up @@ -258,7 +259,7 @@ function init (profileData) {
}

returnValue = treatment;
profile.timeValueCache[cacheKey] = returnValue;
cache.put(cacheKey, returnValue, cacheTTL);
return returnValue;
};

Expand Down Expand Up @@ -309,7 +310,7 @@ function init (profileData) {
profile.getTempBasal = function getTempBasal (time, spec_profile) {

var cacheKey = 'basal' + time + profile.tempbasaltreatments_hash + profile.combobolustreatments_hash + profile.profiletreatments_hash + spec_profile;
var returnValue = profile.timeValueCache[cacheKey];
var returnValue = cache.get(cacheKey);

if (returnValue) {
return returnValue;
Expand Down Expand Up @@ -338,7 +339,7 @@ function init (profileData) {
, combobolusbasal: combobolusbasal
, totalbasal: tempbasal + combobolusbasal
};
profile.timeValueCache[cacheKey] = returnValue;
cache.put(cacheKey, returnValue, cacheTTL);
return returnValue;
};

Expand Down
11 changes: 6 additions & 5 deletions lib/server/bootevent.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,24 @@ function boot (env, language) {
// Check Node version.
// Latest Node 8 LTS and Latest Node 10 LTS are recommended and supported.
// Latest Node version on Azure is tolerated, but not recommended
// Latest Node (non LTS) version works, but not recommended
// Other versions will not start
// Latest Node (non LTS) version works, but is not recommended
// Older Node versions or Node versions with known security issues will not work.
// More explicit:
// < 8 does not work, not supported
// >= 8.15.1 works, supported and recommended
// == 9.x does not work, not supported
// == 10.14.1 works, not fully supported and not recommended (Azure version)
// == 10.14.2 does not work, not supported and not recommended,
// >= 10.15.3 works, supported and recommended
// >= 10.15.2 works, supported and recommended
// >= 11.12.0 does work, not recommended, will not be supported. We only support Node LTS releases
///////////////////////////////////////////////////
function checkNodeVersion (ctx, next) {
var semver = require('semver');
var nodeVersion = process.version;

if ( semver.satisfies(nodeVersion, '^8.15.1') || semver.satisfies(nodeVersion, '^10.15.3')) {
if ( semver.satisfies(nodeVersion, '^8.15.1') || semver.satisfies(nodeVersion, '^10.15.2')) {
//Latest Node 8 LTS and Latest Node 10 LTS are recommended and supported.
//Require at least Node 8 LTS and Node 10 LTS without known security issues
console.debug('Node LTS version ' + nodeVersion + ' is supported');
next();
}
Expand All @@ -42,7 +43,7 @@ function boot (env, language) {
next();
} else {
// Other versions will not start
console.log( 'ERROR: Node version ' + nodeVersion + ' is not supported. Please upgrade your Node');
console.log( 'ERROR: Node version ' + nodeVersion + ' is not supported. Please use a secure LTS version or upgrade your Node');
process.exit(1);
}
}
Expand Down
Loading

0 comments on commit d73958d

Please sign in to comment.