Skip to content

fix:ssrf & code refactor #412

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
May 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Changelog

## 2.9.4 - 2024-05-07
## 2.9.4 - 2024-05-17
fix: Resolve SSRF vulnerability in request handling
feat: Added new API endpoints
- Added support for `addBankAccount`, `deleteBankAccount`, `requestEligibilityCheck` & `fetchEligibility` on customer
- Added support for [Dispute](https://razorpay.com/docs/api/disputes/)
Expand Down
56 changes: 23 additions & 33 deletions lib/api.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict'

const request = require('request-promise')
const axios = require('axios').default
const nodeify = require('./utils/nodeify')
const {
isNonNullObject
Expand Down Expand Up @@ -33,19 +33,18 @@ function getValidHeaders (headers) {

function normalizeError(err) {
throw {
statusCode: err.statusCode,
error: err.error.error
statusCode: err.response.status,
error: err.response.data.error
}
}

class API {
constructor(options) {
this.rq = request.defaults({
baseUrl: options.hostUrl,
json: true,
this.rq = axios.create({
baseURL: options.hostUrl,
auth: {
user: options.key_id,
pass: options.key_secret
username: options.key_id,
password: options.key_secret
},
headers: Object.assign(
{'User-Agent': options.ua},
Expand All @@ -61,48 +60,39 @@ class API {
}

get(params, cb) {
return nodeify(this.rq.get({
url: this.getEntityUrl(params),
qs: params.data,
return nodeify(this.rq.get(this.getEntityUrl(params), {
params: params.data
}).catch(normalizeError), cb)
}

post(params, cb) {
let request = {
url: this.getEntityUrl(params),
body: params.data
};
return nodeify(this.rq.post(request).catch(normalizeError), cb);
return nodeify(this.rq.post(this.getEntityUrl(params), params.data)
.catch(normalizeError), cb);
}

// postFormData method for file uploads.
postFormData(params, cb){
let request = {
url: this.getEntityUrl(params),
formData: params.formData
};
return nodeify(this.rq.post(request).catch(normalizeError), cb);
return nodeify(this.rq.post(this.getEntityUrl(params), params.formData, {
'headers': {
'Content-Type': 'multipart/form-data'
}
})
.catch(normalizeError), cb);
}

put(params, cb) {
return nodeify(this.rq.put({
url: this.getEntityUrl(params),
body: params.data
}).catch(normalizeError), cb)
return nodeify(this.rq.put(this.getEntityUrl(params), params.data)
.catch(normalizeError), cb);
}

patch(params, cb) {
let request = {
url: this.getEntityUrl(params),
body: params.data
};
return nodeify(this.rq.patch(request).catch(normalizeError), cb);
return nodeify(this.rq.patch(this.getEntityUrl(params), params.data)
.catch(normalizeError), cb);
}

delete(params, cb) {
return nodeify(this.rq.delete({
url: this.getEntityUrl(params)
}).catch(normalizeError), cb)
return nodeify(this.rq.delete(this.getEntityUrl(params))
.catch(normalizeError), cb)
}
}

Expand Down
5 changes: 4 additions & 1 deletion lib/resources/accounts.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,13 @@ module.exports = function (api) {
},

uploadAccountDoc(accountId, params, callback) {
let {file, ...rest} = params
return api.postFormData({
version: 'v2',
url: `${BASE_URL}/${accountId}/documents`,
formData: params
formData: {
file: file.value, ...rest
}
}, callback);
},

Expand Down
3 changes: 1 addition & 2 deletions lib/resources/addons.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
* DOCS: https://razorpay.com/docs/subscriptions/api/
*/

const Promise = require("promise"),
{ normalizeDate } = require('../utils/razorpay-utils');
const { normalizeDate } = require('../utils/razorpay-utils');

module.exports = function (api) {

Expand Down
5 changes: 4 additions & 1 deletion lib/resources/documents.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@ module.exports = function (api) {

return {
create(params, callback) {
let {file, ...rest} = params
return api.postFormData({
url: `${BASE_URL}`,
formData: params
formData: {
file: file.value, ...rest
}
}, callback);
},

Expand Down
3 changes: 1 addition & 2 deletions lib/resources/invoices.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
* DOCS: https://razorpay.com/docs/invoices/
*/

const Promise = require("promise"),
{ normalizeDate } = require('../utils/razorpay-utils');
const { normalizeDate } = require('../utils/razorpay-utils');

module.exports = function invoicesApi (api) {

Expand Down
3 changes: 1 addition & 2 deletions lib/resources/paymentLink.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
* DOCS: https://razorpay.com/docs/payment-links/
*/

const Promise = require("promise"),
{ normalizeDate, normalizeNotes } = require('../utils/razorpay-utils');
const { normalizeDate } = require('../utils/razorpay-utils');

module.exports = function paymentLinkApi (api) {

Expand Down
2 changes: 0 additions & 2 deletions lib/resources/payments.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
'use strict'

const Promise = require("promise");

const { normalizeDate } = require('../utils/razorpay-utils')

const ID_REQUIRED_MSG = '`payment_id` is mandatory',
Expand Down
3 changes: 1 addition & 2 deletions lib/resources/plans.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
* DOCS: https://razorpay.com/docs/subscriptions/api/
*/

const Promise = require("promise"),
{ normalizeDate } = require('../utils/razorpay-utils');
const { normalizeDate } = require('../utils/razorpay-utils');

module.exports = function plansApi (api) {

Expand Down
5 changes: 4 additions & 1 deletion lib/resources/stakeholders.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,13 @@ module.exports = function (api) {
},

uploadStakeholderDoc(accountId, stakeholderId, params, callback) {
let {file, ...rest} = params
return api.postFormData({
version: 'v2',
url: `${BASE_URL}/${accountId}/stakeholders/${stakeholderId}/documents`,
formData: params
formData: {
file: file.value, ...rest
}
}, callback);
},

Expand Down
3 changes: 1 addition & 2 deletions lib/resources/subscriptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
* DOCS: https://razorpay.com/docs/subscriptions/api/
*/

const Promise = require("promise"),
{ normalizeDate } = require('../utils/razorpay-utils');
const { normalizeDate } = require('../utils/razorpay-utils');

module.exports = function subscriptionsApi (api) {

Expand Down
1 change: 0 additions & 1 deletion lib/resources/virtualAccounts.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"use strict";

const Promise = require("promise");
const { normalizeDate, normalizeNotes } = require('../utils/razorpay-utils');

const BASE_URL = '/virtual_accounts',
Expand Down
9 changes: 5 additions & 4 deletions lib/utils/nodeify.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
'use strict'

const nodeify = (promise, cb) => {

if (!cb) {
return promise
return promise.then((response)=> response.data)
}

return promise.then((response) => {
cb(null, response)
return promise.then((response) => {
cb(null, response.data)
}).catch((error) => {
cb(error, null)
})
Expand Down
Loading