javascript.apollo.security.apollo-axios-ssrf.apollo-axios-ssrf
semgrep
Author
742
Download Count*
License
User-controllable argument $DATAVAL to $METHOD passed to Axios via internal handler $INNERFUNC. This could be a server-side request forgery. A user could call a restricted API or leak internal headers to an unauthorized party. Validate your user arguments against an allowlist of known URLs, or consider refactoring so that user-controlled data is not necessary.
Run Locally
Run in CI
Defintion
rules:
- id: apollo-axios-ssrf
message: User-controllable argument $DATAVAL to $METHOD passed to Axios via
internal handler $INNERFUNC. This could be a server-side request forgery.
A user could call a restricted API or leak internal headers to an
unauthorized party. Validate your user arguments against an allowlist of
known URLs, or consider refactoring so that user-controlled data is not
necessary.
metadata:
owasp:
- A10:2021 - Server-Side Request Forgery (SSRF)
cwe:
- "CWE-918: Server-Side Request Forgery (SSRF)"
category: security
technology:
- apollo
- axios
references:
- https://www.cvedetails.com/cve/CVE-2020-28168/
- https://owasp.org/www-community/attacks/Server_Side_Request_Forgery
cwe2022-top25: true
cwe2021-top25: true
subcategory:
- audit
likelihood: LOW
impact: MEDIUM
confidence: LOW
license: Commons Clause License Condition v1.0[LGPL-2.1-only]
vulnerability_class:
- Server-Side Request Forgery (SSRF)
languages:
- javascript
severity: WARNING
patterns:
- pattern: const $RESPONSE = await axios.request($INNERARG,...)
- pattern-inside: |
Query: {
$METHOD(parent, args, context, info) {
...
$DATA = args.$DATAVAL
...
async function $INNERFUNC(...,$INNERARG,...){
...
}
...
return $INNERFUNC(...,$DATA,...)
}
}
Examples
apollo-axios-ssrf.jsx
module.exports = {
Query: {
requestStatus(parent, args, context, info)
{
url = args.url
const axios = require('axios');
axios({
method: 'GET'
})
console.log(url)
async function getStatus(url) {
try {
// ruleid: apollo-axios-ssrf
const response = await axios.request(url);
console.log(response);
var s = response.status;
} catch (error) {
console.error(error);
var s = error.code;
}
return s;
}
return getStatus(url);
},
requestResponse(parent, args, context, info)
{
url = args.url
verb = args.verb
payload = args.payload
const axios = require('axios');
if (payload !== null || payload !== "") {
axios({
method: verb,
data: payload,
headers: {
'Content-Type': 'application/json'
}
})
}
else {
axios({
method: verb
})
}
console.log(url)
console.log(payload)
async function getResponse(url) {
try {
// ruleid: apollo-axios-ssrf
const response = await axios.request(url);
console.log(response);
var s = response.status;
} catch (error) {
console.error(error);
var s = error.message;
}
return s;
}
async function getResponseWithPayload(url, payload) {
try {
// ruleid: apollo-axios-ssrf
const response = await axios.request(url);
console.log(response);
var s = response.status;
} catch (error) {
console.error(error);
var s = error.message;
}
return s;
}
if (payload !== null || payload !== "") {
return getResponse(url);
}
else {
return getResponseWithPayload(url, payload)
}
}
}
};
Short Link: https://sg.run/jkEZ