├── README.md ├── doc ├── files.html ├── index.html └── symbols │ ├── .html │ ├── Error.html │ ├── SecurityError.html │ ├── _global_.html │ ├── exports.SecurityError.html │ ├── module.html │ ├── nodeSecure.html │ ├── secure SecurityError.html │ ├── secure.SecurityError.html │ ├── secure.html │ └── src │ └── js_node-secure.js.html ├── js └── node-secure.js ├── package.json ├── run-tests.sh └── test ├── README ├── node-secure-events-test.js ├── node-secure-overridden-test.js ├── node-secure-standard-test.js └── test-commons.js /README.md: -------------------------------------------------------------------------------- 1 | node-secure 2 | =========== 3 | 4 | ### Description 5 | **node-secure** is a tiny module for Node.JS which protects some globals (`undefined`, `NaN`, 6 | `Infinity`, `eval`, `isNaN`) from being overridden and adds functionality to protect your 7 | modules from hacking and code injection
8 | Author: **David de Rosier**
9 | License: **public domain**
10 | Installation: **npm install node-secure** 11 | 12 | ### Server-side must be secured! 13 | 14 | Hope we all agree that server-side programming requires special attention. 15 | An error on this level can crash not only a single client (browser), but entire 16 | server. Moreover we need to take an extra care of the security. 17 | JavaScript is a super dynamic language that allows us to rapidly implement server functionality, 18 | but it also leaves open doors for hackers (through code injections from client). 19 | We can also often struggle from some strange/stupid/typo mistakes which are difficult to find. 20 | 21 | Example? Lets start from something simple. JavaScript does not protect 22 | global variables like `undefined`. Overriding such value can be dangerous - 23 | in example the _http_ module of Node.JS uses insecure comparisons with `undefined` value, 24 | so following example: 25 | 26 | ```js 27 | undefined = 666; 28 | var http = require('http'); 29 | http.createServer(function (req, res) { 30 | res.writeHead(200, {'Content-Type': 'text/plain'}); 31 | res.end('Hello World\n'); 32 | }).listen(1337, "127.0.0.1"); 33 | ``` 34 | 35 | will kill the entire server after first HTTP request with 36 | "_Cannot call method 'slice' of null_" error. Not easy to find a real source of 37 | problem with such message, isn't it? 38 | 39 | 40 | ### V8 means ECMAScript 5 41 | 42 | Fortunately ECMAScript 5 brings some features, which can limit 43 | an access to object properties. They can be even used on standard global properties, 44 | like `undefined`. And we don't have to bother about backward-compatibility on Node.JS. 45 | The basic code snippet presented below can protect the standard global variables for 46 | entire application: 47 | 48 | ```js 49 | Object.defineProperty && (function(){ 50 | // take global object 51 | var global = (function(){return this;})(); 52 | 53 | // when "strict mode' is on we can leave - globals are protected by default 54 | if(!global) return; 55 | 56 | // redefine proper values in case they got overridden 57 | undefined = void 0; 58 | NaN = 0/0; 59 | Infinity = 1/0; 60 | 61 | // make globals read only and non-configurable 62 | ["undefined", "NaN", "Infinity"].forEach(function(key){ 63 | Object.defineProperty(global, key, {writable: false, configurable: false}); 64 | }); 65 | })(); 66 | ``` 67 | 68 | The code above is quite universal and will work on all environments (browsers, SSJS, Rhino, etc) 69 | which provide property descriptor functionality. I would recommend to copy-paste such 70 | code to the main modules of all your applications (if you are not planning to use node-secure module - 71 | which gives much more control). 72 | 73 | 74 | ### spoon="strict mode"; there is no spoon! 75 | 76 | Some developers might say that we shouldn't bother about global variables in Node.JS because 77 | there is a strict mode. Theoretically true, but... currently V8 supports all features of ECMAScript 5 excluding... 78 | the strict mode! Doors for insecurity remains open! 79 | 80 | 81 | ### What is node-secure? 82 | 83 | node-secure is a tiny module for Node.JS which gives some protection mechanisms to your code. 84 | In particular: 85 | 86 | 1. It protects the standard global variables (`undefined`, `NaN`, `Infinity`, `isNaN`) from being overridden. 87 | 2. It gives an extra control on most insecure element of the language - `eval` function. With 88 | node-secure you will be able to track each execution of `eval` with typical for Node.JS 89 | behavior - events. Every time someone executes `eval`, the module will emit an event with a 90 | reference to executor function. Why to bother about events? Wouldn't be better to just 91 | override the evil `eval` with empty function? Well.. some of the modules you use may operate on `eval`. 92 | Better not to break the existing functionality. 93 | 3. The module provides two utility functions - `secureMethods` and `securePrivates`. 94 | First one protects all methods of given object from being overridden. Why? In most of the cases 95 | you wouldn't like to let your own methods being overridden by external code, so is better to keep them 96 | read-only - especially in your custom modules. 97 | 98 | Second method makes all private-like elements of an object (named with underscore prefix) non-enumerable. 99 | If you don't want to hide elements fully (using closures) and just use naming convention for it, 100 | you can add an extra protection by hiding the private elements from being enumerable. 101 | 4. There is a risky situation when someone override and protect `eval` or standard globals before 102 | you even load the node-secure module. In such case the module won't be able to secure 103 | the application. However you can control this situation by calling `isSecure` method or by checking 104 | `status` object. The status can tell you exactly which element couldn't be secured. Moreover 105 | every time when protection of global elements fails, the module will produce an _insecure_ event. 106 | 107 | 108 | #### Installation 109 | 110 | ``` 111 | npm install node-secure 112 | ``` 113 | 114 | 115 | #### Examples 116 | 117 | Just load the module to protect standard globals variables and the `eval` function 118 | 119 | ```js 120 | require("node-secure"); 121 | undefined = 666; // nothing happen (in non strict mode there is no error, however the value won't be overridden) 122 | ``` 123 | 124 | To control execution of `eval`, add the listener: 125 | 126 | ```js 127 | var secure = require("node-secure"); 128 | secure.on("eval", function(caller){ 129 | console.log("Evel executed in following function: "+caller); 130 | }); 131 | ``` 132 | 133 | To check whether the module managed to protect all elements you can define another listener: 134 | 135 | ```js 136 | var secure = require("node-secure"); 137 | secure.on("insecure", function(problems){ 138 | console.log("Some of globals couldn't be protected: "+problems); 139 | }); 140 | ``` 141 | 142 | eventually you can directly check the statuses: 143 | 144 | ```js 145 | if( !secure.isSecure() ) { 146 | console.log("There are some security issues"); 147 | if(secure.status.UNDEFINED_VALUE && secure.status.UNDEFINED_PROTECTION) { 148 | console.log("Fortunately undefined is secured"); 149 | } 150 | } 151 | ``` 152 | 153 | Finally you can protect your own objects. Consider it especially for your custom modules. 154 | 155 | ```js 156 | var secure = require("node-secure"); 157 | exports.test = function(){...}; 158 | // at the end of the module code 159 | secure.secureMethods(exports); 160 | ``` 161 | 162 | Code above just sets the writable flag to _false_ for all methods in given object. So you can always 163 | redefine the access with property descriptor, unless you make the methods non-configurable: 164 | 165 | ```js 166 | secure.secureMethods(exports, {configurable: false}); 167 | ``` 168 | 169 | Remember to hide the private-like elements of your object for `for..in` or `Object.keys` operations: 170 | 171 | ```js 172 | var secure = require("node-secure"); 173 | obj = { 174 | __salary: 1024, 175 | __utilMethod: function(){}, 176 | getSalary: function(){ return this.__salary } 177 | }; 178 | secure.securePrivates(obj); 179 | ``` 180 | 181 | In practice `securePrivates` and `secureMethods` can fail for already non-configurable members. 182 | Fortunately node-secure allows you to track such situation. Lets take example code: 183 | 184 | ```js 185 | var secure = require("node-secure"); 186 | 187 | var obj = { 188 | test: function(){}, 189 | __prv1: 0 190 | }; 191 | 192 | Object.defineProperty(obj, "test", {configurable:false}); 193 | Object.defineProperty(obj, "__prv1", {configurable:false}); 194 | ``` 195 | 196 | and consider some cases: 197 | 198 | ```js 199 | secure.secureMethods(obj); 200 | ``` 201 | 202 | everything is fine here. According to ECMAScript 5 specification you can change the value of _writable_ 203 | property from _true_ to _false_ (but not opposite) even if the property is marked as non-configurable. 204 | However: 205 | 206 | ```js 207 | secure.secureMethods(obj, {enumerable: false, configurable: true}); 208 | ``` 209 | 210 | will not work, because there is not possible to change `enumerable` and `configurable` attributes 211 | of non-configurable property. You can track such situation with node-secure: 212 | 213 | ```js 214 | secure.secureMethods(obj, {enumerable: false, configurable: true}, function(errors){ 215 | console.log("not all methods were properly protected. Reasons: " + errors); 216 | }); 217 | ``` 218 | 219 | Listener function takes as an attribute an array of objects. Each object contains 220 | property and error attributes. `secureMethods` and `securePrivates` never fail when 221 | they can't protect some of the object elements. They continue and produce a report 222 | which you can check with callback function. 223 | 224 | 225 | ### New to property descriptors? 226 | 227 | If your are new to the concept of ECMAScript 5 property descriptors and the things here seem to 228 | be bit strange for you - just see the great 229 | [ECMAScript 5 Object methods cheatsheet](http://kasia.drzyzga.pl/2011/06/ecmascript-5-object-methods-cheatsheet/) 230 | written by Kasia Drzyzga. 231 | 232 | -------------------------------------------------------------------------------- /doc/files.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | JsDoc Reference - File Index 8 | 9 | 10 | 174 | 175 | 176 | 177 | 179 | 180 |
181 |
Class Index 182 | | File Index
183 |
184 |

Classes

185 | 196 |
197 |
198 | 199 |
200 |

File Index

201 | 202 | 203 |
204 |

node-secure.js

205 | 206 |

207 | This simple module allows to protect the code using ECMAScript 5 features, 208 | even when strict mode is not available. 209 |

210 | First it makes all global constants (undefined, NaN, Infinity) non-writable. 211 | and non-configurable. 212 | How important it is you can check by running basic example: 213 | - override undefined with real value 214 | - run http server and make request 215 | Due to unprotected comparisons to undefined value in http module, the entire 216 | server will fail with TypeError (tested on node.js 0.4.8) 217 | Such basic code can be intentionally injected to a server by a hacker 218 | or created by mistake by unexperienced developer. 219 |

220 | Secondly - the module allows you to protect your own code from 221 | intentional/unintentional overriding. The main element which you should 222 | protect are your methods. In most of the cases your code won't work properly 223 | if your methods will be overridden. 224 | Other important thing is to hide private-like members from being enumerable. 225 | Especially when they are not physically private (i.e by usage of closures), 226 | but marked as private with naming convention (using single or double 227 | underscore prefix). 228 |

229 | Third thing is to control execution of eval function - which brings the bigger 230 | risk of potential attacks (execution of injected code fragments). Theoretically 231 | there is possible to override eval (i.e. with empty function), however it can 232 | break other modules which operate on eval function. This module extends eval 233 | with notification mechanism - every time when someone execute eval your program 234 | will be notified about it with "eval" event. The event takes reference to 235 | executor function. 236 |

237 | The dynamic nature of JavaScript gives to developer a freedom of quick 238 | and smart programming. However server-side code should be protected as much 239 | as possible from code injections and hacking. The visibility of code and 240 | easy code inspection mechanism often can leave open doors for bad 241 | intensions and code replacements. 242 |

243 | 244 | 245 |
246 | USAGE
247 | 
248 | 1. Just load the module to protect global statics (undefined, NaN, Infinity)
249 |    example: require('node-secure');
250 |    
251 | 2. Just load the module to control execution of eval (evil?) function.
252 |    With this module eval will work as previously, but every time someone
253 |    execute it, you will get an event notification
254 |    Example: 
255 |       var secure = require("node-secure");
256 |       secure.on("eval", function(f){"Evaluation executed in function "+f.name});
257 |       eval("6*7"); // will emit the "eval" event before code execution
258 |       
259 | 3. Protect your object method for being overridden. It is especially 
260 |    important in case of custom modules.
261 |    Example:
262 |       var secure = require("node-secure");
263 |       secure.secureMethods(exports); // protects all methods from current module
264 |       secure.securePrivates(myObj); // makes all properties starting from "_" non-enumerable
265 |       
266 | 4. Protect standard JavaScript methods from being overridden.  
267 |    Example:
268 |       var secure = require("node-secure");
269 |       secure.secureStandardMethods();
270 | 
271 | 272 | 273 | 274 |
275 | 
276 | API
277 |      SecurityError(msg, problems)            : constructor
278 |      secureStandardMethods(problemHandler)   : function
279 |      secureMethods(obj, config, callback)    : function
280 |      securePrivates(obj, config, callback)   : function
281 |      on(callback)                            : function
282 |      once(callback)                          : function
283 |      removeListener(callback)                : function
284 |      isSecure()                              : function
285 |      status                                  : object
286 |      eval                                    : event
287 |      insecure                                : event
288 |      
289 | 
290 | 291 | 292 |

293 | This version is under development.
294 | Latest stable version is 0.2.0
295 | Use GIT tags for it or npm: npm install node-secure
296 | 297 | Public domain
298 | You use this software at your own risk. 299 |

300 |
301 | 302 |
Author:
303 |
David de Rosier
304 | 305 | 306 |
Version:
307 |
0.3.0alpha
308 | 309 | 310 | 311 |
312 |
313 |
314 | 315 | 316 |
317 |
318 | 319 | Documentation generated by JsDoc Toolkit 2.4.0 on Thu Jul 21 2011 10:53:52 GMT+0100 (BST) 320 |
321 | 322 | -------------------------------------------------------------------------------- /doc/index.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | JsDoc Reference - Index 8 | 9 | 10 | 174 | 175 | 176 | 177 | 179 | 180 |
181 |
Class Index 182 | | File Index
183 |
184 |

Classes

185 | 196 |
197 |
198 | 199 |
200 |

Class Index

201 | 202 | 203 |
204 |

_global_

205 | 206 |
207 |
208 | 209 |
210 |

Error

211 | 212 |
213 |
214 | 215 |
216 |

secure

217 | Namespace containing all elements of the module 218 |
219 |
220 | 221 |
222 |

secure.SecurityError

223 | 224 |
225 |
226 | 227 | 228 |
229 |
230 | 231 | Documentation generated by JsDoc Toolkit 2.4.0 on Thu Jul 21 2011 10:53:52 GMT+0100 (BST) 232 |
233 | 234 | -------------------------------------------------------------------------------- /doc/symbols/.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | JsDoc Reference - <module> 9 | 10 | 174 | 175 | 176 | 177 | 178 | 179 | 181 | 182 | 183 | 184 |
185 | 186 |
Class Index 187 | | File Index
188 |
189 |

Classes

190 | 201 |
202 | 203 |
204 | 205 |
206 | 207 |

208 | 209 | Namespace 210 |

211 | 212 | 213 |

214 | 215 | 216 | 217 | 218 | 219 | 220 |
Defined in: node-secure.js. 221 | 222 |

223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 243 | 244 | 245 |
Namespace Summary
Constructor AttributesConstructor Name and Description
  238 |
239 | 240 |
241 |
242 |
246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 270 | 271 | 272 | 273 |
Field Summary
Field AttributesField Name and Description
<static>   265 |
266 | ..status 267 |
268 |
Statuses of protection level.
269 |
274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 |
287 |
288 | Namespace Detail 289 |
290 | 291 |
292 | 293 |
294 | 295 |
296 | 297 | 298 |
299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 |
312 | 313 | 314 | 315 | 316 |
317 | Field Detail 318 |
319 | 320 | 321 |
<static> 322 | 323 | {Object} 324 | .status 325 | 326 |
327 |
328 | Statuses of protection level. The variable specifies 329 | which feature become protected after module load. 330 | 331 | 332 |
333 | 334 | 335 | 336 |
require('node-secure').status.NAN_VALUE
337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 |
356 |
357 | 358 | 359 | 360 |
361 | 362 | Documentation generated by JsDoc Toolkit 2.4.0 on Thu Jul 21 2011 10:12:22 GMT+0100 (BST) 363 |
364 | 365 | 366 | -------------------------------------------------------------------------------- /doc/symbols/Error.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | JsDoc Reference - Error 9 | 10 | 174 | 175 | 176 | 177 | 178 | 179 | 181 | 182 | 183 | 184 |
185 | 186 |
Class Index 187 | | File Index
188 |
189 |

Classes

190 | 201 |
202 | 203 |
204 | 205 |
206 | 207 |

208 | 209 | Built-In Namespace Error 210 |

211 | 212 | 213 |

214 | 215 | 216 | 217 | 218 | 219 | 220 |

221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 |
246 |
247 | 248 | 249 | 250 |
251 | 252 | Documentation generated by JsDoc Toolkit 2.4.0 on Thu Jul 21 2011 10:53:52 GMT+0100 (BST) 253 |
254 | 255 | 256 | -------------------------------------------------------------------------------- /doc/symbols/SecurityError.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | JsDoc Reference - SecurityError 9 | 10 | 174 | 175 | 176 | 177 | 178 | 179 | 181 | 182 | 183 | 184 |
185 | 186 |
Class Index 187 | | File Index
188 |
189 |

Classes

190 | 201 |
202 | 203 |
204 | 205 |
206 | 207 |

208 | 209 | Class SecurityError 210 |

211 | 212 | 213 |

214 | 215 |
Extends 216 | Error.
217 | 218 | 219 | 220 | 221 | 222 |
Defined in: node-secure.js. 223 | 224 |

225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 245 | 246 | 247 |
Class Summary
Constructor AttributesConstructor Name and Description
  240 |
241 | SecurityError(msg, problems) 242 |
243 |
Error object constructor dedicated to security issues.
244 |
248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 |
261 |
262 | Class Detail 263 |
264 | 265 |
266 | SecurityError(msg, problems) 267 |
268 | 269 |
270 | Error object constructor dedicated to security issues. 271 | 272 |
273 | 274 | 275 | 276 | 277 | 278 |
279 |
Parameters:
280 | 281 |
282 | {string} msg 283 | 284 |
285 |
error message
286 | 287 |
288 | {Array} problems 289 | Optional 290 |
291 |
an array of problems
292 | 293 |
294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 |
303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 |
315 |
316 | 317 | 318 | 319 |
320 | 321 | Documentation generated by JsDoc Toolkit 2.4.0 on Thu Jul 21 2011 10:13:53 GMT+0100 (BST) 322 |
323 | 324 | 325 | -------------------------------------------------------------------------------- /doc/symbols/_global_.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | JsDoc Reference - _global_ 9 | 10 | 174 | 175 | 176 | 177 | 178 | 179 | 181 | 182 | 183 | 184 |
185 | 186 |
Class Index 187 | | File Index
188 |
189 |

Classes

190 | 201 |
202 | 203 |
204 | 205 |
206 | 207 |

208 | 209 | Built-In Namespace _global_ 210 |

211 | 212 | 213 |

214 | 215 | 216 | 217 | 218 | 219 | 220 |

221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 |
246 |
247 | 248 | 249 | 250 |
251 | 252 | Documentation generated by JsDoc Toolkit 2.4.0 on Thu Jul 21 2011 10:53:52 GMT+0100 (BST) 253 |
254 | 255 | 256 | -------------------------------------------------------------------------------- /doc/symbols/exports.SecurityError.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | JsDoc Reference - exports.SecurityError 9 | 10 | 174 | 175 | 176 | 177 | 178 | 179 | 181 | 182 | 183 | 184 |
185 | 186 |
Class Index 187 | | File Index
188 |
189 |

Classes

190 | 199 |
200 | 201 |
202 | 203 |
204 | 205 |

206 | 207 | Class exports.SecurityError 208 |

209 | 210 | 211 |

212 | 213 |
Extends 214 | Error.
215 | 216 | 217 | 218 | 219 | 220 |
Defined in: node-secure.js. 221 | 222 |

223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 243 | 244 | 245 |
Class Summary
Constructor AttributesConstructor Name and Description
  238 |
239 | exports.SecurityError(msg, problems) 240 |
241 |
Error object constructor dedicated to security issues.
242 |
246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 |
259 |
260 | Class Detail 261 |
262 | 263 |
264 | exports.SecurityError(msg, problems) 265 |
266 | 267 |
268 | Error object constructor dedicated to security issues. 269 | 270 |
271 | 272 | 273 | 274 | 275 | 276 |
277 |
Parameters:
278 | 279 |
280 | {string} msg 281 | 282 |
283 |
error message
284 | 285 |
286 | {Array} problems 287 | Optional 288 |
289 |
an array of problems
290 | 291 |
292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 |
301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 |
313 |
314 | 315 | 316 | 317 |
318 | 319 | Documentation generated by JsDoc Toolkit 2.4.0 on Thu Jul 21 2011 09:22:42 GMT+0100 (BST) 320 |
321 | 322 | 323 | -------------------------------------------------------------------------------- /doc/symbols/module.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | JsDoc Reference - module 9 | 10 | 174 | 175 | 176 | 177 | 178 | 179 | 181 | 182 | 183 | 184 |
185 | 186 |
Class Index 187 | | File Index
188 |
189 |

Classes

190 | 201 |
202 | 203 |
204 | 205 |
206 | 207 |

208 | 209 | Namespace module 210 |

211 | 212 | 213 |

214 | 215 | 216 | 217 | 218 | 219 | 220 |
Defined in: node-secure.js. 221 | 222 |

223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 243 | 244 | 245 |
Namespace Summary
Constructor AttributesConstructor Name and Description
  238 |
239 | module 240 |
241 |
242 |
246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 270 | 271 | 272 | 273 |
Field Summary
Field AttributesField Name and Description
<static>   265 |
266 | module.status 267 |
268 |
Statuses of protection level.
269 |
274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 |
287 |
288 | Namespace Detail 289 |
290 | 291 |
292 | module 293 |
294 | 295 |
296 | 297 | 298 |
299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 |
312 | 313 | 314 | 315 | 316 |
317 | Field Detail 318 |
319 | 320 | 321 |
<static> 322 | 323 | {Object} 324 | module.status 325 | 326 |
327 |
328 | Statuses of protection level. The variable specifies 329 | which feature become protected after module load. 330 | 331 | 332 |
333 | 334 | 335 | 336 |
require('node-secure').status.NAN_VALUE
337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 |
356 |
357 | 358 | 359 | 360 |
361 | 362 | Documentation generated by JsDoc Toolkit 2.4.0 on Thu Jul 21 2011 10:13:52 GMT+0100 (BST) 363 |
364 | 365 | 366 | -------------------------------------------------------------------------------- /doc/symbols/nodeSecure.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | JsDoc Reference - nodeSecure 9 | 10 | 174 | 175 | 176 | 177 | 178 | 179 | 181 | 182 | 183 | 184 |
185 | 186 |
Class Index 187 | | File Index
188 |
189 |

Classes

190 | 201 |
202 | 203 |
204 | 205 |
206 | 207 |

208 | 209 | Namespace nodeSecure 210 |

211 | 212 | 213 |

214 | 215 | 216 | 217 | 218 | 219 | 220 |
Defined in: node-secure.js. 221 | 222 |

223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 243 | 244 | 245 |
Namespace Summary
Constructor AttributesConstructor Name and Description
  238 |
239 | nodeSecure 240 |
241 |
242 |
246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 270 | 271 | 272 | 273 |
Field Summary
Field AttributesField Name and Description
<static>   265 |
266 | nodeSecure.status 267 |
268 |
Statuses of protection level.
269 |
274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 |
287 |
288 | Namespace Detail 289 |
290 | 291 |
292 | nodeSecure 293 |
294 | 295 |
296 | 297 | 298 |
299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 |
312 | 313 | 314 | 315 | 316 |
317 | Field Detail 318 |
319 | 320 | 321 |
<static> 322 | 323 | {Object} 324 | nodeSecure.status 325 | 326 |
327 |
328 | Statuses of protection level. The variable specifies 329 | which feature become protected after module load. 330 | 331 | 332 |
333 | 334 | 335 | 336 |
require('node-secure').status.NAN_VALUE
337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 |
356 |
357 | 358 | 359 | 360 |
361 | 362 | Documentation generated by JsDoc Toolkit 2.4.0 on Thu Jul 21 2011 10:11:06 GMT+0100 (BST) 363 |
364 | 365 | 366 | -------------------------------------------------------------------------------- /doc/symbols/secure SecurityError.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | JsDoc Reference - secure SecurityError 9 | 10 | 174 | 175 | 176 | 177 | 178 | 179 | 181 | 182 | 183 | 184 |
185 | 186 |
Class Index 187 | | File Index
188 |
189 |

Classes

190 | 201 |
202 | 203 |
204 | 205 |
206 | 207 |

208 | 209 | Class secure SecurityError 210 |

211 | 212 | 213 |

214 | 215 |
Extends 216 | Error.
217 | 218 | 219 | 220 | 221 | 222 |
Defined in: node-secure.js. 223 | 224 |

225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 245 | 246 | 247 |
Class Summary
Constructor AttributesConstructor Name and Description
  240 |
241 | secure SecurityError(msg, problems) 242 |
243 |
Error object constructor dedicated to security issues.
244 |
248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 |
261 |
262 | Class Detail 263 |
264 | 265 |
266 | secure SecurityError(msg, problems) 267 |
268 | 269 |
270 | Error object constructor dedicated to security issues. 271 | 272 |
273 | 274 | 275 | 276 | 277 | 278 |
279 |
Parameters:
280 | 281 |
282 | {string} msg 283 | 284 |
285 |
error message
286 | 287 |
288 | {Array} problems 289 | Optional 290 |
291 |
an array of problems
292 | 293 |
294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 |
303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 |
315 |
316 | 317 | 318 | 319 |
320 | 321 | Documentation generated by JsDoc Toolkit 2.4.0 on Thu Jul 21 2011 10:29:04 GMT+0100 (BST) 322 |
323 | 324 | 325 | -------------------------------------------------------------------------------- /doc/symbols/secure.SecurityError.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | JsDoc Reference - secure.SecurityError 9 | 10 | 174 | 175 | 176 | 177 | 178 | 179 | 181 | 182 | 183 | 184 |
185 | 186 |
Class Index 187 | | File Index
188 |
189 |

Classes

190 | 201 |
202 | 203 |
204 | 205 |
206 | 207 |

208 | 209 | Class secure.SecurityError 210 |

211 | 212 | 213 |

214 | 215 |
Extends 216 | Error.
217 | 218 | 219 | 220 | 221 | 222 |
Defined in: node-secure.js. 223 | 224 |

225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 245 | 246 | 247 |
Class Summary
Constructor AttributesConstructor Name and Description
  240 |
241 | secure.SecurityError(msg, problems) 242 |
243 |
Error object constructor dedicated to security issues.
244 |
248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 |
261 |
262 | Class Detail 263 |
264 | 265 |
266 | secure.SecurityError(msg, problems) 267 |
268 | 269 |
270 | Error object constructor dedicated to security issues. 271 | 272 |
273 | 274 | 275 | 276 | 277 | 278 |
279 |
Parameters:
280 | 281 |
282 | {string} msg 283 | 284 |
285 |
error message
286 | 287 |
288 | {Array} problems 289 | Optional 290 |
291 |
an array of problems
292 | 293 |
294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 |
303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 |
315 |
316 | 317 | 318 | 319 |
320 | 321 | Documentation generated by JsDoc Toolkit 2.4.0 on Thu Jul 21 2011 10:53:52 GMT+0100 (BST) 322 |
323 | 324 | 325 | -------------------------------------------------------------------------------- /doc/symbols/secure.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | JsDoc Reference - secure 9 | 10 | 174 | 175 | 176 | 177 | 178 | 179 | 181 | 182 | 183 | 184 |
185 | 186 |
Class Index 187 | | File Index
188 |
189 |

Classes

190 | 201 |
202 | 203 |
204 | 205 |
206 | 207 |

208 | 209 | Namespace secure 210 |

211 | 212 | 213 |

214 | 215 | 216 | 217 | Namespace containing all elements of the module 218 | 219 | 220 |
Defined in: node-secure.js. 221 | 222 |

223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 244 | 245 | 246 |
Namespace Summary
Constructor AttributesConstructor Name and Description
  238 |
239 | secure 240 |
241 |
This namespace contains all elements provided through exports 242 | variable.
243 |
247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 271 | 272 | 273 | 274 |
Field Summary
Field AttributesField Name and Description
<static>   266 |
267 | secure.status 268 |
269 |
Statuses of protection level.
270 |
275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 301 | 302 | 303 | 304 | 305 | 310 | 311 | 312 | 313 | 314 | 320 | 321 | 322 | 323 | 324 | 330 | 331 | 332 | 333 |
Method Summary
Method AttributesMethod Name and Description
<static>   297 |
secure.isSecure() 298 |
299 |
Checks the status of the global variables protection
300 |
<static>   306 |
secure.secureMethods(obj, config, errorCallback) 307 |
308 |
Makes all methods of given object non-writable.
309 |
<static>   315 |
secure.securePrivates(obj, config, errorCallback) 316 |
317 |
Marks all private-like members (starting from _ or __ prefix) as not enumerable 318 | Additional protection can be added (read-only, configurability)
319 |
<static>   325 |
secure.secureStandardMethods(problemHandler) 326 |
327 |

328 | Protects methods of standard JavaScript objects from being overridden.

329 |
334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 |
344 |
345 | Namespace Detail 346 |
347 | 348 |
349 | secure 350 |
351 | 352 |
353 | This namespace contains all elements provided through exports 354 | variable. Namespace name need to be defined by developer as a 355 | result of require function. By convention is suggested to use 356 | the name 'secure'.
357 | See the file description 358 | 359 |
360 | 361 | 362 | 363 |
var secure = require('node-secure');
364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 |
377 | 378 | 379 | 380 | 381 |
382 | Field Detail 383 |
384 | 385 | 386 |
<static> 387 | 388 | {Object} 389 | secure.status 390 | 391 |
392 |
393 | Statuses of protection level. The variable specifies 394 | which feature become protected after module load. 395 | 396 | 397 |
398 | 399 | 400 | 401 |
require('node-secure').status.NAN_VALUE
402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 |
417 | Method Detail 418 |
419 | 420 | 421 |
<static> 422 | 423 | {boolean} 424 | secure.isSecure() 425 | 426 |
427 |
428 | Checks the status of the global variables protection 429 | 430 | 431 |
432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 |
441 |
Returns:
442 | 443 |
{boolean} true if the module managed to protect all globals, false otherwise
444 | 445 |
446 | 447 | 448 | 449 | 450 |
451 | 452 | 453 |
<static> 454 | 455 | {object} 456 | secure.secureMethods(obj, config, errorCallback) 457 | 458 |
459 |
460 | Makes all methods of given object non-writable. Additional protection can be provided 461 | with second attribute. 462 | 463 | 464 |
465 | 466 | 467 | 468 | 469 |
470 |
Parameters:
471 | 472 |
473 | {Object} obj 474 | 475 |
476 |
an object
477 | 478 |
479 | {Object} config 480 | 481 |
482 |
a configuration object. Can take enumerable and configurable 483 | parameters. By default both of them are set to true
484 | 485 |
486 | {function} errorCallback 487 | Optional 488 |
489 |
a function which will be invoked when error occurs
490 | 491 |
492 | 493 | 494 | 495 | 496 |
497 |
Throws:
498 | 499 |
500 | {TypeError} 501 |
502 |
when obj parameter is not an object
503 | 504 |
505 | 506 | 507 |
508 |
Returns:
509 | 510 |
{object} object from input arguments (obj)
511 | 512 |
513 | 514 | 515 | 516 | 517 |
518 | 519 | 520 |
<static> 521 | 522 | {Object} 523 | secure.securePrivates(obj, config, errorCallback) 524 | 525 |
526 |
527 | Marks all private-like members (starting from _ or __ prefix) as not enumerable 528 | Additional protection can be added (read-only, configurability) 529 | 530 | 531 |
532 | 533 | 534 | 535 | 536 |
537 |
Parameters:
538 | 539 |
540 | {Object} obj 541 | 542 |
543 |
an object to protect
544 | 545 |
546 | {Object} config 547 | Optional 548 |
549 |
a configuration object
550 | 551 |
552 | {function} errorCallback 553 | Optional 554 |
555 |
callback executed when protection of some 556 | private members will fail
557 | 558 |
559 | 560 | 561 | 562 | 563 |
564 |
Throws:
565 | 566 |
567 | {TypeError} 568 |
569 |
when obj parameter is not an object
570 | 571 |
572 | 573 | 574 |
575 |
Returns:
576 | 577 |
{Object} object from input arguments (obj)
578 | 579 |
580 | 581 | 582 | 583 | 584 |
585 | 586 | 587 |
<static> 588 | 589 | 590 | secure.secureStandardMethods(problemHandler) 591 | 592 |
593 |
594 |

595 | Protects methods of standard JavaScript objects from being overridden. 596 | The optional parameter of the method defines how to handle situations when 597 | function recognize some issues (ie. already overridden method). Three options 598 | available here: 599 | a) function run without input attribute - "insecure" event will be emitted 600 | b) function run with boolean attribute true - SecurityError will be thrown. 601 | c) function run with function as an attribute - the callback will be invoked. 602 | In all three cases an array of problems will be passed as an attribute. 603 |

604 | Function returns the module object which means it can be invoked directly 605 | after require, without overlapping the module context (see example). 606 |

607 | Function does not break when internal error happen. It tries to protect as 608 | many standard methods as possible. Finally it produces the list of problems. 609 |

610 | Function executes only once. After that it replaces itself with an empty 611 | function to avoid situation when multiple attempts of standard object 612 | protection happen. It also means that after first execution the function 613 | releases its resources. 614 |

615 | 616 | 617 |
618 | 619 | 620 | 621 |
  var secure = require("node-secure").secureStandardMethods(
622 | 	      function(problems){
623 |        console.log("Can't continue due to security threats");
624 |        console.log(problems);
625 |        process.exit(1); 			   
626 |      });
627 | 628 | 629 | 630 | 631 |
632 |
Parameters:
633 | 634 |
635 | {boolean|function} problemHandler 636 | Optional 637 |
638 |
boolean or a function
639 | 640 |
641 | 642 | 643 | 644 | 645 |
646 |
Throws:
647 | 648 |
649 | {SecurityError} 650 |
651 |
when problems found and function invoked with 652 | boolean argument set to true
653 | 654 |
655 | 656 | 657 |
658 |
Returns:
659 | 660 |
module object
661 | 662 |
663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 |
675 |
676 | 677 | 678 | 679 |
680 | 681 | Documentation generated by JsDoc Toolkit 2.4.0 on Thu Jul 21 2011 10:53:52 GMT+0100 (BST) 682 |
683 | 684 | 685 | -------------------------------------------------------------------------------- /js/node-secure.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @fileOverview 3 | *

4 | * This simple module allows to protect the code using ECMAScript 5 features, 5 | * even when strict mode is not available. 6 | *

7 | * First it makes all global constants (undefined, NaN, Infinity) non-writable. 8 | * and non-configurable. 9 | * How important it is you can check by running basic example: 10 | * - override undefined with real value 11 | * - run http server and make request 12 | * Due to unprotected comparisons to undefined value in http module, the entire 13 | * server will fail with TypeError (tested on node.js 0.4.8) 14 | * Such basic code can be intentionally injected to a server by a hacker 15 | * or created by mistake by unexperienced developer. 16 | *

17 | * Secondly - the module allows you to protect your own code from 18 | * intentional/unintentional overriding. The main element which you should 19 | * protect are your methods. In most of the cases your code won't work properly 20 | * if your methods will be overridden. 21 | * Other important thing is to hide private-like members from being enumerable. 22 | * Especially when they are not physically private (i.e by usage of closures), 23 | * but marked as private with naming convention (using single or double 24 | * underscore prefix). 25 | *

26 | * Third thing is to control execution of eval function - which brings the bigger 27 | * risk of potential attacks (execution of injected code fragments). Theoretically 28 | * there is possible to override eval (i.e. with empty function), however it can 29 | * break other modules which operate on eval function. This module extends eval 30 | * with notification mechanism - every time when someone execute eval your program 31 | * will be notified about it with "eval" event. The event takes reference to 32 | * executor function. 33 | *

34 | * The dynamic nature of JavaScript gives to developer a freedom of quick 35 | * and smart programming. However server-side code should be protected as much 36 | * as possible from code injections and hacking. The visibility of code and 37 | * easy code inspection mechanism often can leave open doors for bad 38 | * intensions and code replacements. 39 | *

40 | * 41 | * 42 | *
 43 |  * USAGE
 44 |  * 
 45 |  * 1. Just load the module to protect global statics (undefined, NaN, Infinity)
 46 |  *    example: require('node-secure');
 47 |  *    
 48 |  * 2. Just load the module to control execution of eval (evil?) function.
 49 |  *    With this module eval will work as previously, but every time someone
 50 |  *    execute it, you will get an event notification
 51 |  *    Example: 
 52 |  *       var secure = require("node-secure");
 53 |  *       secure.on("eval", function(f){"Evaluation executed in function "+f.name});
 54 |  *       eval("6*7"); // will emit the "eval" event before code execution
 55 |  *       
 56 |  * 3. Protect your object method for being overridden. It is especially 
 57 |  *    important in case of custom modules.
 58 |  *    Example:
 59 |  *       var secure = require("node-secure");
 60 |  *       secure.secureMethods(exports); // protects all methods from current module
 61 |  *       secure.securePrivates(myObj); // makes all properties starting from "_" non-enumerable
 62 |  *       
 63 |  * 4. Protect standard JavaScript methods from being overridden.  
 64 |  *    Example:
 65 |  *       var secure = require("node-secure");
 66 |  *       secure.secureStandardMethods();
 67 |  * 
68 | * 69 | * 70 | * 71 | *
 72 |  * 
 73 |  * API
 74 |  *      SecurityError(msg, problems)            : constructor
 75 |  *      secureStandardMethods(problemHandler)   : function
 76 |  *      secureMethods(obj, config, callback)    : function
 77 |  *      securePrivates(obj, config, callback)   : function
 78 |  *      on(callback)                            : function
 79 |  *      once(callback)                          : function
 80 |  *      removeListener(callback)                : function
 81 |  *      isSecure()                              : function
 82 |  *      status                                  : object
 83 |  *      eval                                    : event
 84 |  *      insecure                                : event
 85 |  *      
 86 |  * 
87 | * 88 | * 89 | *

90 | * This version is under development.
91 | * Latest stable version is 0.2.0
92 | * Use GIT tags for it or npm: npm install node-secure
93 | * 94 | * Public domain
95 | * You use this software at your own risk. 96 | *

97 | * 98 | * @author David de Rosier 99 | * @version 0.3.0alpha 100 | * @source https://github.com/ddrcode/node-secure 101 | * 102 | */ 103 | 104 | 105 | // required modules 106 | var EventEmitter = require("events").EventEmitter, 107 | util = require("util") 108 | ; 109 | 110 | 111 | /** 112 | * This namespace contains all elements provided through exports 113 | * variable. Namespace name need to be defined by developer as a 114 | * result of require function. By convention is suggested to use 115 | * the name 'secure'.
116 | * See the file description 117 | * @example var secure = require('node-secure'); 118 | * @name secure 119 | * @namespace Namespace containing all elements of the module 120 | */ 121 | var nodeSecure = exports; 122 | 123 | 124 | 125 | /** 126 | * Specifies which feature become protected after module load 127 | * Values available through 'status' property of the module 128 | * @exports __status as status 129 | * @private 130 | * @example require('node-secure').status.NAN_VALUE 131 | */ 132 | var __status = { 133 | EVAL: false, 134 | UNDEFINED_VALUE: false, 135 | UNDEFINED_PROTECTION: false, 136 | NAN_VALUE: false, 137 | NAN_PROTECTION: false, 138 | INFINITY_VALUE: false, 139 | INFINITY_PROTECTION: false, 140 | ISNAN_VALUE: false, 141 | ISNAN_PROTECTION: false 142 | }; 143 | 144 | 145 | 146 | /** 147 | * Tests whether the input parameter is a function. Additional test is required because 148 | * V8 returns "function" as a result of typeof operator also for RegExps. 149 | * @returns {boolean} 150 | * @private 151 | */ 152 | var __isFunction = function(test){ 153 | return typeof test === "function" && test.call && test.apply && test.bind; 154 | }; 155 | 156 | 157 | 158 | /** 159 | * The code snippet below protects JavaScript globals from being overridden. 160 | * It also reverts original values if they already got changed. 161 | * To start the protection just load the module to a project. 162 | * @example require('node-secure'); 163 | */ 164 | (function(){ 165 | 166 | // global object in non-strict mode 167 | // (to avoid potentially overridden global variable of node.js) 168 | var global = (function(){ return this; })(); 169 | 170 | // if strict mode is on - globals are protected by default 171 | if( !global ) { 172 | return; 173 | } 174 | 175 | // proper values of globals 176 | var values = { 177 | undefined: void 0, 178 | Infinity: 1/0, 179 | NaN: +"!" 180 | }; 181 | 182 | // restore values and protect them 183 | Object.keys(values).forEach(function(e){ 184 | try { 185 | Object.defineProperty(global,e,{ writable: false, enumerable: false, configurable: false, value: values[e] }); 186 | } catch(ex) { 187 | // nothing to do 188 | } finally { 189 | var dsc = Object.getOwnPropertyDescriptor(global, e); 190 | __status[e.toUpperCase()+"_PROTECTION"] = !dsc.writable && !dsc.configurable; 191 | __status[e.toUpperCase()+"_VALUE"] = e!=="NaN" ? dsc.value===values[e] : String(dsc.value)==="NaN" && typeof dsc.value === "number"; 192 | } 193 | }); 194 | 195 | // restore isNaN function if overridden 196 | var __isNaN = null; 197 | try { 198 | if( !__isFunction(global.isNaN) || global.isNaN(values.NaN) !== true || global.isNaN(5) !== false ) { 199 | __isNaN = global.isNaN = function(n) { 200 | return String(+n) === "NaN"; 201 | }; 202 | } 203 | Object.defineProperty(global, "isNaN", { writable: false, enumerable: false, configurable: false }); 204 | } catch(ez) { 205 | // nothing to do 206 | } finally { 207 | dsc = Object.getOwnPropertyDescriptor(global, "isNaN"); 208 | __status.ISNAN_PROTECTION = !dsc.writable && !dsc.configurable; 209 | __status.ISNAN_VALUE = __isNaN 210 | ? global.isNaN === __isNaN 211 | : __isFunction(global.isNaN) || global.isNaN(values.NaN) === true || global.isNaN(5) === false; 212 | } 213 | 214 | })(); 215 | 216 | 217 | 218 | /** 219 | * Local instance of EventEmitter 220 | * @private 221 | */ 222 | var __eventEmitter = (function(){ 223 | 224 | var Constr = function(){ 225 | EventEmitter.call(this); 226 | }; 227 | 228 | util.inherits(Constr, EventEmitter); 229 | 230 | return new Constr(); 231 | })(); 232 | 233 | 234 | 235 | /** 236 | * Error object constructor dedicated to security issues. 237 | * @name secure.SecurityError 238 | * @constructor 239 | * @extends Error 240 | * @param {string} msg error message 241 | * @param {Array} [problems] an array of problems 242 | */ 243 | exports.SecurityError = SecurityError = (function(){ 244 | var SecurityError = function(msg, problems) { 245 | Error.call(this, msg); 246 | this.message = msg; 247 | this.problems = problems; 248 | }; 249 | SecurityError.prototype = Object.create( Error.prototype ); 250 | SecurityError.prototype.name = "SecurityError"; 251 | SecurityError.prototype.constructor = SecurityError; 252 | return SecurityError; 253 | })(); 254 | 255 | 256 | 257 | /** 258 | * This code snippet overrides the original eval function for better control 259 | * of unexpected execution. Every time the eval function will be called 260 | * the application will emit "eval" event, passing the code for execution 261 | * as an argument. 262 | * 263 | * @example 264 | * var secure = require("node-secure"); 265 | * secure.on("eval", function(code){"Evaluation executed: "+code}); 266 | * eval("6*7); // will emit the "eval" event before code execution 267 | * 268 | */ 269 | (function(){ 270 | var evalDsc = Object.getOwnPropertyDescriptor(global,"eval"); 271 | if( evalDsc.configurable && evalDsc.writable ) { 272 | var __eval = global.eval, 273 | __canEmit = false; 274 | 275 | Object.defineProperty(global, "eval", { 276 | get: function(){ 277 | (__canEmit = !__canEmit) && __eventEmitter.emit("eval", arguments.callee.caller); 278 | return __eval; 279 | }, 280 | configurable: false 281 | }); 282 | 283 | __status.EVAL = true; 284 | } 285 | })(); 286 | 287 | 288 | 289 | /** 290 | *

291 | * Protects methods of standard JavaScript objects from being overridden. 292 | * The optional parameter of the method defines how to handle situations when 293 | * function recognize some issues (ie. already overridden method). Three options 294 | * available here: 295 | * a) function run without input attribute - "insecure" event will be emitted 296 | * b) function run with boolean attribute true - SecurityError will be thrown. 297 | * c) function run with function as an attribute - the callback will be invoked. 298 | * In all three cases an array of problems will be passed as an attribute. 299 | *

300 | * Function returns the module object which means it can be invoked directly 301 | * after require, without overlapping the module context (see example). 302 | *

303 | * Function does not break when internal error happen. It tries to protect as 304 | * many standard methods as possible. Finally it produces the list of problems. 305 | *

306 | * Function executes only once. After that it replaces itself with an empty 307 | * function to avoid situation when multiple attempts of standard object 308 | * protection happen. It also means that after first execution the function 309 | * releases its resources. 310 | *

311 | * 312 | * @name secure.secureStandardMethods 313 | * @function 314 | * @param {boolean|function} [problemHandler] boolean or a function 315 | * @returns module object 316 | * @throws {SecurityError} when problems found and function invoked with 317 | * boolean argument set to true 318 | * @example 319 | * var secure = require("node-secure").secureStandardMethods( 320 | * function(problems){ 321 | * console.log("Can't continue due to security threats"); 322 | * console.log(problems); 323 | * process.exit(1); 324 | * }); 325 | */ 326 | exports.secureStandardMethods = (function(prototypes, objects){ 327 | 328 | 329 | /** 330 | * Array of issues found during standard method protection. 331 | * The object is extended with one custom method: add. 332 | * @private 333 | * @type {Array} 334 | */ 335 | var __problems = (function(){ 336 | var arr = []; 337 | arr.add = function(key, desc){ 338 | arr.push( "Problem in "+key+". "+desc ); 339 | }; 340 | return arr; 341 | })(); 342 | 343 | 344 | /** 345 | * Function iterates through an map of object and method names 346 | * trying to change their property descriptors to 347 | * {writable: false, configurable: false}. 348 | * @private 349 | * @param {Object} elems a map of object and method names 350 | */ 351 | var __iterator = function(elems){ 352 | var proto = elems===prototypes; 353 | Object.keys(elems).forEach(function(p){ 354 | 355 | proto && elems[p].push('constructor'); 356 | 357 | elems[p].forEach(function(f){ 358 | try { 359 | var obj = proto ? global[p].prototype : global[p], 360 | dsc = Object.getOwnPropertyDescriptor(obj, f), 361 | key = (proto ? p+".prototype" : p) + "." + f, 362 | problem = true, error = false; 363 | 364 | if( !dsc ) { 365 | __problems.add( key, "Method does not exist" ); 366 | } else if( !dsc.writable || !dsc.configurable ) { 367 | __problems.add( key, "Method already protected" ); 368 | } else if( !__isFunction(obj[f]) ) { 369 | __problems.add( key, "Method is not a function" ); 370 | } else { 371 | problem = false; 372 | Object.defineProperty(obj, f, {writable: false, configurable: false}); 373 | } 374 | 375 | } catch(ex) { 376 | error = true; 377 | } finally { 378 | if( !problem && !error ) { 379 | dsc = Object.getOwnPropertyDescriptor(obj, f); 380 | } 381 | if( !problem && (error || dsc.writable || dsc.configurable) ){ 382 | __problems.add( key, "Method couldn't be protected for unknown reason" ); 383 | } 384 | } 385 | }); 386 | }); 387 | }; 388 | 389 | 390 | /** 391 | * Real implementation of secureStandardMethods function. 392 | * Moved to internal/private function to let it to be internally 393 | * overridden. Public function won't be able to override itself 394 | * because is protected. 395 | * @private 396 | */ 397 | var __secureStandardMethods = function(problemHandler){ 398 | 399 | if( arguments.length > 0 && typeof problemHandler !== "boolean" && !__isFunction(problemHandler) ) { 400 | throw new TypeError( "problemHandler must be either boolean or a function" ); 401 | } 402 | 403 | __iterator(prototypes); 404 | __iterator(objects); 405 | 406 | if( __problems.length > 0 ) { 407 | var problems = Object.freeze( __problems.slice() ); 408 | if( typeof problemHandler === "boolean" ) { 409 | throw new SecurityError( "Securing standard ECMAScript methods failed. See problems property for details.", problems ); 410 | } else if( __isFunction(problemHandler) ) { 411 | problemHandler( problems ); 412 | } else { 413 | __eventEmitter.emit( "insecure", problems ); 414 | } 415 | } 416 | 417 | // override itself after first execution 418 | __problems = prototypes = objects = __iterator = null; 419 | /** @ignore */ __secureStandardMethods = function(){ 420 | return nodeSecure; 421 | }; 422 | 423 | return nodeSecure; 424 | }; 425 | 426 | 427 | return function(){ 428 | return __secureStandardMethods.apply(nodeSecure, arguments); 429 | }; 430 | 431 | })({ 432 | 'Object': ['toString', 'toLocaleString', 'valueOf', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable'], 433 | 'Array': ['toString','toLocaleString','concat','join','pop','push','reverse','shift','slice','sort','splice','unshift', 434 | 'indexOf','lastIndexOf','every','some','forEach','filter','map','reduce','reduceRight'], 435 | 'Function': ['call','apply','bind','toString'], 436 | 'Number': ['toString','toLocaleString','valueOf','toFixed','toExponential','toPrecision'], 437 | 'Boolean': ['toString','valueOf'], 438 | 'String': ['trim','toString','valueOf','charAt','charCodeAt','concat','indexOf','lastIndexOf',/*'localCompare',*/ 439 | 'match','replace','search','slice','split','substring','toLowerCase','toLocaleLowerCase','toUpperCase','toLocaleUpperCase'], 440 | 'Date': ['toUTCString', 'setMinutes', 'setUTCMonth', 'getMilliseconds', 'getTime', 'getMinutes', 'getUTCHours', 441 | 'toString', 'setUTCFullYear', 'setMonth', 'getUTCMinutes', 'getUTCDate', 'setSeconds', 'toLocaleDateString', 'getMonth', 442 | 'toTimeString', 'toLocaleTimeString', 'setUTCMilliseconds', 'setYear', 'getUTCFullYear', 'getFullYear', 'getTimezoneOffset', 443 | 'setDate', 'getUTCMonth', 'getHours', 'toLocaleString', 'toISOString', 'toDateString', 'getUTCSeconds', 'valueOf', 444 | 'setUTCMinutes', 'getUTCDay', 'toJSON', 'setUTCDate', 'setUTCSeconds', 'getYear', 'getUTCMilliseconds', 'getDay', 445 | 'setFullYear', 'setMilliseconds', 'setTime', 'setHours', 'getSeconds', 'toGMTString', 'getDate', 'setUTCHours'], 446 | 'RegExp': ['toString', 'exec', 'compile', 'test'], 447 | 'Error': ['toString'] 448 | },{ 449 | 'JSON': ['parse', 'stringify'], 450 | 'Object': ['keys','getPrototypeOf','create','preventExtensions','seal','freeze','isSealed','isFrozen', 451 | 'isExtensible', 'defineProperty', 'defineProperties', 'getOwnPropertyDescriptor', 'getOwnPropertyNames'], 452 | 'Array': ['isArray'], 453 | 'String': ['fromCharCode'], 454 | 'Date': ['now','UTC','parse'], 455 | 'Math': ['abs','acos','asin','atan','atan2','ceil', 456 | 'cos','exp','floor','log','max','min','pow','random','round','sin','sqrt','tan'] 457 | } 458 | ); // end of exports.secureStandardMethods factory 459 | 460 | 461 | 462 | // builder of secureMethods and securePrivates methods 463 | (function(){ 464 | 465 | /** 466 | * @private 467 | * @throws TypeError 468 | */ 469 | var __secure = function(obj, config, errorCallback, protectedAttribute, test){ 470 | if( typeof obj !== 'object' || obj === null ) { 471 | throw new TypeError( "Obj is not an object" ); 472 | } 473 | 474 | // case when callback is a second parameter (config not provided) 475 | if( __isFunction(config) && !errorCallback ) { 476 | errorCallback = config; 477 | config = null; 478 | } 479 | 480 | config = config || {}; 481 | if( typeof config !== "object" ) { 482 | throw new TypeError( "config is not an object" ); 483 | } 484 | 485 | if( errorCallback && !__isFunction(errorCallback) ) { 486 | throw new TypeError( "errorCallback is not a function" ); 487 | } 488 | 489 | var cfg = {}; 490 | cfg[protectedAttribute] = false; 491 | ["writable", "enumerable", "configurable"].forEach(function(key){ 492 | if( key !== protectedAttribute && key in config ) { 493 | cfg[key] = !!config[key]; 494 | } 495 | }); 496 | 497 | // array of errors 498 | var errors = []; 499 | 500 | for(var o in obj) { if(obj.hasOwnProperty(o)){ 501 | if( test(o) ) { 502 | try { 503 | Object.defineProperty( obj, o, cfg ); 504 | } catch(ex) { 505 | errors.push( { property: o, error: ex } ); 506 | } 507 | } 508 | }} 509 | 510 | // execute callback when errors 511 | errorCallback && errors.length > 0 && errorCallback( Object.freeze(errors) ); 512 | 513 | return obj; 514 | }; 515 | 516 | 517 | 518 | /** 519 | * Makes all methods of given object non-writable. Additional protection can be provided 520 | * with second attribute. 521 | * @name secure.secureMethods 522 | * @function 523 | * @param {Object} obj an object 524 | * @param {Object} config a configuration object. Can take enumerable and configurable 525 | * parameters. By default both of them are set to true 526 | * @param {function} [errorCallback] a function which will be invoked when error occurs 527 | * @returns {object} object from input arguments (obj) 528 | * @throws {TypeError} when obj parameter is not an object 529 | */ 530 | exports.secureMethods = function(obj, config, errorCallback) { 531 | 532 | return __secure(obj, config, errorCallback, "writable", function(key){ 533 | return __isFunction(obj[key]); 534 | }); 535 | 536 | }; 537 | 538 | 539 | 540 | /** 541 | * Marks all private-like members (starting from _ or __ prefix) as not enumerable 542 | * Additional protection can be added (read-only, configurability) 543 | * @name secure.securePrivates 544 | * @function 545 | * @param {Object} obj an object to protect 546 | * @param {Object} [config] a configuration object 547 | * @param {function} [errorCallback] callback executed when protection of some 548 | * private members will fail 549 | * @returns {Object} object from input arguments (obj) 550 | * @throws {TypeError} when obj parameter is not an object 551 | */ 552 | exports.securePrivates = function(obj, config, errorCallback) { 553 | 554 | return __secure(obj, config, errorCallback, "enumerable", function(key){ 555 | return key[0] === '_'; 556 | }); 557 | 558 | }; 559 | 560 | })(); 561 | 562 | 563 | 564 | /** 565 | * Event listener. Possible events: 566 | * - "eval" - emitted when eval function executed 567 | * - "insecure" - emitted when the module failed to protect at least one of globals 568 | * 569 | * @function 570 | * @param name {string} event name 571 | * @param callback {function} callback function 572 | * @example require("ddr-secure").on("eval", function(caller){ console.log("Eval executed in function: "+caller); }); 573 | */ 574 | ["on", "once", "removeListener"].forEach(function(mth){ 575 | exports[mth] = __eventEmitter[mth].bind(__eventEmitter); 576 | }); 577 | 578 | 579 | 580 | /** 581 | * Statuses of protection level. The variable specifies 582 | * which feature become protected after module load. 583 | * @name secure.status 584 | * @type Object 585 | * @example require('node-secure').status.NAN_VALUE 586 | * @frozen 587 | */ 588 | exports.status = Object.freeze(__status); 589 | 590 | 591 | 592 | /** 593 | * Checks the status of the global variables protection 594 | * @name secure.isSecure 595 | * @function 596 | * @return {boolean} true if the module managed to protect all globals, false otherwise 597 | */ 598 | exports.isSecure = function(){ 599 | return Object.keys(__status).every( function(s){ return __status[s]; } ); 600 | }; 601 | 602 | 603 | 604 | // Protects the module itself 605 | exports.secureMethods( exports, { enumerable: true, configurable: false } ); 606 | 607 | 608 | // notifies that some of globals are not secure. Event notification happen 609 | // as the nearest callback execution. If direct test is required 610 | // call manually isSecure() method directly after module load 611 | !exports.isSecure() && process.nextTick(function(){ 612 | var failures = Object.keys(__status).filter( function(s){ return !__status[s]; }); 613 | __eventEmitter.emit("insecure", failures); 614 | }); 615 | 616 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-secure", 3 | "version": "0.3.0alpha", 4 | "description": "Protects globals from being overridden and adds functionality to protect your modules from hacking and code injection", 5 | "keywords": ["security", "globals", "eval", "node.js"], 6 | "author": "David de Rosier ", 7 | "main": "js/node-secure.js", 8 | "engines": { "node": ">= 0.4.0" }, 9 | "repository": { "type":"git", "url":"https://github.com/ddrcode/node-secure" } 10 | } 11 | -------------------------------------------------------------------------------- /run-tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | txts=$(tput sgr0) 4 | txtb=$(tput bold)$(tput setaf 4) 5 | 6 | for file in node-secure-standard-test.js node-secure-overridden-test.js node-secure-events-test.js; do 7 | echo -e "\n${txtb}${file}${txts}" 8 | node test/$file 9 | done 10 | 11 | echo "" 12 | -------------------------------------------------------------------------------- /test/README: -------------------------------------------------------------------------------- 1 | This folder contains set of test cases for node-secure module. 2 | The tests had to be split into multiple files because they operate 3 | on global variables and permanently change their values and property 4 | descriptors. 5 | 6 | Available tests: 7 | 8 | TEST 1: node-secure-standard-test.js 9 | Checks the module with standard situation, when none of the globals 10 | has been overridden. 11 | 12 | TEST 2: node-secure-overridden-test.js 13 | Test with overridden global values. 14 | Globals are not originally protected here 15 | 16 | TEST 3: node-secure-events-test 17 | Overrides and protects some globals and standard functions than 18 | laods the module. The tests checks if 'insecure' event is fired 19 | automatically. 20 | -------------------------------------------------------------------------------- /test/node-secure-events-test.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Test whether the events are emit when some problems occur 3 | * during the code protection. 4 | * @author David de Rosier 5 | */ 6 | 7 | var assert = require("assert"); 8 | var test = require("./test-commons"); 9 | var secure = null; 10 | 11 | // Modifies some standard values before loading the node-secure module 12 | // The code protects the changes (configurable: false), so the module 13 | // won't be able to apply protection. An event should be emitted. 14 | (function(){ 15 | 16 | Object.defineProperty(global, "undefined", { 17 | value: 42, 18 | enumerable: false, 19 | configurable: false, 20 | writable: false 21 | }); 22 | 23 | Object.defineProperty(global, "isNaN", { 24 | value: function(){ return 2 }, 25 | configurable: false, 26 | enumerable: false, 27 | writable: false 28 | }); 29 | 30 | Object.defineProperty(Object.prototype, "toString", { 31 | writable: false, 32 | configurable: false 33 | }); 34 | 35 | Date.now = 123; 36 | 37 | })(); 38 | 39 | 40 | // tests 41 | (function(){ 42 | 43 | console.log( "Running test: events" ); 44 | 45 | try { 46 | secure = require("../js/node-secure"); 47 | 48 | var cnt = 0; 49 | secure.on( "insecure", function(problems){ 50 | ++cnt; 51 | assert.equal( problems.length, 2, "Two problems should be found" ) 52 | }); 53 | 54 | secure.secureStandardMethods(); 55 | 56 | process.on('exit', function(){ 57 | assert.equal( cnt, 2, "Event should be emitted two times" ); 58 | }); 59 | 60 | } catch(ex) { 61 | if( ex.name === "AssertionError" ) 62 | throw ex; 63 | assert.ok( false, "No error should happen" ); 64 | } 65 | 66 | })(); 67 | -------------------------------------------------------------------------------- /test/node-secure-overridden-test.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Test of the situation when all globals were originally overridden 3 | * with fake values, but their property descriptors aren't changed. 4 | * @author David de Rosier 5 | */ 6 | 7 | var assert = require("assert"); 8 | var test = require("./test-commons"); 9 | var secure = null; 10 | 11 | 12 | // override globals 13 | (function(){ 14 | undefined = 666; 15 | NaN = "this is not a number"; 16 | Infinity = /42/; 17 | isNaN = function(){ return "maybe" }; 18 | eval = function(){ return "eval is evil" }; 19 | })(); 20 | 21 | 22 | 23 | var tests = { 24 | 25 | "default values": function(){ 26 | assert.notEqual( undefined, void 0, "undefined" ); 27 | assert.notEqual( Infinity, 1/0, "infinity" ); 28 | assert.notEqual( String(NaN), "NaN", "NaN" ); 29 | assert.notEqual( isNaN(+"!"), true, "isNaN" ); 30 | assert.notEqual( eval("2+1"), 3, "eval" ); 31 | 32 | assert.notEqual( typeof undefined, "undefined", "typeof undefined" ); 33 | assert.notEqual( typeof Infinity, "number", "typeof Infinity" ); 34 | assert.notEqual( typeof NaN, "number", "typeof NaN" ); 35 | }, 36 | 37 | "node-secure module load": function(){ 38 | secure = test.standardTests.moduleLoad(); 39 | }, 40 | 41 | "secureStandardMethods": function(){ 42 | 43 | Array.prototype.reduceRight = 666; 44 | Object.defineProperty(Object.prototype, "toString", {configurable: false}); 45 | 46 | var callback = function(problems){ 47 | assert.ok( true, "callback method should be executed due to some problems" ); 48 | assert.equal(problems.length, 2, "Function should identify two issues"); 49 | }; 50 | 51 | secure.secureStandardMethods(callback); 52 | 53 | // problems shouldn't stop proetecting other methods 54 | var dsc = Object.getOwnPropertyDescriptor(Object.prototype, "valueOf"); 55 | assert.equal( dsc.writable, false ); 56 | assert.equal( dsc.configurable, false ); 57 | 58 | // tests if the function overrode itself. Second execution should throw error, because 59 | // all standard methods are already protected 60 | secure.secureStandardMethods(callback); 61 | } 62 | 63 | }; 64 | 65 | 66 | test.start(tests); 67 | 68 | 69 | -------------------------------------------------------------------------------- /test/node-secure-standard-test.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Test of standard situation. 3 | * No overridden globals, no property descriptor changes 4 | * @author David de Rosier 5 | */ 6 | 7 | var assert = require("assert"); 8 | var test = require("./test-commons"); 9 | var secure = null; 10 | 11 | var tests = { 12 | 13 | "default values": function(){ 14 | assert.equal( undefined, void 0, "undefined" ); 15 | assert.equal( Infinity, 1/0, "infinity" ); 16 | assert.equal( String(NaN), "NaN", "NaN" ); 17 | 18 | assert.equal( typeof undefined, "undefined", "typeof undefined" ); 19 | assert.equal( typeof Infinity, "number", "typeof Infinity" ); 20 | assert.equal( typeof NaN, "number", "typeof NaN" ); 21 | }, 22 | 23 | 24 | "default eval": function(){ 25 | var a = 5; 26 | var eq = eval("a+1"); 27 | assert.equal( eq, 6, 'eval("a+1")' ); 28 | }, 29 | 30 | 31 | "node-secure module load": function() { 32 | assert.doesNotThrow( function(){ 33 | secure = require("../js/node-secure"); 34 | }); 35 | 36 | this["default values"](); 37 | 38 | assert.equal( typeof secure.secureMethods, "function", "typeof secure.secureMethods" ); 39 | assert.equal( typeof secure.securePrivates, "function", "typeof secure.securePrivates" ); 40 | assert.equal( typeof secure.isSecure, "function", "typeof secure.isSecure" ); 41 | assert.equal( typeof secure.status, "object", "typeof secure.status" ); 42 | 43 | assert.ok( secure.status.EVAL, "status.EVAL" ); 44 | assert.ok( secure.status.UNDEFINED_VALUE, "status.UNDEFINED_VALUE" ); 45 | assert.ok( secure.status.UNDEFINED_PROTECTION, "status.UNDEFINED_PROTECTION" ); 46 | assert.ok( secure.status.NAN_VALUE, "status.NAN_VALUE" ); 47 | assert.ok( secure.status.NAN_PROTECTION, "status.NAN_PROTECTION" ); 48 | assert.ok( secure.status.INFINITY_VALUE, "status.INFINITY_VALUE" ); 49 | assert.ok( secure.status.INFINITY_PROTECTION, "status.INFINITY_PROTECTION" ); 50 | assert.ok( secure.status.ISNAN_VALUE, "status.ISNAN_VALUE" ); 51 | assert.ok( secure.status.ISNAN_PROTECTION, "status.ISNAN_PROTECTION" ); 52 | 53 | assert.equal( secure.isSecure(), true, "secure.isSecure()"); 54 | }, 55 | 56 | 57 | "property definitions of globals": function(){ 58 | ["undefined", "Infinity", "NaN", "isNaN", "eval"].forEach(function(a){ 59 | var def = Object.getOwnPropertyDescriptor(global, a); 60 | assert.equal( def.configurable, false, "'configurable' property of " + a ); 61 | a!=='eval' 62 | ? assert.equal( def.writable, false, "'writable' property of " + a ) 63 | : assert.equal( typeof def.set, 'undefined', "'writable' property of " ); 64 | }); 65 | }, 66 | 67 | 68 | "status": function() { 69 | assert.equal( Object.isFrozen(secure.status), true, "Object.isFrozen(secure.status)" ); 70 | }, 71 | 72 | 73 | "secure eval": function(){ 74 | var evalTest = this["default eval"]; 75 | secure.on("eval", function(caller){ 76 | assert.equal(caller, evalTest); 77 | }); 78 | this["default eval"](); 79 | }, 80 | 81 | 82 | "secureMethods": function(){ 83 | var callback = function(){ 84 | assert.ok( false, "callback method should not be executed" ); 85 | }; 86 | obj = { 87 | mth: function(){} 88 | }; 89 | secure.secureMethods(obj, {}, callback); 90 | }, 91 | 92 | 93 | "secureStandardMethods": function(){ 94 | var callback = function(){ 95 | assert.ok( false, "callback method should not be executed" ); 96 | }; 97 | 98 | secure.secureStandardMethods(callback); 99 | 100 | var dsc = Object.getOwnPropertyDescriptor(Object.prototype, "toString"); 101 | assert.equal( dsc.writable, false ); 102 | assert.equal( dsc.configurable, false ); 103 | 104 | // tests if the function overrode itself. Second execution should throw error, because 105 | // all standard methods are already protected 106 | secure.secureStandardMethods(callback); 107 | } 108 | 109 | }; 110 | 111 | test.start(tests); -------------------------------------------------------------------------------- /test/test-commons.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Common tests adn utils used by other tests from the same folder. 3 | * Don't use it separately. 4 | * @author David de Rosier 5 | */ 6 | 7 | var assert = require("assert"); 8 | 9 | 10 | exports.start = function(tests) { 11 | Object.keys(tests).forEach(function(f){ 12 | console.log( "Running test: " + f ); 13 | tests[f](); 14 | }); 15 | }; 16 | 17 | 18 | exports.standardTests = { 19 | 20 | correctValues: function(){ 21 | assert.equal( undefined, void 0, "undefined" ); 22 | assert.equal( Infinity, 1/0, "infinity" ); 23 | assert.equal( String(NaN), "NaN", "NaN" ); 24 | 25 | assert.equal( typeof undefined, "undefined", "typeof undefined" ); 26 | assert.equal( typeof Infinity, "number", "typeof Infinity" ); 27 | assert.equal( typeof NaN, "number", "typeof NaN" ); 28 | }, 29 | 30 | 31 | moduleLoad: function() { 32 | 33 | var secure; 34 | 35 | assert.doesNotThrow( function(){ 36 | secure = require("../js/node-secure"); 37 | }); 38 | 39 | this.correctValues(); 40 | 41 | assert.equal( typeof secure.secureMethods, "function", "typeof secure.secureMethods" ); 42 | assert.equal( typeof secure.securePrivates, "function", "typeof secure.securePrivates" ); 43 | assert.equal( typeof secure.isSecure, "function", "typeof secure.isSecure" ); 44 | assert.equal( typeof secure.status, "object", "typeof secure.status" ); 45 | 46 | assert.equal( secure.isSecure(), true, "secure.isSecure()"); 47 | 48 | return secure; 49 | } 50 | }; 51 | 52 | --------------------------------------------------------------------------------