javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal
semgrep
Author
4,565
Download Count*
License
Detected possible user input going into a path.join
or path.resolve
function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
Run Locally
Run in CI
Defintion
rules:
- id: path-join-resolve-traversal
message: Detected possible user input going into a `path.join` or `path.resolve`
function. This could possibly lead to a path traversal
vulnerability, where the attacker can access arbitrary files stored in
the file system. Instead, be sure to sanitize or validate user input
first.
metadata:
owasp:
- A05:2017 - Broken Access Control
- A01:2021 - Broken Access Control
cwe:
- "CWE-22: Improper Limitation of a Pathname to a Restricted Directory
('Path Traversal')"
category: security
references:
- https://owasp.org/www-community/attacks/Path_Traversal
technology:
- javascript
- node.js
cwe2022-top25: true
cwe2021-top25: true
subcategory:
- vuln
likelihood: HIGH
impact: MEDIUM
confidence: LOW
license: Commons Clause License Condition v1.0[LGPL-2.1-only]
vulnerability_class:
- Path Traversal
languages:
- javascript
- typescript
severity: WARNING
mode: taint
pattern-sources:
- patterns:
- focus-metavariable: $X
- pattern-either:
- pattern-inside: |
function ... (...,$X,...) {...}
- pattern-inside: |
function ... (...,{...,$X,...},...) {...}
pattern-sinks:
- patterns:
- focus-metavariable: $SINK
- pattern-either:
- pattern-inside: |
$PATH = require('path');
...
- pattern-inside: |
import $PATH from 'path';
...
- pattern-either:
- pattern: $PATH.join(...,$SINK,...)
- pattern: $PATH.resolve(...,$SINK,...)
- patterns:
- focus-metavariable: $SINK
- pattern-inside: |
import 'path';
...
- pattern-either:
- pattern-inside: path.join(...,$SINK,...)
- pattern-inside: path.resolve(...,$SINK,...)
pattern-sanitizers:
- pattern: $Y.replace(...)
- pattern: $Y.indexOf(...)
- pattern: |
function ... (...) {
...
<... $Y.indexOf(...) ...>
...
}
- patterns:
- pattern: $FUNC(...)
- metavariable-regex:
metavariable: $FUNC
regex: sanitize
Examples
path-join-resolve-traversal.js
var path = require('path');
var sanitizer = require('./util/sanitizer');
function test1() {
function someFunc(entry) {
// ruleid:path-join-resolve-traversal
var extractPath = path.join(opts.path, entry.path);
return extractFile(extractPath);
}
someFunc();
}
function test2() {
function someFunc(val) {
createFile({
// ruleid:path-join-resolve-traversal
filePath: path.resolve(opts.path, val)
})
return true
}
someFunc()
}
function test3(req,res) {
let somePath = req.body.path;
// ruleid:path-join-resolve-traversal
return path.join(opts.path, somePath);
}
function test4(req,res) {
let data = req.body.path;
data.forEach((entry) => {
// ruleid:path-join-resolve-traversal
var pth = path.join(opts.path, entry);
doSmth(pth);
})
}
function okTest1(req,res) {
let data = ['one', 'two', 'three'];
for (let x of data) {
// ok:path-join-resolve-traversal
var pth = path.join(opts.path, x);
doSmth(pth);
}
}
function okTest2() {
function someFunc() {
createFile({
// ok:path-join-resolve-traversal
filePath: path.join(__dirname, 'val')
})
return true
}
someFunc()
}
function okTest3(req,res) {
let somePath = req.body.path;
somePath = somePath.replace(/^(\.\.(\/|\\|$))+/, '');
// ok:path-join-resolve-traversal
return path.join(opts.path, somePath);
}
function okTest4(req,res) {
let somePath = sanitizer(req.body.path);
// ok:path-join-resolve-traversal
return path.join(opts.path, somePath);
}
function okTest5(req,res) {
let somePath = req.body.path;
// ok:path-join-resolve-traversal
let result = path.join(opts.path, somePath);
if (result.indexOf(opts.path) === 0) {
return path;
}
return null
}
path-join-resolve-traversal.ts
import { join, resolve } from 'path';
import sanitizer from './util/sanitizer';
function test1() {
function someFunc(entry) {
// ruleid:path-join-resolve-traversal
var extractPath = join(opts.path, entry.path);
return extractFile(extractPath);
}
someFunc();
}
function test2() {
function someFunc(val) {
createFile({
// ruleid:path-join-resolve-traversal
filePath: resolve(opts.path, val)
})
return true
}
someFunc()
}
function test3(req,res) {
let somePath = req.body.path;
// ruleid:path-join-resolve-traversal
return join(opts.path, somePath);
}
function test4(req,res) {
let data = req.body.path;
data.forEach((entry) => {
// ruleid:path-join-resolve-traversal
var pth = join(opts.path, entry);
doSmth(pth);
})
}
function test5(req,res) {
let data = req.body.path;
for (let i = 0; i < data.length; i++) {
// ruleid:path-join-resolve-traversal
var pth = join(opts.path, data[i]);
doSmth(pth);
}
}
function okTest1(req,res) {
let data = ['one', 'two', 'three'];
for (let x of data) {
// ok:path-join-resolve-traversal
var pth = join(opts.path, x);
doSmth(pth);
}
}
function okTest2() {
function someFunc() {
createFile({
// ok:path-join-resolve-traversal
filePath: join(__dirname, 'val')
})
return true
}
someFunc()
}
function okTest3(req,res) {
let somePath = req.body.path;
somePath = somePath.replace(/^(\.\.(\/|\\|$))+/, '');
// ok:path-join-resolve-traversal
return join(opts.path, somePath);
}
function okTest4(req,res) {
let somePath = sanitizer(req.body.path);
// ok:path-join-resolve-traversal
return join(opts.path, somePath);
}
function okTest5(req,res) {
let somePath = req.body.path;
// ok:path-join-resolve-traversal
let result = join(opts.path, somePath);
if (result.indexOf(opts.path) === 0) {
return path;
}
return null
}
Short Link: https://sg.run/OPqk