ssrf-guard

Installation

Requirements

Picking your module

ssrf-guard v3.0.0 is split along HTTP-client boundaries — pick the module(s) matching what you actually use. Most consumers want just one.

=== “RestClient (Spring Boot 3.x default)”

```xml
<dependency>
    <groupId>kr.devslab</groupId>
    <artifactId>ssrf-guard</artifactId>
    <version>3.0.0</version>
</dependency>
```

The meta artifact pulls in `-core`, `-httpclient5`, and `-restclient` — equivalent to the entire v2.0.0 surface.

=== “RestTemplate”

```xml
<dependency>
    <groupId>kr.devslab</groupId>
    <artifactId>ssrf-guard-resttemplate</artifactId>
    <version>3.0.0</version>
</dependency>
```

Wires the same `ClientHttpRequestInterceptor` and `HttpComponentsClientHttpRequestFactory` onto Spring Boot's `RestTemplateBuilder`. Pull in `-restclient` too if you use both.

=== “WebClient (WebFlux)”

```xml
<dependency>
    <groupId>kr.devslab</groupId>
    <artifactId>ssrf-guard-webclient</artifactId>
    <version>3.0.0</version>
</dependency>
```

Wires an `ExchangeFilterFunction` onto the autoconfigured `WebClient.Builder`. Reactive — policy violations come back as `Mono.error(SsrfGuardException)`.

=== “Feign”

```xml
<dependency>
    <groupId>kr.devslab</groupId>
    <artifactId>ssrf-guard-feign</artifactId>
    <version>3.0.0</version>
</dependency>
```

Registers a `feign.RequestInterceptor` — Spring Cloud OpenFeign auto-applies it to every `@FeignClient`.

=== “Spring AI tool calls”

```xml
<dependency>
    <groupId>kr.devslab</groupId>
    <artifactId>ssrf-guard-springai</artifactId>
    <version>3.0.0</version>
</dependency>
```

Wraps every `ToolCallback` bean with URL-argument validation. The defining new SSRF surface — LLM agents that take a URL as a parameter and fetch it.

=== “Plain JDK HttpClient (no Spring)”

```xml
<dependency>
    <groupId>kr.devslab</groupId>
    <artifactId>ssrf-guard-jdkhttp</artifactId>
    <version>3.0.0</version>
</dependency>
```

Use directly:
```java
HttpClient safe = new SsrfGuardedHttpClient(HttpClient.newHttpClient(), urlPolicy);
```

=== “OkHttp (no Spring)”

```xml
<dependency>
    <groupId>kr.devslab</groupId>
    <artifactId>ssrf-guard-okhttp</artifactId>
    <version>3.0.0</version>
</dependency>
```

```java
OkHttpClient client = new OkHttpClient.Builder()
    .addInterceptor(new SsrfGuardOkHttpInterceptor(urlPolicy))
    .dns(new SsrfGuardOkHttpDns(hostPolicy, true))
    .build();
```

!!! tip “Latest version” Replace 3.0.0 with the latest from Maven Central.

!!! info “Coming from v2.0.0?” The kr.devslab:ssrf-guard coordinate still works — it’s a meta artifact that pulls in -core, -httpclient5, and -restclient. Most consumers can upgrade by changing the version and rebuilding. Direct imports of kr.devslab.ssrfguard.security.* need to be updated — see the v3.0.0 changelog for the package-rename mapping.

Minimal configuration

Whichever module you picked, the ssrf.guard.* keys are shared:

```yaml title=”application.yml” ssrf: guard: enabled: true # default — set to false to opt out suffixes: # at minimum, this — empty means “block everything” - api.partner.com - example.org


Without any whitelist entries the guard is in **fail-closed** mode — every outbound call gets `Host not allowed`. That's deliberate.

## Optional hardening (defaults are sane)

```yaml
ssrf:
  guard:
    reject-ip-literal-hosts: true    # default — block http://127.0.0.1, http://2130706433, etc.
    reject-user-info: true           # default — block https://user:pass@host/...
    block-private-networks: true     # default — filter loopback / RFC-1918 / link-local / metadata IPs at DNS time
    follow-redirects: true           # default — and re-validate every hop
    allowed-schemes: [https]         # tighter than the [http, https] default
    allowed-ports: [443]             # tighter than [-1, 80, 443]

Optional observability

Pulling in spring-boot-starter-actuator gets you Micrometer metrics for free:

ssrf_guard_blocked_total{reason="blocked_private_ip", scheme="http"} 42
ssrf_guard_allowed_total{scheme="https"} 13042

The metric tags are bounded (reason is an enum, scheme is http/https) so Prometheus / Datadog / CloudWatch ingest happily.

Verifying the install

For Spring Boot modules, the auto-config bean shows up in --debug output:

./gradlew bootRun --args='--debug' | grep -E 'SsrfGuard.*AutoConfiguration'

You should see at least one matched: line. Try a deliberately blocked URL — the response logs:

WARN  k.d.s.core.UrlPolicy : ssrf-guard: Host not allowed: evil.com (reason=blocked_host, scheme=https, host=evil.com)

Continue to the Quickstart to see the guard in action against a real partner API, or Security Model for the full threat-model writeup.