@@ -57,6 +57,26 @@ function _tilde_expand_list(list){
57
57
} ) ;
58
58
}
59
59
60
+
61
+ // Basic input sanitation to buffer input against XSS attempts. No
62
+ // need for chevrons (i.e. tagged input) in our server-client universe
63
+ // for now.
64
+ var r1 = new RegExp ( "<" , "g" ) ;
65
+ var r2 = new RegExp ( ">" , "g" ) ;
66
+ var r3 = new RegExp ( "\\(" , "g" ) ;
67
+ var r4 = new RegExp ( "\\)" , "g" ) ;
68
+ function _sanitize ( in_str ) {
69
+ if ( Object . prototype . toString . call ( in_str ) === '[object String]' ) {
70
+ //console.log('PRE:: ' + in_str);
71
+ in_str = in_str . replace ( r1 , "" ) ;
72
+ in_str = in_str . replace ( r2 , "" ) ;
73
+ in_str = in_str . replace ( r3 , "" ) ;
74
+ in_str = in_str . replace ( r4 , "" ) ;
75
+ //console.log('POST:: ' + in_str);
76
+ }
77
+ return in_str ;
78
+ }
79
+
60
80
// Aliases.
61
81
var each = us . each ;
62
82
var what_is = bbop . what_is ;
@@ -498,6 +518,28 @@ var NoctuaLauncher = function(){
498
518
/// Response helper.
499
519
///
500
520
521
+ // False, return true is something sanitized.
522
+ self . sanitize_request = function ( req ) {
523
+ var ret = false ;
524
+
525
+ var purgable = [ 'model_id' ,
526
+ 'individual_id' ,
527
+ 'subject_individual_id' ,
528
+ 'object_individual_id' ,
529
+ 'relation_id' ,
530
+ 'barista_token' ] ;
531
+ if ( req && req . query ) {
532
+
533
+ each ( purgable , function ( p ) {
534
+ if ( req . query [ p ] ) {
535
+ req . query [ p ] = _sanitize ( req . query [ p ] ) ;
536
+ ret = true ;
537
+ }
538
+ } ) ;
539
+ }
540
+ return ret ;
541
+ } ;
542
+
501
543
self . get_token = function ( req ) {
502
544
var ret = null ;
503
545
if ( req && req . query && req . query [ 'barista_token' ] ) {
@@ -807,6 +849,8 @@ var NoctuaLauncher = function(){
807
849
808
850
// Redirect to given workbench from root route.
809
851
self . app . get ( '/' , function ( req , res ) {
852
+ self . sanitize_request ( req ) ;
853
+
810
854
// TODO: This workbench should be made a parameter.
811
855
var landing_location = 'workbench/noctua-landing-page' ;
812
856
@@ -822,6 +866,8 @@ var NoctuaLauncher = function(){
822
866
823
867
// Administration page (old landing).
824
868
self . app . get ( '/admin' , function ( req , res ) {
869
+ self . sanitize_request ( req ) ;
870
+
825
871
// Grab markdown renderable file.
826
872
var landing_raw = fs . readFileSync ( './OVERVIEW.' + noctua_context + '.md' ) . toString ( ) ;
827
873
var landing_md = md . markdown . toHTML ( landing_raw ) ;
@@ -857,6 +903,7 @@ var NoctuaLauncher = function(){
857
903
858
904
// General markdown documentation.
859
905
self . app . get ( '/doc/:fname' , function ( req , res ) {
906
+ self . sanitize_request ( req ) ;
860
907
861
908
var final_content = '???' ;
862
909
var fname = req . params [ 'fname' ] || '' ;
@@ -919,6 +966,7 @@ var NoctuaLauncher = function(){
919
966
920
967
//
921
968
self . app . get ( '/basic/:model_type/:query' , function ( req , res ) {
969
+ self . sanitize_request ( req ) ;
922
970
923
971
// Try and see if we have an API token.
924
972
var barista_token = self . get_token ( req ) ;
@@ -980,6 +1028,7 @@ var NoctuaLauncher = function(){
980
1028
// This will skip cached templates.
981
1029
if ( ctype !== null ) {
982
1030
self . app . get ( '/' + thing , function ( req , res ) {
1031
+ self . sanitize_request ( req ) ;
983
1032
984
1033
res . setHeader ( 'Content-Type' , ctype ) ;
985
1034
res . send ( pup_tent . get ( thing ) ) ;
@@ -1011,6 +1060,7 @@ var NoctuaLauncher = function(){
1011
1060
var fname = item [ 0 ] ;
1012
1061
var type = item [ 1 ] ;
1013
1062
self . app . get ( '/images/' + fname , function ( req , res ) {
1063
+ self . sanitize_request ( req ) ;
1014
1064
res . setHeader ( 'Content-Type' , 'image/' + type ) ;
1015
1065
res . sendfile ( 'static/' + fname ) ;
1016
1066
} ) ;
@@ -1019,11 +1069,13 @@ var NoctuaLauncher = function(){
1019
1069
// TODO: This obviously does not do anything than supress some types
1020
1070
// of error messages.
1021
1071
self . app . get ( '/favicon.ico' , function ( req , res ) {
1072
+ self . sanitize_request ( req ) ;
1022
1073
self . standard_response ( res , 200 , 'image/x-icon' , '' ) ;
1023
1074
} ) ;
1024
1075
1025
1076
// Error redirect catch.
1026
1077
self . app . get ( '/error' , function ( req , res ) {
1078
+ self . sanitize_request ( req ) ;
1027
1079
1028
1080
console . log ( 'caught intentional redirect for error report' ) ;
1029
1081
@@ -1053,6 +1105,7 @@ var NoctuaLauncher = function(){
1053
1105
///
1054
1106
1055
1107
self . app . get ( '/status' , function ( req , res ) {
1108
+ self . sanitize_request ( req ) ;
1056
1109
1057
1110
console . log ( 'process heartbeat request' ) ;
1058
1111
@@ -1088,6 +1141,7 @@ var NoctuaLauncher = function(){
1088
1141
// Directly kick-to-edit an extant model--most things should
1089
1142
// pass through here.
1090
1143
self . app . get ( '/editor/graph/:query' , function ( req , res ) {
1144
+ self . sanitize_request ( req ) ;
1091
1145
1092
1146
monitor_internal_kicks = monitor_internal_kicks + 1 ;
1093
1147
@@ -1131,6 +1185,7 @@ var NoctuaLauncher = function(){
1131
1185
var injectable_css = wb [ 'css' ] || [ ] ;
1132
1186
1133
1187
self . app . get ( '/workbench/' + wbid , function ( req , res ) {
1188
+ self . sanitize_request ( req ) ;
1134
1189
1135
1190
monitor_internal_kicks = monitor_internal_kicks + 1 ;
1136
1191
@@ -1169,7 +1224,7 @@ var NoctuaLauncher = function(){
1169
1224
'subject_individual_id or' +
1170
1225
'object_individual_id or' +
1171
1226
'relation_id' ) ;
1172
- }
1227
+ }
1173
1228
} else {
1174
1229
// TODO: Error.
1175
1230
}
@@ -1196,6 +1251,7 @@ var NoctuaLauncher = function(){
1196
1251
// DEBUG: A JSON model debugging tool for @hdietze
1197
1252
/// This path will eventually be destroyed.
1198
1253
self . app . post ( '/seed/json' , function ( req , res ) {
1254
+ self . sanitize_request ( req ) ;
1199
1255
1200
1256
monitor_internal_kicks = monitor_internal_kicks + 1 ;
1201
1257
@@ -1236,11 +1292,13 @@ var NoctuaLauncher = function(){
1236
1292
1237
1293
// Offer POST, not GET.
1238
1294
self . app . get ( '/tractorbeam' , function ( req , res ) {
1295
+ self . sanitize_request ( req ) ;
1239
1296
tll ( 'attempt to GET tractorbeam' ) ;
1240
1297
pre_fail ( res , "no GET endpoint" ,
1241
1298
"try POST instead of GET at this URL" ) ;
1242
1299
} ) ;
1243
1300
self . app . post ( '/tractorbeam' , function ( req , res ) {
1301
+ self . sanitize_request ( req ) ;
1244
1302
1245
1303
monitor_internal_kicks = monitor_internal_kicks + 1 ;
1246
1304
@@ -1580,6 +1638,7 @@ var NoctuaLauncher = function(){
1580
1638
1581
1639
// Test export handler.
1582
1640
self . app . post ( '/action/display' , function ( req , res ) {
1641
+ self . sanitize_request ( req ) ;
1583
1642
1584
1643
// Deal with incoming parameters.
1585
1644
var mstr = req . query [ 'thing' ] ||
@@ -1596,6 +1655,7 @@ var NoctuaLauncher = function(){
1596
1655
1597
1656
// Downloads for the impatient.
1598
1657
self . app . get ( '/download/:model/:format?' , function ( req , res ) {
1658
+ self . sanitize_request ( req ) ;
1599
1659
1600
1660
monitor_internal_kicks = monitor_internal_kicks + 1 ;
1601
1661
0 commit comments