refactor: modularize backend security and observability
This commit is contained in:
34
backend/utils/path-safety.js
Normal file
34
backend/utils/path-safety.js
Normal file
@@ -0,0 +1,34 @@
|
||||
const path = require('path');
|
||||
|
||||
function isPathInside(parent, child) {
|
||||
const relativePath = path.relative(parent, child);
|
||||
return relativePath === '' || (!relativePath.startsWith('..') && !path.isAbsolute(relativePath));
|
||||
}
|
||||
|
||||
function normalizeVirtualPath(rawPath) {
|
||||
if (typeof rawPath !== 'string') return null;
|
||||
|
||||
let decoded = rawPath;
|
||||
try {
|
||||
decoded = decodeURIComponent(rawPath);
|
||||
} catch {
|
||||
// The traversal checks below still apply to malformed encoded input.
|
||||
}
|
||||
|
||||
if (decoded.includes('\x00') || decoded.toLowerCase().includes('%00')) return null;
|
||||
|
||||
const unifiedPath = decoded.replace(/\\/g, '/');
|
||||
if (/(^|\/)\.\.(\/|$)/.test(unifiedPath)) return null;
|
||||
|
||||
let normalized = path.posix.normalize(unifiedPath);
|
||||
if (normalized === '' || normalized === '.') normalized = '/';
|
||||
if (!normalized.startsWith('/')) normalized = `/${normalized}`;
|
||||
|
||||
normalized = normalized.replace(/\/+$/g, '');
|
||||
return normalized || '/';
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
isPathInside,
|
||||
normalizeVirtualPath
|
||||
};
|
||||
Reference in New Issue
Block a user