Fossil SCM

Add a CSRF check to /chat-send.

stephan 2025-09-01 16:58 trunk
Commit 4caa8cb9ff819f7eee8536f7f4892fca803fdf7072ed25d76a6ac4bd19992b7e
2 files changed +18 +2 -2
+18
--- src/chat.c
+++ src/chat.c
@@ -389,10 +389,25 @@
389389
}else{
390390
CX("}");
391391
}
392392
fossil_free(zTime);
393393
}
394
+
395
+/*
396
+** Like chat_emit_permissions_error() but emits a single
397
+** /chat-message-format JSON object
398
+*/
399
+static void chat_emit_csrf_error(void){
400
+ char * zTime = cgi_iso8601_datestamp();
401
+ cgi_set_content_type("application/json");
402
+ CX("{");
403
+ CX("\"isError\": true, \"xfrom\": null,");
404
+ CX("\"mtime\": %!j, \"lmtime\": %!j,", zTime, zTime);
405
+ CX("\"xmsg\": \"CSRF validation failure.\"");
406
+ CX("}");
407
+ fossil_free(zTime);
408
+}
394409
395410
/*
396411
** WEBPAGE: chat-send hidden loadavg-exempt
397412
**
398413
** This page receives (via XHR) a new chat-message and/or a new file
@@ -421,10 +436,13 @@
421436
const char *zMsg;
422437
const char *zUserName;
423438
login_check_credentials();
424439
if( 0==g.perm.Chat ) {
425440
chat_emit_permissions_error(0);
441
+ return;
442
+ }else if( 0==cgi_csrf_safe(1) ){
443
+ chat_emit_csrf_error();
426444
return;
427445
}
428446
zUserName = (g.zLogin && g.zLogin[0]) ? g.zLogin : "nobody";
429447
nByte = atoi(PD("file:bytes","0"));
430448
zMsg = PD("msg","");
431449
--- src/chat.c
+++ src/chat.c
@@ -389,10 +389,25 @@
389 }else{
390 CX("}");
391 }
392 fossil_free(zTime);
393 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
394
395 /*
396 ** WEBPAGE: chat-send hidden loadavg-exempt
397 **
398 ** This page receives (via XHR) a new chat-message and/or a new file
@@ -421,10 +436,13 @@
421 const char *zMsg;
422 const char *zUserName;
423 login_check_credentials();
424 if( 0==g.perm.Chat ) {
425 chat_emit_permissions_error(0);
 
 
 
426 return;
427 }
428 zUserName = (g.zLogin && g.zLogin[0]) ? g.zLogin : "nobody";
429 nByte = atoi(PD("file:bytes","0"));
430 zMsg = PD("msg","");
431
--- src/chat.c
+++ src/chat.c
@@ -389,10 +389,25 @@
389 }else{
390 CX("}");
391 }
392 fossil_free(zTime);
393 }
394
395 /*
396 ** Like chat_emit_permissions_error() but emits a single
397 ** /chat-message-format JSON object
398 */
399 static void chat_emit_csrf_error(void){
400 char * zTime = cgi_iso8601_datestamp();
401 cgi_set_content_type("application/json");
402 CX("{");
403 CX("\"isError\": true, \"xfrom\": null,");
404 CX("\"mtime\": %!j, \"lmtime\": %!j,", zTime, zTime);
405 CX("\"xmsg\": \"CSRF validation failure.\"");
406 CX("}");
407 fossil_free(zTime);
408 }
409
410 /*
411 ** WEBPAGE: chat-send hidden loadavg-exempt
412 **
413 ** This page receives (via XHR) a new chat-message and/or a new file
@@ -421,10 +436,13 @@
436 const char *zMsg;
437 const char *zUserName;
438 login_check_credentials();
439 if( 0==g.perm.Chat ) {
440 chat_emit_permissions_error(0);
441 return;
442 }else if( 0==cgi_csrf_safe(1) ){
443 chat_emit_csrf_error();
444 return;
445 }
446 zUserName = (g.zLogin && g.zLogin[0]) ? g.zLogin : "nobody";
447 nByte = atoi(PD("file:bytes","0"));
448 zMsg = PD("msg","");
449
--- src/fossil.dom.js
+++ src/fossil.dom.js
@@ -843,12 +843,12 @@
843843
/**
844844
Parses a string as HTML.
845845
846846
Usages:
847847
848
- Array (htmlString)
849
- DOMElement (DOMElement target, htmlString)
848
+ Array parseHtml(htmlString)
849
+ DOMElement parseHtml(DOMElement target, htmlString)
850850
851851
The first form parses the string as HTML and returns an Array of
852852
all elements parsed from it. If string is falsy then it returns
853853
an empty array.
854854
855855
--- src/fossil.dom.js
+++ src/fossil.dom.js
@@ -843,12 +843,12 @@
843 /**
844 Parses a string as HTML.
845
846 Usages:
847
848 Array (htmlString)
849 DOMElement (DOMElement target, htmlString)
850
851 The first form parses the string as HTML and returns an Array of
852 all elements parsed from it. If string is falsy then it returns
853 an empty array.
854
855
--- src/fossil.dom.js
+++ src/fossil.dom.js
@@ -843,12 +843,12 @@
843 /**
844 Parses a string as HTML.
845
846 Usages:
847
848 Array parseHtml(htmlString)
849 DOMElement parseHtml(DOMElement target, htmlString)
850
851 The first form parses the string as HTML and returns an Array of
852 all elements parsed from it. If string is falsy then it returns
853 an empty array.
854
855

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button