Skip to content

Commit

Permalink
Merge pull request #370 from gilbitron/20220802-security
Browse files Browse the repository at this point in the history
Security Fixes 2022-08-02
  • Loading branch information
ryanlelek authored Aug 4, 2022
2 parents 28b6e8a + 67c7c63 commit 55e442c
Show file tree
Hide file tree
Showing 11 changed files with 94 additions and 27 deletions.
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

0 comments on commit 55e442c

Please sign in to comment.