Skip to content

Commit 2d8cceb

Browse files
Merge pull request #1913 from swagger-api/ft/add-documentation-for-safe-url-resolver
Add documentation for swagger-parser-safe-url-resolver
2 parents ba13af5 + f543757 commit 2d8cceb

File tree

1 file changed

+71
-0
lines changed
  • modules/swagger-parser-safe-url-resolver

1 file changed

+71
-0
lines changed
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# Swagger Parser Safe URL Resolver
2+
3+
The `swagger-parser-safe-url-resolver` is a library used for verifying that the hostname of URLs does not resolve to a private/restricted IPv4/IPv6 address range.
4+
This library can be used in services that deal with user-submitted URLs that get fetched (like in swagger-parser when resolving external URL $refs) to protect against Server-Side Request Forgery and DNS rebinding attacks.
5+
6+
## How does it work?
7+
The main class of the package is the `PermittedUrlsChecker` which has one method: `verify(String url)`.
8+
This method takes in a string URL and performs the following steps:
9+
10+
1. Gets the hostname portion from the URL
11+
2. Resolves the hostname to an IP address
12+
3. Checks if that IP address is in a private/restricted IP address range (and throws an exception if it is)
13+
4. Returns a `ResolvedUrl` object which contains
14+
4.1. `String url` where the original URL has the hostname replaced with the IP address
15+
4.2. A `String hostHeader` which contains the hostname from the original URL to be added as a host header
16+
17+
This behavior can also be customized with the allowlist and denylist in the constructor, whereby:
18+
19+
- An entry in the allowlist will allow the URL to pass even if it resolves to a private/restricted IP address
20+
- An entry in the denylist will throw an exception even when the URL resolves to a public IP address
21+
22+
## Installation
23+
Add the following to you `pom.xml` file under `dependencies`
24+
```xml
25+
<dependency>
26+
<groupId>io.swagger.parser.v3</groupId>
27+
<artifactId>swagger-parser-safe-url-resolver</artifactId>
28+
// version of swagger-parser being used
29+
<version>2.1.14</version>
30+
</dependency>
31+
```
32+
33+
## Example usage
34+
35+
```java
36+
import io.swagger.v3.parser.urlresolver.PermittedUrlsChecker;
37+
import io.swagger.v3.parser.urlresolver.exceptions.HostDeniedException;
38+
import io.swagger.v3.parser.urlresolver.models.ResolvedUrl;
39+
40+
import java.util.List;
41+
42+
public class Main {
43+
public static void main() {
44+
List<String> allowlist = List.of("mysite.local");
45+
List<String> denylist = List.of("*.example.com:443");
46+
var checker = new PermittedUrlsChecker(allowlist, denylist);
47+
48+
try {
49+
// Will throw a HostDeniedException as `localhost`
50+
// resolves to local IP and is not in allowlist
51+
checker.verify("http://localhost/example");
52+
53+
// Will return a ResolvedUrl if `github.com`
54+
// resolves to a public IP
55+
checker.verify("https://github.com/swagger-api/swagger-parser");
56+
57+
// Will throw a HostDeniedException as `*.example.com` is
58+
// explicitly deny listed, even if it resolves to public IP
59+
checker.verify("https://subdomain.example.com/somepage");
60+
61+
// Will return a `ResolvedUrl` as `mysite.local`
62+
// is explicitly allowlisted
63+
ResolvedUrl resolvedUrl = checker.verify("http://mysite.local/example");
64+
System.out.println(resolvedUrl.getUrl()); // "http://127.0.0.1/example"
65+
System.out.println(resolvedUrl.getHostHeader()); // "mysite.local"
66+
} catch (HostDeniedException e) {
67+
e.printStackTrace();
68+
}
69+
}
70+
}
71+
```

0 commit comments

Comments
 (0)