(window.webpackJsonp=window.webpackJsonp||[]).push([[189],{616:function(e,t,r){"use strict";r.r(t);var a=r(56),n=Object(a.a)({},(function(){var e=this,t=e.$createElement,r=e._self._c||t;return r("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[r("h1",{attrs:{id:"security-http-response-headers"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#security-http-response-headers"}},[e._v("#")]),e._v(" Security HTTP Response Headers")]),e._v(" "),r("p",[r("RouterLink",{attrs:{to:"/features/exploits/headers.html#headers"}},[e._v("Security HTTP Response Headers")]),e._v(" can be used to increase the security of web applications.\nThis section is dedicated to WebFlux based support for Security HTTP Response Headers.")],1),e._v(" "),r("h2",{attrs:{id:"default-security-headers"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#default-security-headers"}},[e._v("#")]),e._v(" Default Security Headers")]),e._v(" "),r("p",[e._v("Spring Security provides a "),r("RouterLink",{attrs:{to:"/features/exploits/headers.html#headers-default"}},[e._v("default set of Security HTTP Response Headers")]),e._v(" to provide secure defaults.\nWhile each of these headers are considered best practice, it should be noted that not all clients utilize the headers, so additional testing is encouraged.")],1),e._v(" "),r("p",[e._v("You can customize specific headers.\nFor example, assume that you want the defaults except you wish to specify "),r("code",[e._v("SAMEORIGIN")]),e._v(" for "),r("RouterLink",{attrs:{to:"/servlet/exploits/headers.html#servlet-headers-frame-options"}},[e._v("X-Frame-Options")]),e._v(".")],1),e._v(" "),r("p",[e._v("You can easily do this with the following Configuration:")]),e._v(" "),r("p",[e._v("Example 1. Customize Default Security Headers")]),e._v(" "),r("p",[e._v("Java")]),e._v(" "),r("div",{staticClass:"language- extra-class"},[r("pre",{pre:!0,attrs:{class:"language-text"}},[r("code",[e._v("@Bean\nSecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {\n\thttp\n\t\t// ...\n\t\t.headers(headers -> headers\n\t\t\t.frameOptions(frameOptions -> frameOptions\n\t\t\t\t.mode(Mode.SAMEORIGIN)\n\t\t\t)\n\t\t);\n\treturn http.build();\n}\n")])])]),r("p",[e._v("Kotlin")]),e._v(" "),r("div",{staticClass:"language- extra-class"},[r("pre",{pre:!0,attrs:{class:"language-text"}},[r("code",[e._v("@Bean\nfun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {\n return http {\n // ...\n headers {\n frameOptions {\n mode = Mode.SAMEORIGIN\n }\n }\n }\n}\n")])])]),r("p",[e._v("If you do not want the defaults to be added and want explicit control over what should be used, you can disable the defaults.\nAn example is provided below:")]),e._v(" "),r("p",[e._v("Example 2. Disable HTTP Security Response Headers")]),e._v(" "),r("p",[e._v("Java")]),e._v(" "),r("div",{staticClass:"language- extra-class"},[r("pre",{pre:!0,attrs:{class:"language-text"}},[r("code",[e._v("@Bean\nSecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {\n\thttp\n\t\t// ...\n\t\t.headers(headers -> headers.disable());\n\treturn http.build();\n}\n")])])]),r("p",[e._v("Kotlin")]),e._v(" "),r("div",{staticClass:"language- extra-class"},[r("pre",{pre:!0,attrs:{class:"language-text"}},[r("code",[e._v("@Bean\nfun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {\n return http {\n // ...\n headers {\n disable()\n }\n }\n}\n")])])]),r("h2",{attrs:{id:"cache-control"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#cache-control"}},[e._v("#")]),e._v(" Cache Control")]),e._v(" "),r("p",[e._v("Spring Security includes "),r("RouterLink",{attrs:{to:"/features/exploits/headers.html#headers-cache-control"}},[e._v("Cache Control")]),e._v(" headers by default.")],1),e._v(" "),r("p",[e._v("However, if you actually want to cache specific responses, your application can selectively add them to the "),r("a",{attrs:{href:"https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/http/server/reactive/ServerHttpResponse.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("ServerHttpResponse"),r("OutboundLink")],1),e._v(" to override the header set by Spring Security.\nThis is useful to ensure things like CSS, JavaScript, and images are properly cached.")]),e._v(" "),r("p",[e._v("When using Spring WebFlux, this is typically done within your configuration.\nDetails on how to do this can be found in the "),r("a",{attrs:{href:"https://docs.spring.io/spring/docs/5.0.0.RELEASE/spring-framework-reference/web-reactive.html#webflux-config-static-resources",target:"_blank",rel:"noopener noreferrer"}},[e._v("Static Resources"),r("OutboundLink")],1),e._v(" portion of the Spring Reference documentation")]),e._v(" "),r("p",[e._v("If necessary, you can also disable Spring Security’s cache control HTTP response headers.")]),e._v(" "),r("p",[e._v("Example 3. Cache Control Disabled")]),e._v(" "),r("p",[e._v("Java")]),e._v(" "),r("div",{staticClass:"language- extra-class"},[r("pre",{pre:!0,attrs:{class:"language-text"}},[r("code",[e._v("@Bean\nSecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {\n\thttp\n\t\t// ...\n\t\t.headers(headers -> headers\n\t\t\t.cache(cache -> cache.disable())\n\t\t);\n\treturn http.build();\n}\n")])])]),r("p",[e._v("Kotlin")]),e._v(" "),r("div",{staticClass:"language- extra-class"},[r("pre",{pre:!0,attrs:{class:"language-text"}},[r("code",[e._v("@Bean\nfun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {\n return http {\n // ...\n headers {\n cache {\n disable()\n }\n }\n }\n}\n")])])]),r("h2",{attrs:{id:"content-type-options"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#content-type-options"}},[e._v("#")]),e._v(" Content Type Options")]),e._v(" "),r("p",[e._v("Spring Security includes "),r("RouterLink",{attrs:{to:"/features/exploits/headers.html#headers-content-type-options"}},[e._v("Content-Type")]),e._v(" headers by default.\nHowever, you can disable it with:")],1),e._v(" "),r("p",[e._v("Example 4. Content Type Options Disabled")]),e._v(" "),r("p",[e._v("Java")]),e._v(" "),r("div",{staticClass:"language- extra-class"},[r("pre",{pre:!0,attrs:{class:"language-text"}},[r("code",[e._v("@Bean\nSecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {\n\thttp\n\t\t// ...\n\t\t.headers(headers -> headers\n\t\t\t.contentTypeOptions(contentTypeOptions -> contentTypeOptions.disable())\n\t\t);\n\treturn http.build();\n}\n")])])]),r("p",[e._v("Kotlin")]),e._v(" "),r("div",{staticClass:"language- extra-class"},[r("pre",{pre:!0,attrs:{class:"language-text"}},[r("code",[e._v("@Bean\nfun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {\n return http {\n // ...\n headers {\n contentTypeOptions {\n disable()\n }\n }\n }\n}\n")])])]),r("h2",{attrs:{id:""}},[r("a",{staticClass:"header-anchor",attrs:{href:"#"}},[e._v("#")])]),e._v(" "),r("p",[e._v("Spring Security provides the "),r("RouterLink",{attrs:{to:"/features/exploits/headers.html#headers-hsts"}},[e._v("Strict Transport Security")]),e._v(" header by default.\nHowever, you can customize the results explicitly.\nFor example, the following is an example of explicitly providing HSTS:")],1),e._v(" "),r("p",[e._v("Example 5. Strict Transport Security")]),e._v(" "),r("p",[e._v("Java")]),e._v(" "),r("div",{staticClass:"language- extra-class"},[r("pre",{pre:!0,attrs:{class:"language-text"}},[r("code",[e._v("@Bean\nSecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {\n\thttp\n\t\t// ...\n\t\t.headers(headers -> headers\n\t\t\t.hsts(hsts -> hsts\n\t\t\t\t.includeSubdomains(true)\n\t\t\t\t.preload(true)\n\t\t\t\t.maxAge(Duration.ofDays(365))\n\t\t\t)\n\t\t);\n\treturn http.build();\n}\n")])])]),r("p",[e._v("Kotlin")]),e._v(" "),r("div",{staticClass:"language- extra-class"},[r("pre",{pre:!0,attrs:{class:"language-text"}},[r("code",[e._v("@Bean\nfun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {\n return http {\n // ...\n headers {\n hsts {\n includeSubdomains = true\n preload = true\n maxAge = Duration.ofDays(365)\n }\n }\n }\n}\n")])])]),r("h2",{attrs:{id:"x-frame-options"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#x-frame-options"}},[e._v("#")]),e._v(" X-Frame-Options")]),e._v(" "),r("p",[e._v("By default, Spring Security disables rendering within an iframe using "),r("RouterLink",{attrs:{to:"/features/exploits/headers.html#headers-frame-options"}},[e._v("X-Frame-Options")]),e._v(".")],1),e._v(" "),r("p",[e._v("You can customize frame options to use the same origin using the following:")]),e._v(" "),r("p",[e._v("Example 6. X-Frame-Options: SAMEORIGIN")]),e._v(" "),r("p",[e._v("Java")]),e._v(" "),r("div",{staticClass:"language- extra-class"},[r("pre",{pre:!0,attrs:{class:"language-text"}},[r("code",[e._v("@Bean\nSecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {\n\thttp\n\t\t// ...\n\t\t.headers(headers -> headers\n\t\t\t.frameOptions(frameOptions -> frameOptions\n\t\t\t\t.mode(SAMEORIGIN)\n\t\t\t)\n\t\t);\n\treturn http.build();\n}\n")])])]),r("p",[e._v("Kotlin")]),e._v(" "),r("div",{staticClass:"language- extra-class"},[r("pre",{pre:!0,attrs:{class:"language-text"}},[r("code",[e._v("@Bean\nfun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {\n return http {\n // ...\n headers {\n frameOptions {\n mode = SAMEORIGIN\n }\n }\n }\n}\n")])])]),r("h2",{attrs:{id:"x-xss-protection"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#x-xss-protection"}},[e._v("#")]),e._v(" X-XSS-Protection")]),e._v(" "),r("p",[e._v("By default, Spring Security instructs browsers to block reflected XSS attacks using the <.\nYou can disable "),r("code",[e._v("X-XSS-Protection")]),e._v(" with the following Configuration:")]),e._v(" "),r("p",[e._v("Example 7. X-XSS-Protection Customization")]),e._v(" "),r("p",[e._v("Java")]),e._v(" "),r("div",{staticClass:"language- extra-class"},[r("pre",{pre:!0,attrs:{class:"language-text"}},[r("code",[e._v("@Bean\nSecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {\n\thttp\n\t\t// ...\n\t\t.headers(headers -> headers\n\t\t\t.xssProtection(xssProtection -> xssProtection.disable())\n\t\t);\n\treturn http.build();\n}\n")])])]),r("p",[e._v("Kotlin")]),e._v(" "),r("div",{staticClass:"language- extra-class"},[r("pre",{pre:!0,attrs:{class:"language-text"}},[r("code",[e._v("@Bean\nfun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {\n return http {\n // ...\n headers {\n xssProtection {\n disable()\n }\n }\n }\n}\n")])])]),r("h2",{attrs:{id:"-2"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#-2"}},[e._v("#")])]),e._v(" "),r("p",[e._v("Spring Security does not add "),r("RouterLink",{attrs:{to:"/features/exploits/headers.html#headers-csp"}},[e._v("Content Security Policy")]),e._v(" by default, because a reasonable default is impossible to know without context of the application.\nThe web application author must declare the security policy(s) to enforce and/or monitor for the protected resources.")],1),e._v(" "),r("p",[e._v("For example, given the following security policy:")]),e._v(" "),r("p",[e._v("Example 8. Content Security Policy Example")]),e._v(" "),r("div",{staticClass:"language- extra-class"},[r("pre",{pre:!0,attrs:{class:"language-text"}},[r("code",[e._v("Content-Security-Policy: script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/\n")])])]),r("p",[e._v("You can enable the CSP header as shown below:")]),e._v(" "),r("p",[e._v("Example 9. Content Security Policy")]),e._v(" "),r("p",[e._v("Java")]),e._v(" "),r("div",{staticClass:"language- extra-class"},[r("pre",{pre:!0,attrs:{class:"language-text"}},[r("code",[e._v("@Bean\nSecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {\n\thttp\n\t\t// ...\n\t\t.headers(headers -> headers\n\t\t\t.contentSecurityPolicy(policy -> policy\n\t\t\t\t.policyDirectives(\"script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/\")\n\t\t\t)\n\t\t);\n\treturn http.build();\n}\n")])])]),r("p",[e._v("Kotlin")]),e._v(" "),r("div",{staticClass:"language- extra-class"},[r("pre",{pre:!0,attrs:{class:"language-text"}},[r("code",[e._v("@Bean\nfun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {\n return http {\n // ...\n headers {\n contentSecurityPolicy {\n policyDirectives = \"script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/\"\n }\n }\n }\n}\n")])])]),r("p",[e._v("To enable the CSP "),r("code",[e._v("report-only")]),e._v(" header, provide the following configuration:")]),e._v(" "),r("p",[e._v("Example 10. Content Security Policy Report Only")]),e._v(" "),r("p",[e._v("Java")]),e._v(" "),r("div",{staticClass:"language- extra-class"},[r("pre",{pre:!0,attrs:{class:"language-text"}},[r("code",[e._v("@Bean\nSecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {\n\thttp\n\t\t// ...\n\t\t.headers(headers -> headers\n\t\t\t.contentSecurityPolicy(policy -> policy\n\t\t\t\t.policyDirectives(\"script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/\")\n\t\t\t\t.reportOnly()\n\t\t\t)\n\t\t);\n\treturn http.build();\n}\n")])])]),r("p",[e._v("Kotlin")]),e._v(" "),r("div",{staticClass:"language- extra-class"},[r("pre",{pre:!0,attrs:{class:"language-text"}},[r("code",[e._v("@Bean\nfun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {\n return http {\n // ...\n headers {\n contentSecurityPolicy {\n policyDirectives = \"script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/\"\n reportOnly = true\n }\n }\n }\n}\n")])])]),r("h2",{attrs:{id:"referrer-policy"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#referrer-policy"}},[e._v("#")]),e._v(" Referrer Policy")]),e._v(" "),r("p",[e._v("Spring Security does not add "),r("RouterLink",{attrs:{to:"/features/exploits/headers.html#headers-referrer"}},[e._v("Referrer Policy")]),e._v(" headers by default.\nYou can enable the Referrer Policy header using configuration as shown below:")],1),e._v(" "),r("p",[e._v("Example 11. Referrer Policy Configuration")]),e._v(" "),r("p",[e._v("Java")]),e._v(" "),r("div",{staticClass:"language- extra-class"},[r("pre",{pre:!0,attrs:{class:"language-text"}},[r("code",[e._v("@Bean\nSecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {\n\thttp\n\t\t// ...\n\t\t.headers(headers -> headers\n\t\t\t.referrerPolicy(referrer -> referrer\n\t\t\t\t.policy(ReferrerPolicy.SAME_ORIGIN)\n\t\t\t)\n\t\t);\n\treturn http.build();\n}\n")])])]),r("p",[e._v("Kotlin")]),e._v(" "),r("div",{staticClass:"language- extra-class"},[r("pre",{pre:!0,attrs:{class:"language-text"}},[r("code",[e._v("@Bean\nfun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {\n return http {\n // ...\n headers {\n referrerPolicy {\n policy = ReferrerPolicy.SAME_ORIGIN\n }\n }\n }\n}\n")])])]),r("h2",{attrs:{id:"feature-policy"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#feature-policy"}},[e._v("#")]),e._v(" Feature Policy")]),e._v(" "),r("p",[e._v("Spring Security does not add "),r("RouterLink",{attrs:{to:"/features/exploits/headers.html#headers-feature"}},[e._v("Feature Policy")]),e._v(" headers by default.\nThe following "),r("code",[e._v("Feature-Policy")]),e._v(" header:")],1),e._v(" "),r("p",[e._v("Example 12. Feature-Policy Example")]),e._v(" "),r("div",{staticClass:"language- extra-class"},[r("pre",{pre:!0,attrs:{class:"language-text"}},[r("code",[e._v("Feature-Policy: geolocation 'self'\n")])])]),r("p",[e._v("You can enable the Feature Policy header as shown below:")]),e._v(" "),r("p",[e._v("Example 13. Feature-Policy Configuration")]),e._v(" "),r("p",[e._v("Java")]),e._v(" "),r("div",{staticClass:"language- extra-class"},[r("pre",{pre:!0,attrs:{class:"language-text"}},[r("code",[e._v("@Bean\nSecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {\n\thttp\n\t\t// ...\n\t\t.headers(headers -> headers\n\t\t\t.featurePolicy(\"geolocation 'self'\")\n\t\t);\n\treturn http.build();\n}\n")])])]),r("p",[e._v("Kotlin")]),e._v(" "),r("div",{staticClass:"language- extra-class"},[r("pre",{pre:!0,attrs:{class:"language-text"}},[r("code",[e._v("@Bean\nfun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {\n return http {\n // ...\n headers {\n featurePolicy(\"geolocation 'self'\")\n }\n }\n}\n")])])]),r("h2",{attrs:{id:"permissions-policy"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#permissions-policy"}},[e._v("#")]),e._v(" Permissions Policy")]),e._v(" "),r("p",[e._v("Spring Security does not add "),r("RouterLink",{attrs:{to:"/features/exploits/headers.html#headers-permissions"}},[e._v("Permissions Policy")]),e._v(" headers by default.\nThe following "),r("code",[e._v("Permissions-Policy")]),e._v(" header:")],1),e._v(" "),r("p",[e._v("Example 14. Permissions-Policy Example")]),e._v(" "),r("div",{staticClass:"language- extra-class"},[r("pre",{pre:!0,attrs:{class:"language-text"}},[r("code",[e._v("Permissions-Policy: geolocation=(self)\n")])])]),r("p",[e._v("You can enable the Permissions Policy header as shown below:")]),e._v(" "),r("p",[e._v("Example 15. Permissions-Policy Configuration")]),e._v(" "),r("p",[e._v("Java")]),e._v(" "),r("div",{staticClass:"language- extra-class"},[r("pre",{pre:!0,attrs:{class:"language-text"}},[r("code",[e._v('@Bean\nSecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {\n\thttp\n\t\t// ...\n\t\t.headers(headers -> headers\n\t\t\t.permissionsPolicy(permissions -> permissions\n\t\t\t\t.policy("geolocation=(self)")\n\t\t\t)\n\t\t);\n\treturn http.build();\n}\n')])])]),r("p",[e._v("Kotlin")]),e._v(" "),r("div",{staticClass:"language- extra-class"},[r("pre",{pre:!0,attrs:{class:"language-text"}},[r("code",[e._v('@Bean\nfun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {\n return http {\n // ...\n headers {\n permissionsPolicy {\n policy = "geolocation=(self)"\n }\n }\n }\n}\n')])])]),r("h2",{attrs:{id:"clear-site-data"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#clear-site-data"}},[e._v("#")]),e._v(" Clear Site Data")]),e._v(" "),r("p",[e._v("Spring Security does not add "),r("RouterLink",{attrs:{to:"/features/exploits/headers.html#headers-clear-site-data"}},[e._v("Clear-Site-Data")]),e._v(" headers by default.\nThe following Clear-Site-Data header:")],1),e._v(" "),r("p",[e._v("Example 16. Clear-Site-Data Example")]),e._v(" "),r("div",{staticClass:"language- extra-class"},[r("pre",{pre:!0,attrs:{class:"language-text"}},[r("code",[e._v('Clear-Site-Data: "cache", "cookies"\n')])])]),r("p",[e._v("can be sent on log out with the following configuration:")]),e._v(" "),r("p",[e._v("Example 17. Clear-Site-Data Configuration")]),e._v(" "),r("p",[e._v("Java")]),e._v(" "),r("div",{staticClass:"language- extra-class"},[r("pre",{pre:!0,attrs:{class:"language-text"}},[r("code",[e._v("@Bean\nSecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {\n\tServerLogoutHandler securityContext = new SecurityContextServerLogoutHandler();\n\tClearSiteDataServerHttpHeadersWriter writer = new ClearSiteDataServerHttpHeadersWriter(CACHE, COOKIES);\n\tServerLogoutHandler clearSiteData = new HeaderWriterServerLogoutHandler(writer);\n\tDelegatingServerLogoutHandler logoutHandler = new DelegatingServerLogoutHandler(securityContext, clearSiteData);\n\n\thttp\n\t\t// ...\n\t\t.logout()\n\t\t\t.logoutHandler(logoutHandler);\n\treturn http.build();\n}\n")])])]),r("p",[e._v("Kotlin")]),e._v(" "),r("div",{staticClass:"language- extra-class"},[r("pre",{pre:!0,attrs:{class:"language-text"}},[r("code",[e._v("@Bean\nfun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {\n val securityContext: ServerLogoutHandler = SecurityContextServerLogoutHandler()\n val writer = ClearSiteDataServerHttpHeadersWriter(CACHE, COOKIES)\n val clearSiteData: ServerLogoutHandler = HeaderWriterServerLogoutHandler(writer)\n val customLogoutHandler = DelegatingServerLogoutHandler(securityContext, clearSiteData)\n\n return http {\n // ...\n logout {\n logoutHandler = customLogoutHandler\n }\n }\n}\n")])])])])}),[],!1,null,null,null);t.default=n.exports}}]);