Commit 48ac053
fix(security): block Redis datasource from internal Appsmith Redis (GHSA-qhfj-g87x-m39w) (#41921)
## Summary
Closes
[GHSA-qhfj-g87x-m39w](GHSA-qhfj-g87x-m39w).
The Redis datasource plugin opened a Jedis connection to a
user-controlled host/port with no IP-class filtering, so a user with
datasource-create permission could point a Redis datasource at the
internal Appsmith Redis. The existing HTTP-side filter doesn't cover
Redis — Jedis uses the JVM's default resolver and bypasses the Reactor
Netty hook.
This PR also closes a DNS-rebinding TOCTOU on the same path and enforces
TLS certificate hostname verification for `rediss://` datasources (items
4 and 5 below).
## Changes
1. **Block Redis datasources from reaching the internal Appsmith
Redis.** `RedisPlugin.datasourceCreate` now consults a shared
`RestrictedHostFilter`. Blocks literal hostname / IP matches against
`APPSMITH_REDIS_URL` and `APPSMITH_REDIS_GIT_URL`, plus loopback /
link-local / cloud-metadata literals. Enforcement is connection-time
only — `PluginExecutor.validateDatasource` is documented format-only, so
host-policy belongs on the connection path. UX: Save succeeds, "Test
Datasource" rejects with `Host not allowed.`.
2. **Make SSRF protections always-on; rename `IN_DOCKER` to
`APPSMITH_DISABLE_SSRF_FILTER`.** The previous filter gated the loopback
/ link-local block on `IN_DOCKER=1`, which Appsmith's official Docker
image always sets — so users on documented deployment paths were already
getting this protection. This change closes the gap for unofficial
distributions (self-built images, bare-metal, etc.) and replaces a
poorly-named variable with one that actually describes what it does. The
most likely place to hit this is a development machine running the
server directly against `http://localhost:*` — set
`APPSMITH_DISABLE_SSRF_FILTER=true` to allow it.
3. **Extract `RestrictedHostFilter` from `WebClientUtils`.** Pure
refactor — the host-filter logic had already grown several non-HTTP call
sites and the class name had outgrown its scope.
4. **Close the DNS-rebinding TOCTOU on the Redis path (upgrade Jedis
3.3.0 → 5.2.0 + pin the resolved IP).** The create-time pre-check in (1)
and Jedis's own connection-time lookup resolved the hostname
independently, so a hostile resolver could return an allowed IP to the
check and the internal Redis IP to the driver. Jedis 5.2.0 (up from
3.3.0, which predated the API) allows injecting a `JedisSocketFactory`;
the new `RestrictedHostJedisSocketFactory` resolves once at connect
time, validates every resolved address, and connects directly to the
pinned IP — so the driver never re-resolves and the window is closed.
The create-time check stays as fast Save/Test UX and now logs the block
at WARN, tagged with the requesting user/org/trace (a useful
reconnaissance signal). Jedis is plugin-isolated (PF4J + shaded); the
server's own Redis runs on Lettuce and is untouched.
5. **Enforce TLS certificate hostname verification for `rediss://`
datasources.** Jedis 5.2.0 validates the certificate trust chain but
does not verify that the cert's SAN/CN matches the host (it only does so
by default in 7.5.0+), so a man-in-the-middle presenting any
CA-trusted-but-mismatched cert on the pinned IP would have been
accepted. The socket factory now sets the endpoint identification
algorithm to `HTTPS`, verifying against the configured hostname (we
connect to the pinned IP but hand the original hostname to the TLS layer
for SNI and verification). This was a pre-existing gap, not introduced
here; closing it now is low-risk because Redis TLS support is recent
(#41587, ~2026-03) and barely adopted, and chain validation was already
on — so only CA-trusted-but-mismatched certs and IP-addressed
`rediss://` (certs rarely carry IP SANs) are newly rejected.
6. **Housekeeping: drop dead `IN_DOCKER` references from Dockerfile /
deploy scripts / CI workflow.** No consumer left after the rename in
(2).
/ok-to-test tags="@tag.All"
## Test plan
- [x] CI green across all commits (Jedis 5.2.0 upgrade, socket factory,
TLS verification, logging).
- [x] Deploy preview: Redis datasource at \`localhost\` / in-cluster
Redis service DNS — Save accepted, Test rejected with \`Host not
allowed.\`. Legitimate external Redis works.
- [x] Connect-time SSRF rejection (the rebinding gate) covered by
`RedisPluginTest` (`socketFactory_blockedHost_failsAtConnectTime`). A
live end-to-end rebinding flip needs a changing resolver and was not
exercised on the DP (rbndr.us is unreachable from AWS).
- [x] Confirm the one existing `rediss://` user (Appsmith internal)
connects via a hostname matching its cert, now that hostname
verification is enforced.
- [x] Dev environment: confirm \`APPSMITH_DISABLE_SSRF_FILTER=true\`
unblocks \`http://localhost:*\` datasources during local development.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- This is an auto-generated comment: Cypress test results -->
> [!TIP]
> 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
> Workflow run:
<https://github.com/appsmithorg/appsmith/actions/runs/28840292682>
> Commit: c795905
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=28840292682&attempt=2"
target="_blank">Cypress dashboard</a>.
> Tags: `@tag.All`
> Spec:
> <hr>Tue, 07 Jul 2026 13:31:52 UTC
<!-- end of auto-generated comment: Cypress test results -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
## Release Notes
* **New Features**
* Added centralized SSRF/restricted host filtering with denylisting and
normalization.
* Enabled consistent enforcement across outbound web requests,
Elasticsearch DNS resolution, SMTP test-email, and Redis datasource
connections.
* Mitigated Redis DNS rebinding by validating once and pinning the
resolved address.
* **Bug Fixes**
* Blocked hosts now fail with a consistent “Host not allowed” error
across execution paths.
* **Tests**
* Added dedicated host/IP blocking test suite.
* Updated integration tests to explicitly control SSRF filtering
enablement and state restoration during runs.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>1 parent 7491d32 commit 48ac053
21 files changed
Lines changed: 1961 additions & 636 deletions
File tree
- .github/workflows
- app/server
- appsmith-interfaces/src
- main/java/com/appsmith/util
- test/java/com/appsmith
- external/connections
- util
- appsmith-plugins
- elasticSearchPlugin/src
- main/java/org/apache/http/impl/nio/client
- test/java/com/external/plugins
- graphqlPlugin/src/test/java/com/external/plugins
- redisPlugin
- src
- main/java/com/external/plugins
- test/java/com/external/plugins
- restApiPlugin/src/test/java/com/external/plugins
- appsmith-server/src
- main/java/com/appsmith/server
- configurations
- solutions/ce
- test/java/com/appsmith/server/solutions
- scripts
Lines changed: 0 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
328 | 328 | | |
329 | 329 | | |
330 | 330 | | |
331 | | - | |
332 | 331 | | |
333 | 332 | | |
334 | 333 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
4 | | - | |
5 | | - | |
6 | 4 | | |
7 | 5 | | |
8 | 6 | | |
| |||
Lines changed: 606 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 22 additions & 210 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
13 | | - | |
14 | 13 | | |
15 | 14 | | |
16 | 15 | | |
| |||
21 | 20 | | |
22 | 21 | | |
23 | 22 | | |
24 | | - | |
25 | 23 | | |
26 | 24 | | |
27 | 25 | | |
28 | 26 | | |
29 | 27 | | |
30 | | - | |
31 | | - | |
32 | 28 | | |
33 | | - | |
34 | | - | |
35 | | - | |
36 | 29 | | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
37 | 46 | | |
38 | 47 | | |
39 | 48 | | |
40 | | - | |
41 | | - | |
42 | | - | |
43 | | - | |
44 | | - | |
45 | | - | |
46 | 49 | | |
47 | 50 | | |
48 | 51 | | |
| |||
66 | 69 | | |
67 | 70 | | |
68 | 71 | | |
69 | | - | |
70 | | - | |
71 | | - | |
72 | | - | |
73 | | - | |
74 | | - | |
75 | | - | |
76 | | - | |
77 | | - | |
78 | | - | |
79 | | - | |
80 | | - | |
81 | | - | |
82 | | - | |
83 | | - | |
84 | | - | |
85 | | - | |
86 | | - | |
87 | | - | |
88 | | - | |
89 | | - | |
90 | | - | |
91 | | - | |
92 | | - | |
93 | | - | |
94 | | - | |
95 | | - | |
96 | | - | |
97 | | - | |
98 | | - | |
99 | | - | |
100 | 72 | | |
101 | 73 | | |
102 | 74 | | |
| |||
199 | 171 | | |
200 | 172 | | |
201 | 173 | | |
202 | | - | |
203 | | - | |
204 | | - | |
205 | | - | |
206 | | - | |
207 | | - | |
208 | | - | |
209 | | - | |
210 | | - | |
211 | | - | |
212 | | - | |
213 | | - | |
214 | | - | |
215 | | - | |
216 | | - | |
217 | | - | |
218 | | - | |
219 | | - | |
220 | | - | |
221 | | - | |
222 | | - | |
223 | | - | |
224 | | - | |
225 | | - | |
226 | | - | |
227 | | - | |
228 | | - | |
229 | | - | |
230 | | - | |
231 | | - | |
232 | | - | |
233 | | - | |
234 | | - | |
235 | | - | |
236 | | - | |
237 | | - | |
238 | | - | |
239 | | - | |
240 | | - | |
241 | | - | |
242 | | - | |
243 | | - | |
244 | | - | |
245 | | - | |
246 | | - | |
247 | | - | |
248 | | - | |
249 | | - | |
250 | | - | |
251 | | - | |
252 | | - | |
253 | | - | |
254 | 174 | | |
255 | 175 | | |
256 | 176 | | |
| |||
259 | 179 | | |
260 | 180 | | |
261 | 181 | | |
262 | | - | |
263 | | - | |
264 | | - | |
265 | | - | |
266 | | - | |
267 | | - | |
268 | | - | |
269 | | - | |
270 | | - | |
271 | | - | |
272 | | - | |
273 | | - | |
| 182 | + | |
| 183 | + | |
274 | 184 | | |
275 | 185 | | |
276 | 186 | | |
277 | | - | |
278 | | - | |
279 | | - | |
280 | | - | |
281 | | - | |
282 | | - | |
283 | | - | |
284 | | - | |
285 | | - | |
286 | | - | |
287 | | - | |
288 | | - | |
289 | | - | |
290 | | - | |
291 | | - | |
292 | | - | |
293 | | - | |
294 | | - | |
295 | | - | |
296 | | - | |
297 | | - | |
298 | | - | |
299 | | - | |
300 | | - | |
301 | | - | |
302 | | - | |
303 | | - | |
304 | | - | |
305 | | - | |
306 | | - | |
307 | | - | |
308 | | - | |
309 | | - | |
310 | | - | |
311 | | - | |
312 | | - | |
313 | | - | |
314 | | - | |
315 | | - | |
316 | | - | |
317 | | - | |
318 | | - | |
319 | | - | |
320 | | - | |
321 | | - | |
322 | | - | |
323 | | - | |
324 | | - | |
325 | | - | |
326 | | - | |
327 | | - | |
328 | | - | |
329 | | - | |
330 | | - | |
331 | | - | |
332 | | - | |
333 | | - | |
334 | | - | |
335 | | - | |
336 | | - | |
337 | | - | |
338 | | - | |
339 | | - | |
340 | | - | |
341 | | - | |
342 | | - | |
343 | | - | |
344 | | - | |
345 | | - | |
346 | | - | |
347 | | - | |
348 | | - | |
349 | | - | |
350 | | - | |
351 | | - | |
352 | | - | |
353 | | - | |
354 | | - | |
355 | | - | |
356 | | - | |
357 | | - | |
358 | | - | |
359 | | - | |
360 | | - | |
361 | | - | |
362 | | - | |
363 | | - | |
364 | | - | |
365 | | - | |
366 | | - | |
367 | | - | |
368 | | - | |
369 | | - | |
370 | | - | |
371 | | - | |
372 | | - | |
373 | | - | |
374 | | - | |
375 | 187 | | |
376 | 188 | | |
377 | 189 | | |
| |||
380 | 192 | | |
381 | 193 | | |
382 | 194 | | |
383 | | - | |
| 195 | + | |
384 | 196 | | |
385 | 197 | | |
386 | 198 | | |
| |||
392 | 204 | | |
393 | 205 | | |
394 | 206 | | |
395 | | - | |
| 207 | + | |
396 | 208 | | |
397 | 209 | | |
398 | 210 | | |
| |||
401 | 213 | | |
402 | 214 | | |
403 | 215 | | |
404 | | - | |
| 216 | + | |
405 | 217 | | |
406 | 218 | | |
407 | 219 | | |
| |||
415 | 227 | | |
416 | 228 | | |
417 | 229 | | |
418 | | - | |
| 230 | + | |
419 | 231 | | |
420 | 232 | | |
421 | 233 | | |
| |||
Lines changed: 3 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
39 | 39 | | |
40 | 40 | | |
41 | 41 | | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
42 | 45 | | |
43 | 46 | | |
44 | 47 | | |
| |||
0 commit comments