-
Notifications
You must be signed in to change notification settings - Fork 6
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
Only capture hostname when the request is not blocked because of SSRF #381
Changes from 3 commits
af6312f
048efd8
2eef0be
ef5ec27
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -83,10 +83,24 @@ function wrapDNSLookupCallback( | |
|
||
const context = getContext(); | ||
|
||
// This is set if this resolve is part of an outgoing request that we are inspecting | ||
const requestContext = RequestContextStorage.getStore(); | ||
|
||
let port: number | undefined; | ||
|
||
if (urlArg) { | ||
port = getPortFromURL(urlArg); | ||
} else if (requestContext) { | ||
port = requestContext.port; | ||
} | ||
|
||
if (context) { | ||
const matches = agent.getConfig().getEndpoints(context); | ||
|
||
if (matches.find((endpoint) => endpoint.forceProtectionOff)) { | ||
// Add to list of hostnames that the application is connecting to | ||
agent.onConnectHostname(hostname, port); | ||
|
||
// User disabled protection for this endpoint, we don't need to inspect the resolved IPs | ||
// Just call the original callback to allow the DNS lookup | ||
return callback(err, addresses, family); | ||
|
@@ -109,25 +123,20 @@ function wrapDNSLookupCallback( | |
} | ||
|
||
if (!context) { | ||
// Add to list of hostnames that the application is connecting to | ||
agent.onConnectHostname(hostname, port); | ||
|
||
// If there's no context, we can't check if the hostname is in the context | ||
// Just call the original callback to allow the DNS lookup | ||
return callback(err, addresses, family); | ||
} | ||
|
||
// This is set if this resolve is part of an outgoing request that we are inspecting | ||
const requestContext = RequestContextStorage.getStore(); | ||
|
||
let port: number | undefined; | ||
|
||
if (urlArg) { | ||
port = getPortFromURL(urlArg); | ||
} else if (requestContext) { | ||
port = requestContext.port; | ||
} | ||
|
||
const privateIP = resolvedIPAddresses.find(isPrivateIP); | ||
|
||
if (!privateIP) { | ||
// Add to list of hostnames that the application is connecting to | ||
agent.onConnectHostname(hostname, port); | ||
|
||
// If the hostname doesn't resolve to a private IP address, it's not an SSRF attack | ||
// Just call the original callback to allow the DNS lookup | ||
return callback(err, addresses, family); | ||
|
@@ -166,6 +175,9 @@ function wrapDNSLookupCallback( | |
} | ||
|
||
if (!found) { | ||
// Add to list of hostnames that the application is connecting to | ||
agent.onConnectHostname(hostname, port); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looking for a way to avoid the sprinkled Easy to forget when adding a new if statement here or there, right? undici & fetch const response = await fetch("url") When response is returned and the fetch call didn't throw, we know the request succeeded, can we maybe hook into the return value and call http/https module We could wrap the So I think we have no choice to use the DNS lookup indeed, instead of adding the logic in optionObj.lookup = inspectDNSLookupCalls(
nativeLookup,
agent,
module,
`${module}.request`,
url,
stackTraceCallingLocation
) as NonNullable<RequestOptions["lookup"]>; becomes optionObj.lookup = addHostnameToAgent(
agent,
inspectDNSLookupCalls(
nativeLookup,
agent,
module,
`${module}.request`,
url,
stackTraceCallingLocation
)
);
function addHostnameToAgent(agent: Agent, lookup: Function) {
return function addHostnameToAgent(...args: unknown[]) {
// see if DNS lookup succeeded
if (!error) {
agent.onConnectHostname(hostname, port);
}
}
} |
||
|
||
// If we can't find the hostname in the context, it's not an SSRF attack | ||
// Just call the original callback to allow the DNS lookup | ||
return callback(err, addresses, family); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A bit weird to have an assertion outside a test? Let's move that line?