This is an automated email from the ASF dual-hosted git repository.
dongjoon pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/spark-kubernetes-operator.git
The following commit(s) were added to refs/heads/main by this push:
new fea5481 [SPARK-55192] Improve HTTP response security
fea5481 is described below
commit fea548118dc4e7daf192595e20cebd8fd5bc12c3
Author: Dongjoon Hyun <[email protected]>
AuthorDate: Mon Jan 26 16:58:07 2026 +0900
[SPARK-55192] Improve HTTP response security
### What changes were proposed in this pull request?
This PR aims to improve HTTP response security like Apache Spark.
- https://github.com/apache/spark/pull/19419
### Why are the changes needed?
To improve HTTP response by
1. Adding an explicit default handler to generate the response consistently
like (2).
2. Adding a set of default headers.
- Use `text/plain` instead of `text/html` for `Content-Type`
- Disable cache by `Cache-control: no-cache, no-store, must-revalidate`
- Disable sniffing by `X-content-type-options: nosniff`
- Disable resource loading by `Content-security-policy: default-src
'none'`
**BEFORE**
```
$ curl -vv http://localhost:19091/
* Host localhost:19091 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
* Trying [::1]:19091...
* Connected to localhost (::1) port 19091
> GET / HTTP/1.1
> Host: localhost:19091
> User-Agent: curl/8.7.1
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 404 Not Found
< Content-Length: 50
< Content-Type: text/html
< Connection: close
<
* Closing connection
<h1>404 Not Found</h1>No context found for request%
```
**AFTER**
```
$ curl -vv http://localhost:19091/
* Host localhost:19091 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
* Trying [::1]:19091...
* Connected to localhost (::1) port 19091
> GET / HTTP/1.1
> Host: localhost:19091
> User-Agent: curl/8.7.1
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 404 Not Found
< X-frame-options: DENY
< Date: Mon, 26 Jan 2026 07:32:29 GMT
< Content-security-policy: default-src 'none'
< Transfer-encoding: chunked
< Content-type: text/plain; charset=utf-8
< X-content-type-options: nosniff
< Cache-control: no-cache, no-store, must-revalidate
<
* Connection #0 to host localhost left intact
```
### Does this PR introduce _any_ user-facing change?
No behavior change excepts the read-only HTTP responses.
### How was this patch tested?
Manual review.
### Was this patch authored or co-authored using generative AI tooling?
Yes (`Opus 4.5` on `Claude Code v2.1.5`)
Closes #472 from dongjoon-hyun/SPARK-55192.
Authored-by: Dongjoon Hyun <[email protected]>
Signed-off-by: Dongjoon Hyun <[email protected]>
---
.../spark/k8s/operator/metrics/PrometheusPullModelHandler.java | 4 ++--
.../java/org/apache/spark/k8s/operator/probe/ProbeService.java | 8 ++++++++
.../main/java/org/apache/spark/k8s/operator/utils/ProbeUtil.java | 8 +++++++-
3 files changed, 17 insertions(+), 3 deletions(-)
diff --git
a/spark-operator/src/main/java/org/apache/spark/k8s/operator/metrics/PrometheusPullModelHandler.java
b/spark-operator/src/main/java/org/apache/spark/k8s/operator/metrics/PrometheusPullModelHandler.java
index 8b723ed..6442d7f 100644
---
a/spark-operator/src/main/java/org/apache/spark/k8s/operator/metrics/PrometheusPullModelHandler.java
+++
b/spark-operator/src/main/java/org/apache/spark/k8s/operator/metrics/PrometheusPullModelHandler.java
@@ -93,7 +93,7 @@ public class PrometheusPullModelHandler extends
PrometheusServlet implements Htt
exchange,
HTTP_OK,
formatMetricsSnapshot(),
- Map.of("Content-Type", List.of("text/plain;version=0.0.4")));
+ Map.of("Content-Type", List.of("text/plain; charset=utf-8;
version=0.0.4")));
} else {
HttpServletRequest httpServletRequest = null;
String value = getMetricsSnapshot(httpServletRequest);
@@ -101,7 +101,7 @@ public class PrometheusPullModelHandler extends
PrometheusServlet implements Htt
exchange,
HTTP_OK,
String.join("\n", filterNonEmptyRecords(value)),
- Map.of("Content-Type", List.of("text/plain;version=0.0.4")));
+ Map.of("Content-Type", List.of("text/plain; charset=utf-8;
version=0.0.4")));
}
}
diff --git
a/spark-operator/src/main/java/org/apache/spark/k8s/operator/probe/ProbeService.java
b/spark-operator/src/main/java/org/apache/spark/k8s/operator/probe/ProbeService.java
index 9bcd6bb..0fe00ff 100644
---
a/spark-operator/src/main/java/org/apache/spark/k8s/operator/probe/ProbeService.java
+++
b/spark-operator/src/main/java/org/apache/spark/k8s/operator/probe/ProbeService.java
@@ -19,7 +19,9 @@
package org.apache.spark.k8s.operator.probe;
+import static java.net.HttpURLConnection.HTTP_NOT_FOUND;
import static
org.apache.spark.k8s.operator.config.SparkOperatorConf.OPERATOR_PROBE_PORT;
+import static org.apache.spark.k8s.operator.utils.ProbeUtil.sendMessage;
import java.io.IOException;
import java.net.InetSocketAddress;
@@ -56,6 +58,12 @@ public class ProbeService {
}
server.createContext(READYZ, new ReadinessProbe(operators));
server.createContext(HEALTHZ, new HealthProbe(operators,
sentinelManagers));
+ server.createContext(
+ "/",
+ exchange -> {
+ sendMessage(exchange, HTTP_NOT_FOUND, "");
+ exchange.close();
+ });
server.setExecutor(executor);
}
diff --git
a/spark-operator/src/main/java/org/apache/spark/k8s/operator/utils/ProbeUtil.java
b/spark-operator/src/main/java/org/apache/spark/k8s/operator/utils/ProbeUtil.java
index 3677f42..99f0291 100644
---
a/spark-operator/src/main/java/org/apache/spark/k8s/operator/utils/ProbeUtil.java
+++
b/spark-operator/src/main/java/org/apache/spark/k8s/operator/utils/ProbeUtil.java
@@ -66,8 +66,14 @@ public final class ProbeUtil {
throws IOException {
try (OutputStream outputStream = httpExchange.getResponseBody()) {
byte[] bytes = message.getBytes(StandardCharsets.UTF_8);
+ Headers responseHeaders = httpExchange.getResponseHeaders();
+ responseHeaders.set("Cache-Control", "no-cache, no-store,
must-revalidate");
+ responseHeaders.set("Content-Security-Policy", "default-src 'none'");
+ responseHeaders.set("Content-Type", "text/plain; charset=utf-8");
+ responseHeaders.set("X-Content-Type-Options", "nosniff");
+ responseHeaders.set("X-Frame-Options", "DENY");
+ // Add any additional headers if provided
if (headers != null && !headers.isEmpty()) {
- Headers responseHeaders = httpExchange.getResponseHeaders();
responseHeaders.putAll(headers);
}
httpExchange.sendResponseHeaders(code, bytes.length);
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]