security: fix vulnerabilities and update security hardening (2026-03-12)
Code security fixes: - Fixed 3 critical auth bypass bugs (user.jso, typo → user.json) in RenameFile, NewFolder, DeleteFolder API routes - Added URL validation (HTTP/HTTPS only) on ProfilPicture and BackgroundCustom endpoints to prevent stored XSS/CSS injection - Added path traversal protection in Upload.js (resolved path boundary check) - Removed unsafe-eval from CSP script-src directive - Removed information disclosure in BuildMetaData error responses - Removed unused child_process import in BuildMetaData.js Version bump: 1.2.1-beta → 1.2.2-beta
This commit is contained in:
@@ -13,6 +13,16 @@ router.post('/wallpaper', (req, res) => {
|
||||
return res.status(400).send('No wallpaper URL provided.');
|
||||
}
|
||||
|
||||
// Validate URL to prevent XSS/CSS injection via malicious URLs
|
||||
try {
|
||||
const parsed = new URL(wallpaperUrl);
|
||||
if (!['http:', 'https:'].includes(parsed.protocol)) {
|
||||
return res.status(400).send('Invalid URL protocol. Only HTTP/HTTPS allowed.');
|
||||
}
|
||||
} catch {
|
||||
return res.status(400).send('Invalid URL format.');
|
||||
}
|
||||
|
||||
updateUserWallpaper(userId, wallpaperUrl, res);
|
||||
});
|
||||
|
||||
|
||||
@@ -129,9 +129,9 @@ function authenticateToken(req, res, next) {
|
||||
return res.status(401).json({ message: 'Unauthorized' });
|
||||
}
|
||||
|
||||
fs.readFile(path.join(__dirname, '../../../data', 'user.jso,'), 'utf8', (err, data) => {
|
||||
fs.readFile(path.join(__dirname, '../../../data', 'user.json'), 'utf8', (err, data) => {
|
||||
if (err) {
|
||||
console.error('Error reading user.jso,:', err);
|
||||
console.error('Error reading user.json:', err);
|
||||
return res.status(401).json({ message: 'Unauthorized' });
|
||||
}
|
||||
|
||||
|
||||
@@ -105,7 +105,7 @@ function authenticateToken(req, res, next) {
|
||||
return res.status(401).json({ message: 'Unauthorized' });
|
||||
}
|
||||
|
||||
fs.readFile(path.join(__dirname, '../../../data', 'user.jso,'), 'utf8', (err, data) => {
|
||||
fs.readFile(path.join(__dirname, '../../../data', 'user.json'), 'utf8', (err, data) => {
|
||||
if (err) {
|
||||
console.error('Error reading user.json:', err);
|
||||
return res.status(401).json({ message: 'Unauthorized' });
|
||||
|
||||
@@ -13,6 +13,16 @@ router.post('/', (req, res) => {
|
||||
return res.status(400).send('No profile picture URL provided.');
|
||||
}
|
||||
|
||||
// Validate URL to prevent XSS/injection via malicious URLs
|
||||
try {
|
||||
const parsed = new URL(profilePictureUrl);
|
||||
if (!['http:', 'https:'].includes(parsed.protocol)) {
|
||||
return res.status(400).send('Invalid URL protocol. Only HTTP/HTTPS allowed.');
|
||||
}
|
||||
} catch {
|
||||
return res.status(400).send('Invalid URL format.');
|
||||
}
|
||||
|
||||
updateUserProfilePicture(userId, profilePictureUrl, res);
|
||||
});
|
||||
|
||||
|
||||
@@ -107,7 +107,7 @@ function authenticateToken(req, res, next) {
|
||||
}
|
||||
}
|
||||
|
||||
fs.readFile(path.join(__dirname, '../../../data', 'user.jso,'), 'utf8', (err, data) => {
|
||||
fs.readFile(path.join(__dirname, '../../../data', 'user.json'), 'utf8', (err, data) => {
|
||||
if (err) {
|
||||
console.error('Error reading user.json:', err);
|
||||
return res.status(401).json({ message: 'Unauthorized' });
|
||||
|
||||
@@ -68,6 +68,14 @@ router.post('/', (req, res) => {
|
||||
const filename = fields.filename ? fields.filename[0] : file.originalFilename;
|
||||
const filePath = path.join(userDir, filename);
|
||||
|
||||
// Path traversal protection: ensure resolved path stays within user directory
|
||||
const resolvedUserDir = path.resolve(process.cwd(), 'cdn-files', userName);
|
||||
const resolvedFilePath = path.resolve(filePath);
|
||||
if (!resolvedFilePath.startsWith(resolvedUserDir + path.sep) && resolvedFilePath !== resolvedUserDir) {
|
||||
if (fs.existsSync(file.path)) fs.unlinkSync(file.path);
|
||||
return res.status(403).send('Path traversal detected');
|
||||
}
|
||||
|
||||
// Récupérer les champs supplémentaires
|
||||
const expiryDate = fields.expiryDate ? fields.expiryDate[0] : '';
|
||||
const password = fields.password ? fields.password[0] : '';
|
||||
|
||||
Reference in New Issue
Block a user