200 |
File Index
201 |
202 |
203 |
204 |
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 | .html:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 | JsDoc Reference -
9 |
10 |
174 |
175 |
176 |
177 |
178 |
179 |
181 |
182 |
183 |
184 |
185 |
186 |
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 | Namespace Summary
228 |
229 |
230 | Constructor Attributes |
231 | Constructor Name and Description |
232 |
233 |
234 |
235 |
236 | |
237 |
238 |
239 |
240 |
241 |
242 | |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 | Field Summary
254 |
255 |
256 | Field Attributes |
257 | Field Name and Description |
258 |
259 |
260 |
261 |
262 |
263 | <static> |
264 |
265 |
266 | ..status
267 |
268 | Statuses of protection level.
269 | |
270 |
271 |
272 |
273 |
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 |
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 |
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 | Class Summary
230 |
231 |
232 | Constructor Attributes |
233 | Constructor Name and Description |
234 |
235 |
236 |
237 |
238 | |
239 |
240 |
243 | Error object constructor dedicated to security issues.
244 | |
245 |
246 |
247 |
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 |
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 |
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 | Class Summary
228 |
229 |
230 | Constructor Attributes |
231 | Constructor Name and Description |
232 |
233 |
234 |
235 |
236 | |
237 |
238 |
241 | Error object constructor dedicated to security issues.
242 | |
243 |
244 |
245 |
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 |
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 | Namespace Summary
228 |
229 |
230 | Constructor Attributes |
231 | Constructor Name and Description |
232 |
233 |
234 |
235 |
236 | |
237 |
238 |
241 |
242 | |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 | Field Summary
254 |
255 |
256 | Field Attributes |
257 | Field Name and Description |
258 |
259 |
260 |
261 |
262 |
263 | <static> |
264 |
265 |
268 | Statuses of protection level.
269 | |
270 |
271 |
272 |
273 |
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 |
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 | Namespace Summary
228 |
229 |
230 | Constructor Attributes |
231 | Constructor Name and Description |
232 |
233 |
234 |
235 |
236 | |
237 |
238 |
241 |
242 | |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 | Field Summary
254 |
255 |
256 | Field Attributes |
257 | Field Name and Description |
258 |
259 |
260 |
261 |
262 |
263 | <static> |
264 |
265 |
268 | Statuses of protection level.
269 | |
270 |
271 |
272 |
273 |
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 |
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 | Class Summary
230 |
231 |
232 | Constructor Attributes |
233 | Constructor Name and Description |
234 |
235 |
236 |
237 |
238 | |
239 |
240 |
241 | secure SecurityError(msg, problems)
242 |
243 | Error object constructor dedicated to security issues.
244 | |
245 |
246 |
247 |
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 |
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 | Class Summary
230 |
231 |
232 | Constructor Attributes |
233 | Constructor Name and Description |
234 |
235 |
236 |
237 |
238 | |
239 |
240 |
243 | Error object constructor dedicated to security issues.
244 | |
245 |
246 |
247 |
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 |
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 | Namespace Summary
228 |
229 |
230 | Constructor Attributes |
231 | Constructor Name and Description |
232 |
233 |
234 |
235 |
236 | |
237 |
238 |
241 | This namespace contains all elements provided through exports
242 | variable.
243 | |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 | Field Summary
255 |
256 |
257 | Field Attributes |
258 | Field Name and Description |
259 |
260 |
261 |
262 |
263 |
264 | <static> |
265 |
266 |
269 | Statuses of protection level.
270 | |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 | Method Summary
286 |
287 |
288 | Method Attributes |
289 | Method Name and Description |
290 |
291 |
292 |
293 |
294 |
295 | <static> |
296 |
297 |
299 | Checks the status of the global variables protection
300 | |
301 |
302 |
303 |
304 | <static> |
305 |
306 |
308 | Makes all methods of given object non-writable.
309 | |
310 |
311 |
312 |
313 | <static> |
314 |
315 |
317 | Marks all private-like members (starting from _ or __ prefix) as not enumerable
318 | Additional protection can be added (read-only, configurability)
319 | |
320 |
321 |
322 |
323 | <static> |
324 |
325 |
327 |
328 | Protects methods of standard JavaScript objects from being overridden.
329 | |
330 |
331 |
332 |
333 |
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 |
--------------------------------------------------------------------------------