Compare commits
1 Commits
main
...
chore/HTTP
| Author | SHA1 | Date |
|---|---|---|
|
|
e497630714 |
|
|
@ -3,8 +3,7 @@ import axios, { AxiosRequestConfig, Method, ResponseType } from 'axios'
|
|||
import FormData from 'form-data'
|
||||
import * as querystring from 'querystring'
|
||||
import { getCredentialData, getCredentialParam } from '../../../src/utils'
|
||||
import * as ipaddr from 'ipaddr.js'
|
||||
import dns from 'dns/promises'
|
||||
import { checkDenyList } from '../../../src/httpSecurity'
|
||||
|
||||
class HTTP_Agentflow implements INode {
|
||||
label: string
|
||||
|
|
@ -232,44 +231,6 @@ class HTTP_Agentflow implements INode {
|
|||
]
|
||||
}
|
||||
|
||||
private isDeniedIP(ip: string, denyList: string[]): void {
|
||||
const parsedIp = ipaddr.parse(ip)
|
||||
for (const entry of denyList) {
|
||||
if (entry.includes('/')) {
|
||||
try {
|
||||
const [range, _] = entry.split('/')
|
||||
const parsedRange = ipaddr.parse(range)
|
||||
if (parsedIp.kind() === parsedRange.kind()) {
|
||||
if (parsedIp.match(ipaddr.parseCIDR(entry))) {
|
||||
throw new Error('Access to this host is denied by policy.')
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error(`isDeniedIP: ${error}`)
|
||||
}
|
||||
} else if (ip === entry) throw new Error('Access to this host is denied by policy.')
|
||||
}
|
||||
}
|
||||
|
||||
private async checkDenyList(url: string) {
|
||||
const httpDenyListString: string | undefined = process.env.HTTP_DENY_LIST
|
||||
if (!httpDenyListString) return url
|
||||
const httpDenyList = httpDenyListString.split(',').map((ip) => ip.trim())
|
||||
|
||||
const urlObj = new URL(url)
|
||||
|
||||
const hostname = urlObj.hostname
|
||||
|
||||
if (ipaddr.isValid(hostname)) {
|
||||
this.isDeniedIP(hostname, httpDenyList)
|
||||
} else {
|
||||
const addresses = await dns.lookup(hostname, { all: true })
|
||||
for (const address of addresses) {
|
||||
this.isDeniedIP(address.address, httpDenyList)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async run(nodeData: INodeData, _: string, options: ICommonObject): Promise<any> {
|
||||
const method = nodeData.inputs?.method as 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'
|
||||
const url = nodeData.inputs?.url as string
|
||||
|
|
@ -332,7 +293,7 @@ class HTTP_Agentflow implements INode {
|
|||
// Build final URL with query parameters
|
||||
const finalUrl = queryString ? `${url}${url.includes('?') ? '&' : '?'}${queryString}` : url
|
||||
|
||||
await this.checkDenyList(finalUrl)
|
||||
await checkDenyList(finalUrl)
|
||||
|
||||
// Prepare request config
|
||||
const requestConfig: AxiosRequestConfig = {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { z } from 'zod'
|
||||
import fetch from 'node-fetch'
|
||||
import { DynamicStructuredTool } from '../OpenAPIToolkit/core'
|
||||
import { checkDenyList } from '../../../src/httpSecurity'
|
||||
|
||||
export const desc = `Use this when you need to execute a DELETE request to remove data from a website.`
|
||||
|
||||
|
|
@ -165,6 +166,9 @@ export class RequestsDeleteTool extends DynamicStructuredTool {
|
|||
finalUrl = url.toString()
|
||||
}
|
||||
|
||||
// Check if URL is allowed by security policy
|
||||
await checkDenyList(finalUrl)
|
||||
|
||||
try {
|
||||
const res = await fetch(finalUrl, {
|
||||
method: 'DELETE',
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { z } from 'zod'
|
||||
import fetch from 'node-fetch'
|
||||
import { DynamicStructuredTool } from '../OpenAPIToolkit/core'
|
||||
import { checkDenyList } from '../../../src/httpSecurity'
|
||||
|
||||
export const desc = `Use this when you need to execute a GET request to get data from a website.`
|
||||
|
||||
|
|
@ -165,6 +166,9 @@ export class RequestsGetTool extends DynamicStructuredTool {
|
|||
finalUrl = url.toString()
|
||||
}
|
||||
|
||||
// Check if URL is allowed by security policy
|
||||
await checkDenyList(finalUrl)
|
||||
|
||||
try {
|
||||
const res = await fetch(finalUrl, {
|
||||
headers: requestHeaders
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { z } from 'zod'
|
||||
import fetch from 'node-fetch'
|
||||
import { DynamicStructuredTool } from '../OpenAPIToolkit/core'
|
||||
import { checkDenyList } from '../../../src/httpSecurity'
|
||||
|
||||
export const desc = `Use this when you want to execute a POST request to create or update a resource.`
|
||||
|
||||
|
|
@ -126,6 +127,9 @@ export class RequestsPostTool extends DynamicStructuredTool {
|
|||
...this.headers
|
||||
}
|
||||
|
||||
// Check if URL is allowed by security policy
|
||||
await checkDenyList(inputUrl)
|
||||
|
||||
const res = await fetch(inputUrl, {
|
||||
method: 'POST',
|
||||
headers: requestHeaders,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { z } from 'zod'
|
||||
import fetch from 'node-fetch'
|
||||
import { DynamicStructuredTool } from '../OpenAPIToolkit/core'
|
||||
import { checkDenyList } from '../../../src/httpSecurity'
|
||||
|
||||
export const desc = `Use this when you want to execute a PUT request to update or replace a resource.`
|
||||
|
||||
|
|
@ -126,6 +127,9 @@ export class RequestsPutTool extends DynamicStructuredTool {
|
|||
...this.headers
|
||||
}
|
||||
|
||||
// Check if URL is allowed by security policy
|
||||
await checkDenyList(inputUrl)
|
||||
|
||||
const res = await fetch(inputUrl, {
|
||||
method: 'PUT',
|
||||
headers: requestHeaders,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,52 @@
|
|||
import * as ipaddr from 'ipaddr.js'
|
||||
import dns from 'dns/promises'
|
||||
|
||||
/**
|
||||
* Checks if an IP address is in the deny list
|
||||
* @param ip - IP address to check
|
||||
* @param denyList - Array of denied IP addresses/CIDR ranges
|
||||
* @throws Error if IP is in deny list
|
||||
*/
|
||||
export function isDeniedIP(ip: string, denyList: string[]): void {
|
||||
const parsedIp = ipaddr.parse(ip)
|
||||
for (const entry of denyList) {
|
||||
if (entry.includes('/')) {
|
||||
try {
|
||||
const [range, _] = entry.split('/')
|
||||
const parsedRange = ipaddr.parse(range)
|
||||
if (parsedIp.kind() === parsedRange.kind()) {
|
||||
if (parsedIp.match(ipaddr.parseCIDR(entry))) {
|
||||
throw new Error('Access to this host is denied by policy.')
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error(`isDeniedIP: ${error}`)
|
||||
}
|
||||
} else if (ip === entry) {
|
||||
throw new Error('Access to this host is denied by policy.')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a URL is allowed based on HTTP_DENY_LIST environment variable
|
||||
* @param url - URL to check
|
||||
* @throws Error if URL hostname resolves to a denied IP
|
||||
*/
|
||||
export async function checkDenyList(url: string): Promise<void> {
|
||||
const httpDenyListString: string | undefined = process.env.HTTP_DENY_LIST
|
||||
if (!httpDenyListString) return
|
||||
|
||||
const httpDenyList = httpDenyListString.split(',').map((ip) => ip.trim())
|
||||
const urlObj = new URL(url)
|
||||
const hostname = urlObj.hostname
|
||||
|
||||
if (ipaddr.isValid(hostname)) {
|
||||
isDeniedIP(hostname, httpDenyList)
|
||||
} else {
|
||||
const addresses = await dns.lookup(hostname, { all: true })
|
||||
for (const address of addresses) {
|
||||
isDeniedIP(address.address, httpDenyList)
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue