Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Security Fixes 2022-08-02 #370

Merged
merged 5 commits into from
Aug 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,25 @@ Supported Node Versions:
- v10.x.x (LTS)
Please use the latest version available of the above major Node.js releases to ensure you have the latest security fixes!

Security
--------
Make sure you edit the default username and password in your `config.js` file.
```
##### WARNING #####
// You MUST change the username and password for security
// Do NOT use "admin" as a username as it's easily guessed.
// You are encouraged to use tools to generate a password
// Preferably, use a local password manager
// If you absolutely must use an online tool, here are some suggestions
// https://bitwarden.com/password-generator/
// https://www.grc.com/passwords.htm
```

Markdown Reference
------------------
If you want to embed links and images, you'll need to use the Markdown syntax.
[See this Markdown Guide](https://www.markdownguide.org/cheat-sheet)

Links
---------------

Expand Down
9 changes: 5 additions & 4 deletions app/functions/get_filepath.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
'use strict';

// Modules
var path = require('path');
var sanitize = require('sanitize-filename');
var path = require('path');
var sanitizeFilename = require('sanitize-filename');
var sanitize = require('./sanitize.js');

function get_filepath (p) {

Expand All @@ -12,12 +13,12 @@ function get_filepath (p) {

// Add Category
if (p.category) {
filepath += '/' + sanitize(p.category);
filepath += '/' + sanitizeFilename(sanitize(p.category));
}

// Add File Name
if (p.filename) {
filepath += '/' + sanitize(p.filename);
filepath += '/' + sanitizeFilename(sanitize(p.filename));
}

// Normalize
Expand Down
19 changes: 19 additions & 0 deletions app/functions/sanitize.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@

'use strict';

// Modules
var validator = require('validator');

// Settings
var invalidChars = '&\'"/><';

// TODO: Add Test
function sanitizer (str) {
str = validator.blacklist(str, invalidChars);
str = validator.trim(str);
str = validator.escape(str);
return str;
}

// Exports
module.exports = exports = sanitizer;
8 changes: 6 additions & 2 deletions app/routes/category.create.route.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,14 @@ var get_filepath = require('../functions/get_filepath.js');
function route_category_create (config) {
return function (req, res, next) {

fs.mkdir(get_filepath({
// Generate filepath
// Sanitized within function
var filepath = get_filepath({
content : config.content_dir,
category : req.body.category
}), function (error) {
});

fs.mkdir(filepath, function (error) {
if (error) {
return res.json({
status : 1,
Expand Down
5 changes: 4 additions & 1 deletion app/routes/home.route.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ const utils = require('../core/utils');
function route_home (config) {
return async function (req, res, next) {

// Generate Filepath
// Generate filepath
// Sanitized within function
var filepath = get_filepath({
content : config.content_dir,
filename : 'index'
Expand All @@ -32,6 +33,8 @@ function route_home (config) {
filepath = filepath.slice(0, -suffix.length - 1);
}

// Generate filepath
// Sanitized within function
var template_filepath = get_filepath({
content : [config.theme_dir, config.theme_name, 'templates'].join('/'),
filename : 'home.html'
Expand Down
2 changes: 2 additions & 0 deletions app/routes/page.create.route.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ var get_filepath = require('../functions/get_filepath.js');
function route_page_create (config) {
return function (req, res, next) {

// Generate filepath
// Sanitized within function
var filepath = get_filepath({
content : config.content_dir,
category : req.body.category,
Expand Down
3 changes: 2 additions & 1 deletion app/routes/page.delete.route.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ function route_page_delete (config) {
file_name = req_file[1];
}

// Generate Filepath
// Generate filepath
// Sanitized within function
var filepath = get_filepath({
content : config.content_dir,
category : file_category,
Expand Down
10 changes: 9 additions & 1 deletion app/routes/page.edit.route.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

// Modules
var fs = require('fs-extra');
var validator = require('validator');
var get_filepath = require('../functions/get_filepath.js');
var create_meta_info = require('../functions/create_meta_info.js');

Expand All @@ -22,6 +23,7 @@ function route_page_edit (config) {
}

// Generate Filepath
// Sanitized within function
var filepath = get_filepath({
content : config.content_dir,
category : file_category,
Expand All @@ -42,8 +44,14 @@ function route_page_edit (config) {

var complete_content = create_content(req.body);

// Sanitize Content
// This will disallow <script> and <style> embeds
// because output will be HTML-encoded.
// If you need images, links, etc. use the Markdown format (see docs)
var sanitized_content = validator.escape(complete_content);

try {
await fs.writeFile(filepath, complete_content);
await fs.writeFile(filepath, sanitized_content);

res.json({
status : 0,
Expand Down
30 changes: 16 additions & 14 deletions app/routes/search.route.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
'use strict';

// Modules
var validator = require('validator');
// TODO: This underscore function may not be functioning correctly
var _s = require('underscore.string');
var remove_image_content_directory = require('../functions/remove_image_content_directory.js');
var sanitize = require('../functions/sanitize.js');

const searchHandler = require('../core/search');
const searchHandler = require('../core/search');
const contentsHandler = require('../core/contents');

function route_search (config) {
Expand All @@ -16,17 +17,18 @@ function route_search (config) {
if (!req.query.search) { return next(); }

// remove < and >
var tagFreeQuery = _s.stripTags(req.query.search);

// remove /, ', " and & from query
var invalidChars = '&\'"/';
var sanitizedQuery = validator.blacklist(tagFreeQuery, invalidChars);

// trim and convert to string
var searchQuery = sanitizedQuery.toString(sanitizedQuery).trim();

var searchResults = await searchHandler(searchQuery, config);
var pageListSearch = remove_image_content_directory(config, await contentsHandler(null, config));
var rawQuery = _s.stripTags(req.query.search);
var sanitizedQuery = sanitize(rawQuery);

// Using try/catch seems broken
var searchResults = [];
var pageListSearch = [];
try {
searchResults = await searchHandler(sanitizedQuery, config);
pageListSearch = remove_image_content_directory(config, await contentsHandler(null, config));
} catch (e) {
// Continue with defaults of empty arrays
}

// TODO: Move to Raneto Core
// Loop through Results and Extract Category
Expand All @@ -41,7 +43,7 @@ function route_search (config) {
return res.render('search', {
config,
pages : pageListSearch,
search : searchQuery,
search : sanitizedQuery,
searchResults,
body_class : 'page-search',
lang : config.lang,
Expand Down
8 changes: 8 additions & 0 deletions example/config.default.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,14 @@ var config = {
},
secret: 'someCoolSecretRightHere',

// ##### WARNING #####
// You MUST change the username and password for security
// Do NOT use "admin" as a username as it's easily guessed.
// You are encouraged to use tools to generate a password
// Preferably, use a local password manager
// If you absolutely must use an online tool, here are some suggestions
// https://bitwarden.com/password-generator/
// https://www.grc.com/passwords.htm
credentials : [
{
username : 'admin',
Expand Down
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
"body-parser": "1.20.0",
"bootstrap": "4.6.1",
"bootstrap-rtl": "3.3.4",
"commander": "9.3.0",
"commander": "9.4.0",
"cookie-parser": "1.4.6",
"debug": "4.3.4",
"express": "4.18.1",
Expand All @@ -63,7 +63,7 @@
"markdown-toc": "1.2.0",
"marked": "3.0.8",
"masonry-layout": "4.2.2",
"moment": "2.29.3",
"moment": "2.29.4",
"morgan": "1.10.0",
"node-fetch": "2.6.7",
"passport": "0.6.0",
Expand All @@ -72,15 +72,15 @@
"sanitize-filename": "1.6.3",
"serve-favicon": "2.5.0",
"sitemap": "7.1.1",
"sweetalert2": "11.4.20",
"sweetalert2": "11.4.24",
"underscore": "1.13.4",
"underscore.string": "3.3.6",
"validator": "13.7.0",
"gulp": "4.0.2"
},
"devDependencies": {
"chai": "4.3.6",
"eslint": "8.19.0",
"eslint": "8.21.0",
"eslint-config-standard": "17.0.0",
"eslint-plugin-import": "2.26.0",
"eslint-plugin-node": "11.1.0",
Expand Down