Skip to content

Commit 732453c

Browse files
Potential fix for code scanning alert no. 70: Server-side request forgery
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: Marc <[email protected]>
1 parent 02d737b commit 732453c

File tree

1 file changed

+63
-0
lines changed

1 file changed

+63
-0
lines changed

integration-proxy/src/main/java/io/sentrius/sso/controllers/api/documents/DocumentRetrievalProxyController.java

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
import org.springframework.http.ResponseEntity;
1818
import org.springframework.web.bind.annotation.*;
1919

20+
import java.net.InetAddress;
21+
import java.net.URI;
22+
import java.net.URISyntaxException;
2023
import java.util.HashMap;
2124
import java.util.List;
2225
import java.util.Map;
@@ -62,6 +65,12 @@ public ResponseEntity<Map<String, Object>> retrieveDocument(
6265
.body(Map.of("error", "sourceUrl is required"));
6366
}
6467

68+
if (!isAllowedSourceUrl(sourceUrl)) {
69+
log.warn("Rejected document retrieval request to disallowed URL: {}", sourceUrl);
70+
return ResponseEntity.badRequest()
71+
.body(Map.of("error", "Invalid or disallowed sourceUrl"));
72+
}
73+
6574
@SuppressWarnings("unchecked")
6675
Map<String, String> options = (Map<String, String>) request.get("options");
6776
if (options == null) {
@@ -137,4 +146,58 @@ public ResponseEntity<Map<String, Object>> getSupportedSources(
137146
.body(Map.of("error", "Failed to get supported sources"));
138147
}
139148
}
149+
150+
/**
151+
* Validate that the provided sourceUrl is safe to use for outbound HTTP(S) requests.
152+
* This helps protect against server-side request forgery (SSRF).
153+
*/
154+
private boolean isAllowedSourceUrl(String sourceUrl) {
155+
try {
156+
URI uri = new URI(sourceUrl);
157+
158+
String scheme = uri.getScheme();
159+
if (scheme == null || (!"http".equalsIgnoreCase(scheme) && !"https".equalsIgnoreCase(scheme))) {
160+
return false;
161+
}
162+
163+
String host = uri.getHost();
164+
if (host == null || host.isEmpty()) {
165+
return false;
166+
}
167+
168+
InetAddress address = InetAddress.getByName(host);
169+
if (address.isAnyLocalAddress() || address.isLoopbackAddress()) {
170+
return false;
171+
}
172+
173+
byte[] ip = address.getAddress();
174+
int firstOctet = ip[0] & 0xFF;
175+
int secondOctet = ip[1] & 0xFF;
176+
177+
// 10.0.0.0/8
178+
if (firstOctet == 10) {
179+
return false;
180+
}
181+
// 172.16.0.0 – 172.31.255.255
182+
if (firstOctet == 172 && secondOctet >= 16 && secondOctet <= 31) {
183+
return false;
184+
}
185+
// 192.168.0.0/16
186+
if (firstOctet == 192 && secondOctet == 168) {
187+
return false;
188+
}
189+
// 169.254.0.0/16 (link-local)
190+
if (firstOctet == 169 && secondOctet == 254) {
191+
return false;
192+
}
193+
194+
return true;
195+
} catch (URISyntaxException e) {
196+
log.warn("Invalid sourceUrl syntax: {}", sourceUrl, e);
197+
return false;
198+
} catch (Exception e) {
199+
log.warn("Failed to validate sourceUrl: {}", sourceUrl, e);
200+
return false;
201+
}
202+
}
140203
}

0 commit comments

Comments
 (0)