Skip to content
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import json
import tornado.escape
import datetime

from diraccfg import CFG
Expand Down Expand Up @@ -517,7 +518,8 @@ def __generateHTMLDiff(self, diffGen):
diffList.append(("", diffLine[1:], diffLine[1:], lineNumber))
lineNumber = lineNumber + 1

return {"diff": diffList, "lines": linesDiffList, "totalLines": lineNumber}
escList = [(k, tornado.escape.xhtml_escape(a), tornado.escape.xhtml_escape(b), n) for (k, a, b, n) in diffList]
return {"diff": escList, "lines": linesDiffList, "totalLines": lineNumber}

def __showCurrentDiff(self):
if not self.__authorizeAction():
Expand Down
11 changes: 8 additions & 3 deletions src/WebAppDIRAC/WebApp/handler/FileCatalogHandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,10 @@ def web_getSelectedFiles(self, archivePath=None, path=None):
pathInZip = lfn[pos_relative:last_slash]
tmpPathInZip = tmpdir + pathInZip
gLogger.always(f"path in zip {tmpPathInZip}")
if not os.path.isdir(tmpPathInZip):
os.makedirs(tmpPathInZip)
if ".." in pathInZip.split(os.sep):
shutil.rmtree(tmpdir, ignore_errors=True)
return {"success": "false", "error": "Invalid path", "lfn": lfn}
os.makedirs(tmpPathInZip, exist_ok=True)
result = dataMgr.getFile(str(lfn), destinationDir=str(tmpPathInZip))
if not result["OK"]:
gLogger.error("Error getting while getting files", result["Message"])
Expand Down Expand Up @@ -91,7 +93,10 @@ def web_getSelectedFiles(self, archivePath=None, path=None):
# Validate archivePath to prevent path traversal attacks
realArchivePath = os.path.realpath(archivePath)
tempDir = tempfile.gettempdir()
if not realArchivePath.startswith(tempDir + os.sep) and realArchivePath != tempDir:
base = os.path.basename(realArchivePath)
if realArchivePath != os.path.join(tempDir, base) or not (
base.startswith("DIRAC_FC_") and base.endswith(".zip")
):
gLogger.error(f"Path traversal attempt detected: {archivePath}")
return {"success": "false", "error": "Invalid archive path"}

Expand Down
7 changes: 5 additions & 2 deletions src/WebAppDIRAC/WebApp/handler/JobLaunchpadHandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,9 +175,12 @@ def web_jobSubmit(self):
storePath = tempfile.mkdtemp(prefix="DIRAC_")
try:
for fileObj in store:
name = os.path.join(storePath, fileObj.filename.lstrip(os.sep))
basename = os.path.basename(fileObj.filename)
if not basename or basename in (".", ".."):
raise ValueError(f"Invalid upload filename: {fileObj.filename!r}")
name = os.path.join(storePath, basename)

tFile = open(name, "w")
tFile = open(name, "xb")
tFile.write(fileObj.body)
tFile.close()

Expand Down
6 changes: 5 additions & 1 deletion src/WebAppDIRAC/WebApp/handler/JobMonitorHandler.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import json
import datetime
from urllib.parse import quote

from DIRAC import gConfig, gLogger
from DIRAC.Core.Utilities import DictCache
Expand Down Expand Up @@ -474,10 +475,13 @@ def web_getSandbox(self, jobID: int = None, sandbox: str = "Output", check=None)
if check:
return {"success": "true"}

if sandbox not in ("Input", "Output", "Check"):
return {"success": "false", "error": "Invalid sandbox type"}

data = result["Value"]
fname = f"{str(jobID)}_{sandbox}Sandbox.tar"
self.set_header("Content-type", "application/x-tar")
self.set_header("Content-Disposition", f'attachment; filename="{fname}"')
self.set_header("Content-Disposition", f"attachment; filename*=UTF-8''{quote(fname)}")
self.set_header("Content-Length", len(data))
self.set_header("Cache-Control", "no-cache, no-store, must-revalidate, max-age=0")
self.set_header("Pragma", "no-cache")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1135,7 +1135,7 @@ Ext.define("DIRAC.JobMonitor.classes.JobMonitor", {
width: 140,
height: 28,
renderer: function (toolTip, record, ctx) {
toolTip.setHtml(record.get("key") + ": " + record.get("value"));
toolTip.setHtml(Ext.util.Format.htmlEncode(record.get("key") + ": " + record.get("value")));
},
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -785,7 +785,7 @@ Ext.define("DIRAC.PilotMonitor.classes.PilotMonitor", {
width: 140,
height: 28,
renderer: function (toolTip, record, ctx) {
toolTip.setHtml(record.get("key") + ": " + record.get("value"));
toolTip.setHtml(Ext.util.Format.htmlEncode(record.get("key") + ": " + record.get("value")));
},
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,7 @@ Ext.define("DIRAC.SystemAdministration.classes.SystemAdministration", {
},
],
rendererChkBox: function (val) {
val = Ext.util.Format.htmlEncode(val);
return '<input value="' + val + '" type="checkbox" class="checkrow" style="margin:0px;padding:0px"/>';
},
rendererValueBar: function (value) {
Expand Down Expand Up @@ -758,6 +759,7 @@ Ext.define("DIRAC.SystemAdministration.classes.SystemAdministration", {
},
],
rendererChkBox: function (val) {
val = Ext.util.Format.htmlEncode(val);
return '<input value="' + val + '" type="checkbox" class="checkrow" style="margin:0px;padding:0px"/>';
},
rendererUptime: function (value, record) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ Ext.define("Ext.dirac.utils.DiracGridPanel", {
});
} else {
var tooltipRenderer = function (value, metaData) {
metaData.tdAttr = Ext.String.format('data-qtip="{0}"', value);
metaData.tdAttr = Ext.String.format('data-qtip="{0}"', Ext.util.Format.htmlEncode(value));
return value;
};
Ext.apply(oColumn, {
Expand Down Expand Up @@ -383,6 +383,7 @@ Ext.define("Ext.dirac.utils.DiracGridPanel", {
* @param{Number} val it is the column value
*/
rendererChkBox: function (val) {
val = Ext.util.Format.htmlEncode(val);
return '<input value="' + val + '" type="checkbox" class="checkrow" style="margin:0px;padding:0px"/>';
},
/*************************************************************************
Expand Down
Loading