├── .deepsource.toml ├── .eslintrc.json ├── .github └── workflows │ ├── node-ci.yaml │ └── release.yaml ├── .gitignore ├── .mocharc.json ├── CHANGELOG.md ├── LICENSE ├── README.md ├── lib └── index.js ├── package-lock.json ├── package.json └── test ├── fixtures ├── allowedUrls.js └── blockedUrls.js └── index.test.js /.deepsource.toml: -------------------------------------------------------------------------------- 1 | version = 1 2 | 3 | [[analyzers]] 4 | name = "javascript" 5 | enabled = true 6 | 7 | [[analyzers]] 8 | name = "test-coverage" 9 | enabled = true 10 | 11 | [[analyzers]] 12 | name = "secrets" 13 | enabled = true -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "commonjs": true, 5 | "es2021": true 6 | }, 7 | "extends": [ 8 | "google" 9 | ], 10 | "parserOptions": { 11 | "ecmaVersion": 12 12 | }, 13 | "rules": { 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /.github/workflows/node-ci.yaml: -------------------------------------------------------------------------------- 1 | name: Node.js CI 2 | 3 | on: [push] 4 | 5 | jobs: 6 | build: 7 | strategy: 8 | matrix: 9 | node-version: [14.x, 15.x, 16.x, 18.x] 10 | os: 11 | - ubuntu-latest 12 | runs-on: "${{ matrix.os }}" 13 | steps: 14 | - uses: actions/checkout@v2 15 | - name: Use Node.js ${{ matrix.node-version }} 16 | uses: actions/setup-node@v1 17 | with: 18 | node-version: ${{ matrix.node-version }} 19 | - run: npm install 20 | - run: npm run build --if-present 21 | - run: npm test 22 | env: 23 | CI: true 24 | -------------------------------------------------------------------------------- /.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | name: Release 2 | on: 3 | push: 4 | branches: 5 | - master 6 | workflow_dispatch: 7 | inputs: 8 | reason: 9 | description: 'Manual Release Reason' 10 | jobs: 11 | release: 12 | name: Release 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Checkout 16 | uses: actions/checkout@v2 17 | with: 18 | fetch-depth: 0 19 | - name: Setup Node.js 20 | uses: actions/setup-node@v1 21 | with: 22 | node-version: '18.x' 23 | - name: Install dependencies 24 | run: npm ci 25 | - name: Release 26 | env: 27 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 28 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 29 | run: npx semantic-release 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Gatsby files 86 | .cache/ 87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 88 | # https://nextjs.org/blog/next-9-1#public-directory-support 89 | # public 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # Serverless directories 95 | .serverless/ 96 | 97 | # FuseBox cache 98 | .fusebox/ 99 | 100 | # DynamoDB Local files 101 | .dynamodb/ 102 | 103 | # TernJS port file 104 | .tern-port 105 | 106 | # VS Code 107 | .vscode/ 108 | 109 | # IntelliJ 110 | .idea/ 111 | -------------------------------------------------------------------------------- /.mocharc.json: -------------------------------------------------------------------------------- 1 | { 2 | "diff": true, 3 | "extension": [".test.js"], 4 | "package": "./package.json", 5 | "reporter": "spec", 6 | "slow": 75, 7 | "timeout": 50000, 8 | "ui": "bdd", 9 | "watch-files": ["lib/**/*.js", "test/**/*.js"], 10 | "watch-ignore": [] 11 | } 12 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [1.1.1](https://github.com/y-mehta/ssrf-req-filter/compare/v1.1.0...v1.1.1) (2024-05-11) 2 | 3 | 4 | ### Bug Fixes 5 | 6 | * upgrade ipaddr.js from 2.1.0 to 2.2.0 ([#44](https://github.com/y-mehta/ssrf-req-filter/issues/44)) ([6fb0027](https://github.com/y-mehta/ssrf-req-filter/commit/6fb00272585bd53e16d09b6494f52ea4cbf79371)) 7 | 8 | # [1.1.0](https://github.com/y-mehta/ssrf-req-filter/compare/v1.0.7...v1.1.0) (2023-08-17) 9 | 10 | 11 | ### Features 12 | 13 | * Add support for using existing http(s).Agent ([286e29d](https://github.com/y-mehta/ssrf-req-filter/commit/286e29db59580f1d8df93449318ef4d91123768e)) 14 | 15 | ## [1.0.7](https://github.com/y-mehta/ssrf-req-filter/compare/v1.0.6...v1.0.7) (2023-08-14) 16 | 17 | 18 | ### Bug Fixes 19 | 20 | * update allowedUrls.txt ([#35](https://github.com/y-mehta/ssrf-req-filter/issues/35)) ([53a9a32](https://github.com/y-mehta/ssrf-req-filter/commit/53a9a3215cb5ddc7a6bb73d9fba1955b78763c89)) 21 | 22 | ## [1.0.6](https://github.com/y-mehta/ssrf-req-filter/compare/v1.0.5...v1.0.6) (2023-03-17) 23 | 24 | 25 | ### Bug Fixes 26 | 27 | * bumped outdated dependencies ([#30](https://github.com/y-mehta/ssrf-req-filter/issues/30)) ([bf7d700](https://github.com/y-mehta/ssrf-req-filter/commit/bf7d7000e39f85a40729000f9b26c8cdec1e965c)), closes [#16](https://github.com/y-mehta/ssrf-req-filter/issues/16) 28 | 29 | ## [1.0.5](https://github.com/y-mehta/ssrf-req-filter/compare/v1.0.4...v1.0.5) (2021-07-01) 30 | 31 | 32 | ### Bug Fixes 33 | 34 | * upgrade ipaddr.js from 2.0.0 to 2.0.1 ([#6](https://github.com/y-mehta/ssrf-req-filter/issues/6)) ([f231ed7](https://github.com/y-mehta/ssrf-req-filter/commit/f231ed78f8ed6b993af2cde0b68c9c308b54a249)) 35 | 36 | ## [1.0.4](https://github.com/y-mehta/ssrf-req-filter/compare/v1.0.3...v1.0.4) (2020-12-29) 37 | 38 | 39 | ### Bug Fixes 40 | 41 | * Fixed tests ([cc95856](https://github.com/y-mehta/ssrf-req-filter/commit/cc958560c62951ceed1cdee86ad5a7353c7cb8d1)) 42 | 43 | ## [1.0.3](https://github.com/y-mehta/ssrf-req-filter/compare/v1.0.2...v1.0.3) (2020-12-29) 44 | 45 | 46 | ### Bug Fixes 47 | 48 | * Modified tests ([d87fc84](https://github.com/y-mehta/ssrf-req-filter/commit/d87fc848c862cbc6a7fff95fa9e85275aac097d2)) 49 | 50 | # Changelog 51 | 52 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. 53 | 54 | ### [1.0.1](https://github.com/y-mehta/ssrf-req-filter/compare/v1.0.0...v1.0.1) (2020-10-27) 55 | 56 | ## 1.0.0 (2020-10-26) 57 | - Bump Release Version 58 | - Minor Bug Fixes 59 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Yash Mehta 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ssrf-req-filter - Prevent SSRF Attacks :shield: 2 | 3 | ![npm](https://img.shields.io/npm/v/ssrf-req-filter?style=for-the-badge) ![NPM](https://img.shields.io/npm/l/ssrf-req-filter?style=for-the-badge) 4 | 5 | ## Server-Side Request Forgery (SSRF) 6 | 7 | SSRF is an attack vector that abuses an application to interact with the internal/external network or the machine itself. One of the enablers for this vector is the mishandling of URLs. [Read More](https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html) 8 | 9 | ## Install 10 | 11 | `npm install ssrf-req-filter` 12 | 13 | ## Usage 14 | 15 | - Axios: 16 | 17 | ``` 18 | const ssrfFilter = require('ssrf-req-filter'); 19 | const url = 'https://127.0.0.1' 20 | axios.get(url, {httpAgent: ssrfFilter(url), httpsAgent: ssrfFilter(url)}) 21 | .then((response) => { 22 | console.log(`Success`); 23 | }) 24 | .catch((error) => { 25 | console.log(`${error.toString().split('\n')[0]}`); 26 | }) 27 | .then(() => { 28 | 29 | }); 30 | ``` 31 | 32 | 33 | - Node-fetch: 34 | 35 | ``` 36 | const ssrfFilter = require('ssrf-req-filter'); 37 | const fetch = require("node-fetch"); 38 | const url = 'https://127.0.0.1' 39 | fetch(url, { 40 | agent: ssrfFilter(url) 41 | }) 42 | .then((response) => { 43 | console.log(`Success`); 44 | }) 45 | .catch(error => { 46 | console.log(`${error.toString().split('\n')[0]}`); 47 | }); 48 | ``` 49 | 50 | *Note: It's recommended to overwrite both httpAgent and httpsAgent in Axios with ssrf-req-filter. Otherwise, SSRF mitigation can be bypassed via cross protocol redirects. Refer to [Doyensec's research](https://blog.doyensec.com/2023/03/16/ssrf-remediation-bypass.html) for more information.* 51 | 52 | *Credits*: Implementation inspired By https://github.com/welefen/ssrf-agent 53 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | const http = require('http'); 2 | const https = require('https'); 3 | const ipaddr = require('ipaddr.js'); 4 | 5 | const checkIp = (ip) => { 6 | if (!ipaddr.isValid(ip)) { 7 | return true; 8 | } 9 | try { 10 | const addr = ipaddr.parse(ip); 11 | const range = addr.range(); 12 | if (range !== 'unicast') { 13 | return false; // Private IP Range 14 | } 15 | } catch (err) { 16 | return false; 17 | } 18 | return true; 19 | }; 20 | 21 | // prevent memory leak 22 | const ACTIVE = Symbol('active'); 23 | 24 | const requestFilterHandler = (agent)=>{ 25 | if (agent[ACTIVE]) return agent; 26 | agent[ACTIVE] = true; 27 | const {createConnection} = agent; 28 | agent.createConnection = function(options, func) { 29 | const {host: address} = options; 30 | if (!checkIp(address)) { 31 | throw new Error(`Call to ${address} is blocked.`); 32 | } 33 | const socket = createConnection.call(this, options, func); 34 | socket.on('lookup', (error, address) => { 35 | if (error || checkIp(address)) { 36 | return false; 37 | } 38 | return socket.destroy(new Error(`Call to ${address} is blocked.`)); 39 | }); 40 | return socket; 41 | }; 42 | return agent; 43 | }; 44 | 45 | const manageConnection = (url) => { 46 | const httpAgent = new http.Agent(); 47 | const httpsAgent = new https.Agent(); 48 | const agent = url.startsWith('https') ? httpsAgent : httpAgent; 49 | return requestFilterHandler(agent); 50 | }; 51 | 52 | module.exports = (url) => manageConnection(url); 53 | module.exports.requestFilterHandler = (agent) => requestFilterHandler(agent); 54 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ssrf-req-filter", 3 | "description": "Module to prevent SSRF when making requests", 4 | "version": "1.1.1", 5 | "keywords": [ 6 | "ssrf", 7 | "security", 8 | "agent", 9 | "ssrf fix", 10 | "ssrf filter", 11 | "request filter", 12 | "nodejs ssrf", 13 | "axios ssrf", 14 | "axios", 15 | "nodejs" 16 | ], 17 | "homepage": "https://github.com/y-mehta/ssrf-req-filter", 18 | "dependencies": { 19 | "ipaddr.js": "^2.2.0" 20 | }, 21 | "devDependencies": { 22 | "@semantic-release/changelog": "^6.0.2", 23 | "@semantic-release/commit-analyzer": "^9.0.2", 24 | "@semantic-release/git": "^10.0.1", 25 | "@semantic-release/npm": "^9.0.2", 26 | "@semantic-release/release-notes-generator": "^10.0.3", 27 | "axios": "^1.6.0", 28 | "chai": "^4.2.0", 29 | "eslint": "^7.12.0", 30 | "eslint-config-google": "^0.14.0", 31 | "eslint-plugin-import": "^2.22.1", 32 | "mocha": "^10.2.0" 33 | }, 34 | "main": "./lib/index.js", 35 | "directories": { 36 | "test": "./test", 37 | "lib": "./lib" 38 | }, 39 | "files": [ 40 | "lib/", 41 | "LICENSE", 42 | "README.md" 43 | ], 44 | "scripts": { 45 | "lint": "npx eslint lib test", 46 | "lintfix": "npx eslint --fix lib test", 47 | "test": "node ./node_modules/mocha/bin/mocha" 48 | }, 49 | "repository": { 50 | "type": "git", 51 | "url": "git+https://github.com/y-mehta/ssrf-req-filter.git" 52 | }, 53 | "author": "Yash Mehta", 54 | "license": "MIT", 55 | "bugs": { 56 | "url": "https://github.com/y-mehta/ssrf-req-filter/issues" 57 | }, 58 | "release": { 59 | "branches": [ 60 | "master" 61 | ], 62 | "plugins": [ 63 | "@semantic-release/commit-analyzer", 64 | "@semantic-release/release-notes-generator", 65 | "@semantic-release/changelog", 66 | "@semantic-release/npm", 67 | "@semantic-release/git" 68 | ] 69 | }, 70 | "publishConfig": { 71 | "provenance": true 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /test/fixtures/allowedUrls.js: -------------------------------------------------------------------------------- 1 | const allowedUrls = [ 2 | 'https://google.com', 3 | 'https://github.com', 4 | 'https://facebook.com', 5 | 'https://cloudflare.com', 6 | 'https://postman-echo.com/get', 7 | ]; 8 | 9 | module.exports = allowedUrls; 10 | -------------------------------------------------------------------------------- /test/fixtures/blockedUrls.js: -------------------------------------------------------------------------------- 1 | const blockedUrls = [ 2 | 'http://127.0.0.1:80', 3 | 'http://127.0.0.1:443', 4 | 'http://127.0.0.1:22', 5 | 'http://0.0.0.0:80', 6 | 'http://0.0.0.0:443', 7 | 'http://0.0.0.0:22', 8 | 'http://localhost:80', 9 | 'http://localhost:443', 10 | 'http://localhost:22', 11 | 'http://[::]:80', 12 | 'http://[::]:25/', 13 | 'http://[::]:22/', 14 | 'http://0000::1:80', 15 | 'http://0000::1:25', 16 | 'http://0000::1:22', 17 | 'http://0000::1:3128', 18 | 'http://localtest.me', 19 | 'http://customer1.app.localhost.my.company.127.0.0.1.nip.io', 20 | 'http://mail.ebc.apple.com', 21 | 'http://spoofed.burpcollaborator.net', 22 | 'http://127.127.127.127', 23 | 'http://127.0.1.3', 24 | 'http://127.0.0.0', 25 | 'http://0177.0.0.1', 26 | 'http://2130706433', 27 | 'http://3232235521', 28 | 'http://3232235777', 29 | 'http://[0:0:0:0:0:ffff:127.0.0.1]', 30 | 'http://0', 31 | 'http://127.1', 32 | 'http://127.0.1', 33 | 'http://127.1.1.1:80@127.2.2.2:80', 34 | 'http://127.1.1.1:80@@127.2.2.2:80', 35 | 'http://127.1.1.1:80:@@127.2.2.2:80', 36 | 'http://127.1.1.1:80#@127.2.2.2:80', 37 | 'http://169.254.169.254', 38 | 'http://169.254.169.254.xip.io', 39 | 'http://1ynrnhl.xip.io', 40 | 'http://www.owasp.org.1ynrnhl.xip.io', 41 | 'http://425.510.425.510', 42 | 'http://2852039166', 43 | 'http://7147006462', 44 | 'http://0xA9.0xFE.0xA9.0xFE', 45 | 'http://0xA9FEA9FE', 46 | 'http://0x41414141A9FEA9FE', 47 | 'http://0251.0376.0251.0376', 48 | 'http://0251.00376.000251.0000376', 49 | 'http://169.254.169.254/latest/meta-data/hostname', 50 | 'https://A.127.0.0.1.1time.10.0.0.1.1time.repeat.8f058b82-4c39-4dfe-91f7-9b07bcd7fbd5.rebind.network', 51 | 'http://[::]:22/', 52 | 'http://[::]:25/', 53 | 'http://[::]:80', 54 | 'http://[0:0:0:0:0:ffff:127.0.0.1]', 55 | 'http://0.0.0.0:22', 56 | 'http://0.0.0.0:443', 57 | 'http://0.0.0.0:80', 58 | 'http://127.0.0.1:22', 59 | 'http://127.0.0.1:443', 60 | 'http://127.0.0.1:80', 61 | 'http://425.510.425.510', 62 | 'http://mail.ebc.apple.com', 63 | 'http://metadata.nicob.net', 64 | 'http://0177.0.0.1', 65 | 'http://127.0.0.0', 66 | 'http://127.0.1.3', 67 | 'http://127.1.1.1:80:@@127.2.2.2:80', 68 | 'http://127.1.1.1:80@@127.2.2.2:80', 69 | 'http://127.1.1.1:80@127.2.2.2:80', 70 | 'http://127.1.1.1:80#@127.2.2.2:80', 71 | 'http://127.127.127.127', 72 | 'http://169.254.169.254', 73 | 'http://169.254.169.254/latest/meta-data/hostname', 74 | 'http://0', 75 | 'http://0000::1:22', 76 | 'http://0000::1:25', 77 | 'http://0000::1:3128', 78 | 'http://0000::1:80', 79 | 'http://0251.00376.000251.0000376', 80 | 'http://0251.0376.0251.0376', 81 | 'http://0x41414141A9FEA9FE', 82 | 'http://0xA9.0xFE.0xA9.0xFE', 83 | 'http://0xA9FEA9FE', 84 | 'http://127.0.1', 85 | 'http://127.1', 86 | 'http://169.254.169.254.xip.io', 87 | 'http://1ynrnhl.xip.io', 88 | 'http://2130706433', 89 | 'http://2852039166', 90 | 'http://3232235521', 91 | 'http://3232235777', 92 | 'http://7147006462', 93 | 'http://customer1.app.localhost.my.company.127.0.0.1.nip.io', 94 | 'http://localhost:+11211aaa', 95 | 'http://localhost:00011211aaaa', 96 | 'http://localhost:22', 97 | 'http://localhost:443', 98 | 'http://localhost:80', 99 | 'http://localtest.me', 100 | ]; 101 | 102 | module.exports = blockedUrls; 103 | -------------------------------------------------------------------------------- /test/index.test.js: -------------------------------------------------------------------------------- 1 | const http = require('http'); 2 | const https = require('https'); 3 | const axios = require('axios'); 4 | const expect = require('chai').expect; 5 | 6 | const ssrfFilter = require('../lib/index.js'); 7 | const {requestFilterHandler} = require('../lib/index.js'); 8 | 9 | const blockedUrls = require('./fixtures/blockedUrls.js'); 10 | const allowedUrls = require('./fixtures/allowedUrls.js'); 11 | 12 | describe('SSRF Filtering', () => { 13 | let httpAgent; 14 | let httpsAgent; 15 | 16 | before(() => { 17 | httpAgent = new http.Agent(); 18 | httpsAgent = new https.Agent(); 19 | }); 20 | 21 | describe('ssrfFilter Blocked', () => { 22 | blockedUrls.forEach((url) => { 23 | it(url, async () => { 24 | let check = 0; 25 | 26 | const response = await axios 27 | .get(url, { 28 | httpAgent: ssrfFilter(url), 29 | httpsAgent: ssrfFilter(url), 30 | }) 31 | .then((response) => { 32 | check = 1; 33 | }) 34 | .catch((error) => { 35 | check = 0; 36 | }) 37 | .then(() => { 38 | return check; 39 | }); 40 | 41 | expect(response).to.equal(0); 42 | }); 43 | }); 44 | }); 45 | 46 | describe('ssrfFilter Allowed', () => { 47 | allowedUrls.forEach((url) => { 48 | it(url, async () => { 49 | let check = 0; 50 | 51 | const response = await axios 52 | .get(url, { 53 | httpAgent: ssrfFilter(url), 54 | httpsAgent: ssrfFilter(url), 55 | }) 56 | .then((response) => { 57 | check = 1; 58 | }) 59 | .catch((error) => { 60 | check = 0; 61 | }) 62 | .then(() => { 63 | return check; 64 | }); 65 | 66 | expect(response).to.equal(1); 67 | }); 68 | }); 69 | }); 70 | 71 | describe('ssrfFilter DNS Rebinding', () => { 72 | it('With rebind.it: ', async function () { 73 | let check = 0; 74 | const rebindingUrl = 'http://s-35.185.206.165-127.0.0.1-' + new Date().valueOf() + '-rr-e.d.rebind.it'; 75 | this._runnable.title = this._runnable.title + rebindingUrl; 76 | 77 | const response = await axios 78 | .get(rebindingUrl, { 79 | httpAgent: ssrfFilter(rebindingUrl), 80 | httpsAgent: ssrfFilter(rebindingUrl), 81 | }) 82 | .then((response) => { 83 | check = 1; 84 | }) 85 | .catch((error) => { 86 | if (error.message === 'Request failed with status code 400') { 87 | check = 1; 88 | } else { 89 | check = 0; 90 | } 91 | }) 92 | .then(() => { 93 | return check; 94 | }); 95 | 96 | expect(response).to.equal(1); 97 | }); 98 | }); 99 | 100 | describe('requestFilterHandler Blocked', () => { 101 | blockedUrls.forEach((url) => { 102 | it(`${url} is Blocked`, async () => { 103 | let check = 0; 104 | 105 | const response = await axios 106 | .get(url, { 107 | httpAgent: requestFilterHandler(httpAgent), 108 | httpsAgent: requestFilterHandler(httpsAgent), 109 | }) 110 | .then((response) => { 111 | check = 1; 112 | }) 113 | .catch((error) => { 114 | check = 0; 115 | }) 116 | .then(() => { 117 | return check; 118 | }); 119 | 120 | expect(response).to.equal(0); 121 | }); 122 | }); 123 | }); 124 | 125 | describe('requestFilterHandler Allowed', () => { 126 | allowedUrls.forEach((url) => { 127 | it(`${url} is Allowed`, async () => { 128 | let check = 0; 129 | 130 | const response = await axios 131 | .get(url, { 132 | httpAgent: requestFilterHandler(httpAgent), 133 | httpsAgent: requestFilterHandler(httpsAgent), 134 | }) 135 | .then((response) => { 136 | check = 1; 137 | }) 138 | .catch((error) => { 139 | check = 0; 140 | }) 141 | .then(() => { 142 | return check; 143 | }); 144 | 145 | expect(response).to.equal(1); 146 | }); 147 | }); 148 | }); 149 | }); 150 | --------------------------------------------------------------------------------