
OpenRewrite रेसिपी जो Spring Security हेडर सप्रेशन (CVE-2026-22732) का पता लगाती है और उसे ठीक करती है, Content-Length हेडर के दुरुपयोग की पहचान करके और तत्काल हेडर-लेखन कॉन्फ़िगरेशन उत्पन्न करके।
OpenRewrite रेसिपी जो CVE-2026-22732 के प्रति संवेदनशील कोड का पता लगाती है, जो एक Spring Security दोष है जहां तीन रिस्पॉन्स विधियों में से किसी एक के माध्यम से Content-Length सेट करने से Spring Security का OnCommittedResponseWrapper बायपास हो जाता है। क्योंकि रैपर हेडर को कभी नहीं देखता, onResponseCommitted() कभी फायर नहीं होता, और आलसी-जोड़े गए सुरक्षा हेडर (X-Frame-Options, X-Content-Type-Options, Cache-Control, आदि) चुपचाप हटा दिए जाते हैं।
वास्तविक ट्रिगर, संवेदनशील Spring Security 6.4.12 के साथ Spring Boot 3.4.3 / एम्बेडेड Tomcat के विरुद्ध पुष्टि किए गए:
रैपर-बायपासिंग ओवरलोड के माध्यम से Servlet Content-Length
response.setHeader("Content-Length", "42");
response.setIntHeader("Content-Length", 42);
response.addIntHeader("Content-Length", 42);
ये तीनों ओवरलोड OnCommittedResponseWrapper में ओवरराइड नहीं हैं। बाद के बॉडी राइट्स घोषित लंबाई को पूरा करते हैं और कंटेनर आलसी हेडर राइटर को फायर किए बिना कमिट कर देता है।
HttpHeaders के माध्यम से WebFlux Content-Length
serverHttpResponse.getHeaders().set("Content-Length", "42");
serverHttpResponse.getHeaders().add("Content-Length", "42");
serverHttpResponse.getHeaders().setContentLength(42L);
WebFlux बिना शर्त रिस्पॉन्स कमिट
serverHttpResponse.writeWith(Mono.just(dataBuffer));
serverHttpResponse.writeAndFlushWith(publisher);
serverHttpResponse.setComplete();
रेसिपी Spring Security की उपस्थिति पर गेटेड है — यह उन फाइलों में कुछ भी उत्सर्जित नहीं करती जो किसी org.springframework.security.* प्रकार को संदर्भित नहीं करतीं — और प्रभावित Spring Security संस्करण श्रेणियों पर। Spring सलाह के अनुसार, 2026-03-19 को प्रकाशित, प्रभावित श्रेणियां और फिक्स संस्करण हैं:
| श्रृंखला | प्रभावित | फिक्स्ड |
|---|---|---|
| 5.7.x | 5.7.0 – 5.7.21 | 5.7.22 (एंटरप्राइज़) |
| 5.8.x | 5.8.0 – 5.8.23 | 5.8.24 (एंटरप्राइज़) |
| 6.3.x | 6.3.0 – 6.3.14 | 6.3.15 (एंटरप्राइज़) |
| 6.4.x | 6.4.0 – 6.4.14 | 6.4.15 (एंटरप्राइज़) |
| 6.5.x | 6.5.0 – 6.5.8 | 6.5.9 (OSS) |
| 7.0.x | 7.0.0 – 7.0.3 | 7.0.4 (OSS) |
जो प्रोजेक्ट अपनी श्रृंखला में फिक्स के बराबर या उससे ऊपर का Spring Security संस्करण हल करते हैं (या 7.0 / 6.5 से आगे की किसी भी भविष्य की श्रृंखला पर), उन्हें अप्रभावित माना जाता है और उन्हें कोई प्रति-सिंक या प्रति-फाइल मार्कर नहीं मिलता। जिन प्रोजेक्ट्स में संस्करण हल नहीं किया जा सकता, वे सामान्य पैटर्न-आधारित पहचान पर वापस आ जाते हैं ताकि एक स्कैनर उस निष्कर्ष की रिपोर्ट करने की ओर झुके जिसे वह अस्वीकृत नहीं कर सकता। SpringSecurityVersionByProject डेटा तालिका अभी भी हल किए गए संस्करण को रिकॉर्ड करती है और प्रत्येक प्रोजेक्ट को प्रभावित या नहीं के रूप में फ्लैग करती है, ताकि आप ऑडिट कर सकें कि क्या फ़िल्टर किया गया था।
ये खतरनाक दिखते हैं लेकिन रैपर-ट्रैक किए जाते हैं, इसलिए रिस्पॉन्स कमिट होने से पहले सुरक्षा हेडर लिखे जाते हैं:
| कोड | यह सुरक्षित क्यों है |
|---|---|
response.setContentLength(int) / setContentLengthLong(long) | ओवरराइड — रैपर घोषित लंबाई रिकॉर्ड करता है और बॉडी पूरी होने पर onResponseCommitted() फायर करता है। |
response.flushBuffer() | ओवरराइड — super.flushBuffer() से पहले doOnResponseCommitted() कॉल करता है। |
response.getOutputStream().write(..) / flush() / close() | SaveContextServletOutputStream लौटाता है; हर write/flush/close डेलीगेट करने से पहले doOnResponseCommitted() फायर करता है। |
response.getWriter().write(..) / print(..) / println(..) / flush() / close() | SaveContextPrintWriter लौटाता है; वही पैटर्न। |
response.addHeader("Content-Length", v) | रैपर में विशेष-मामला — setContentLength(long) के माध्यम से रूट किया गया। |
Semgrep डेमो का /vuln/flush एंडपॉइंट दावा करता है कि flushBuffer() ट्रिगर है, लेकिन संवेदनशील Spring Security 6.4.12 पर रिस्पॉन्स वास्तव में सभी छह सुरक्षा हेडर लौटाता है। डेमो में वास्तविक ट्रिगर /vuln/stream और /vuln/content-length में setIntHeader("Content-Length", ...) कॉल हैं।
यह चलाएं:
| रेसिपी | उद्देश्य |
|---|---|
io.moderne.recipe.cve202622732.FindSpringSecurityHeaderSuppression | हर पहचान चलाता है और संस्करण रिपोर्ट तालिका उत्सर्जित करता है |
उपरोक्त एग्रीगेटर दो छोटी रेसिपी से बना है। यदि आप केवल एक पहचान चाहते हैं तो आप उन्हें व्यक्तिगत रूप से लागू कर सकते हैं।
| रेसिपी | उद्देश्य |
|---|---|
io.moderne.recipe.cve202622732.FindHttpResponseContentLengthHeader | "Content-Length" लिटरल के लिए टेंट-फ्लो जो setHeader / setIntHeader / addIntHeader (सर्वलेट) या HttpHeaders.set / add (WebFlux) तक पहुंचता है |
io.moderne.recipe.cve202622732.FindHttpResponseContentLengthOrFlushBuffer | WebFlux बिना शर्त कमिट: writeWith, writeAndFlushWith, setComplete, HttpHeaders.setContentLength |
यह चलाएं:
| रेसिपी | उद्देश्य |
|---|---|
io.moderne.recipe.cve202622732.FixSpringSecurityHeaderSuppression | सबसे सस्ता उपचार चुनता है जो प्रत्येक प्रोजेक्ट वास्तव में ले सकता है |
यह क्रम में दो चरण चलाता है।
1. प्रोजेक्ट की अपनी श्रृंखला पर फिक्स पर बढ़ाएं। Spring Security ने फिक्स को 6.5.9 और 7.0.4 के रूप में Maven Central पर प्रकाशित किया। प्रत्येक बंप एक FindAffectedSpringSecuritySeries पूर्वशर्त पर गेटेड है, क्योंकि UpgradeDependencyVersion केवल जांचता है कि उसका लक्ष्य नया है — 7.0.4 पर जाने के लिए कहा गया, यह खुशी से एक 5.8 प्रोजेक्ट को दो प्रमुख संस्करणों में खींच लेगा।
2. चरण 1 जो ठीक नहीं कर सका, उसमें एक उत्सुक हेडर-लेखन कॉन्फ़िगरेशन जोड़ें। यह प्रति प्रोजेक्ट एक @Configuration क्लास उत्पन्न करता है:
@Bean
public static BeanPostProcessor eagerHeaderWriterFilterBeanPostProcessor() {
return new BeanPostProcessor() {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof HeaderWriterFilter) {
((HeaderWriterFilter) bean).setShouldWriteHeadersEagerly(true);
}
return bean;
}
};
}
हेडर को पहले से लिखना अप्रासंगिक बना देता है कि रैपर कभी कमिट का निरीक्षण करता है या नहीं, इसलिए यह प्रोजेक्ट में हर सिंक को एक साथ बंद कर देता है — जिसमें वे भी शामिल हैं जिन तक टेंट विश्लेषण नहीं पहुंच सकता, जैसे "ज्ञात सीमाएं" के तहत Map फ्लो। BeanPostProcessor HttpSecurity DSL द्वारा निर्मित फिल्टर देखता है क्योंकि AutowireBeanFactoryObjectPostProcessor उन्हें बीन फैक्ट्री के माध्यम से आरंभ करता है। इस CVE के लिए दो स्वतंत्र रूप से प्रकाशित फिक्स बिल्कुल इसी आकार का उपयोग करते हैं (hmcts/idam-web-public, और armory-io के Spinnaker फोर्क समतुल्य ObjectPostProcessor के माध्यम से)।
चरण 2 वही कवर करता है जो चरण 1 नहीं कर सकता:
| स्थिति | बंप क्यों काम नहीं करता |
|---|---|
| 5.7, 5.8, 6.3, 6.4 | फिक्स केवल Spring Enterprise ग्राहकों को जाता है — Maven Central पर नहीं |
| 6.0 - 6.2 | उन श्रृंखलाओं पर कोई फिक्स कभी जारी नहीं हुआ |
| आयातित BOM द्वारा प्रबंधित संस्करण | बंप को संपादित करने के लिए स्थानीय रूप से कुछ भी घोषित नहीं है |
वह अंतिम पंक्ति कोई किनारे का मामला नहीं है। nla/bamboo 7.0.3 हल करता है — एक श्रृंखला जिसमें ओपन-सोर्स फिक्स है — पूरी तरह से Spring Boot BOM से, इसलिए अकेले संस्करण जांच दोनों चरणों के तहत इसे छोड़ देगी और इसे संवेदनशील छोड़ देगी। AddEagerHeaderWriterConfiguration इसलिए केवल अपग्रेड को स्थगित करता है जब प्रोजेक्ट के पास ओपन-सोर्स फिक्स उपलब्ध हो और अपना स्वयं का संस्करण घोषित करता हो।