helmet_core/lib.rs
1//! Helmet is a collection of HTTP headers that help secure your app by setting various HTTP headers.
2//!
3//! `helmet-core` provides the core functionality of Helmet, vie convenient builders to configure the library.
4//!
5//! The library can be adapted to different frameworks by wrapping the `Helmet` struct in a way that suits the framework. For reference implementations see the [ntex-helmet](https://crates.io/crates/ntex-helmet) crate or the [axum-helmet](https://crates.io/crates/axum-helmet) crate.
6//!
7//! It is based on the [Helmet](https://helmetjs.github.io/) library for Node.js and is highly configurable.
8//!
9//! # Usage
10//!
11//! ```no_run
12//! use helmet_core::{ContentSecurityPolicy, CrossOriginOpenerPolicy, Helmet};
13//!
14//! let helmet = Helmet::new()
15//! .add(
16//! ContentSecurityPolicy::new()
17//! .child_src(vec!["'self'", "https://youtube.com"])
18//! .connect_src(vec!["'self'", "https://youtube.com"])
19//! .default_src(vec!["'self'", "https://youtube.com"])
20//! .font_src(vec!["'self'", "https://youtube.com"]),
21//! )
22//! .add(CrossOriginOpenerPolicy::same_origin_allow_popups());
23//! ```
24//!
25//! By default Helmet will set the following headers:
26//!
27//! ```text
28//! Content-Security-Policy: default-src 'self'; base-uri 'self'; font-src 'self' https: data:; form-action 'self'; frame-ancestors 'self'; img-src 'self' data:; object-src 'none'; script-src 'self'; script-src-attr 'none'; style-src 'self' https: 'unsafe-inline'; upgrade-insecure-requests
29//! Cross-Origin-Opener-Policy: same-origin
30//! Cross-Origin-Resource-Policy: same-origin
31//! Origin-Agent-Cluster: ?1
32//! Referrer-Policy: no-referrer
33//! Strict-Transport-Security: max-age=15552000; includeSubDomains
34//! X-Content-Type-Options: nosniff
35//! X-DNS-Prefetch-Control: off
36//! X-Download-Options: noopen
37//! X-Frame-Options: sameorigin
38//! X-Permitted-Cross-Domain-Policies: none
39//! X-XSS-Protection: 0
40//! ```
41//!
42//! This might be a good starting point for most users, but it is highly recommended to spend some time with the documentation for each header, and adjust them to your needs.
43//!
44//! # Configuration
45//!
46//! By default if you construct a new instance of `Helmet` it will not set any headers.
47//!
48//! The `helmet-core` crate helps you configure Helmet by providing convenient builders for each header.
49use core::fmt::Display;
50
51/// Header trait
52///
53/// Allows custom headers to be added to the response
54///
55/// # Examples
56///
57/// ```
58/// use helmet_core::Header;
59///
60/// struct MyHeader;
61///
62/// impl Into<Header> for MyHeader {
63/// fn into(self) -> Header {
64/// ("My-Header", "My-Value".to_owned())
65/// }
66/// }
67/// ```
68
69pub type Header = (&'static str, String);
70
71/// Manages `Cross-Origin-Embedder-Policy` header
72///
73/// The Cross-Origin-Embedder-Policy HTTP response header prevents a document from loading any cross-origin resources that do not explicitly grant the document permission (via CORS headers) to load them.
74///
75/// # Values
76///
77/// - unsafe-none: The document is not subject to any Cross-Origin-Embedder-Policy restrictions.
78/// - require-corp: The document is subject to Cross-Origin-Embedder-Policy restrictions.
79/// - credentialless: The document is subject to Cross-Origin-Embedder-Policy restrictions, and is not allowed to request credentials (e.g. cookies, certificates, HTTP authentication) from the user.
80///
81/// # Examples
82///
83/// ```
84/// use helmet_core::CrossOriginEmbedderPolicy;
85///
86/// let cross_origin_embedder_policy = CrossOriginEmbedderPolicy::unsafe_none();
87///
88/// let cross_origin_embedder_policy = CrossOriginEmbedderPolicy::require_corp();
89///
90/// let cross_origin_embedder_policy = CrossOriginEmbedderPolicy::credentialless();
91/// ```
92#[derive(Clone)]
93pub enum CrossOriginEmbedderPolicy {
94 UnsafeNone,
95 RequireCorp,
96 Credentialless,
97}
98
99impl CrossOriginEmbedderPolicy {
100 pub fn unsafe_none() -> Self {
101 Self::UnsafeNone
102 }
103
104 pub fn require_corp() -> Self {
105 Self::RequireCorp
106 }
107
108 pub fn credentialless() -> Self {
109 Self::Credentialless
110 }
111}
112
113impl CrossOriginEmbedderPolicy {
114 pub fn as_str(&self) -> &'static str {
115 match self {
116 CrossOriginEmbedderPolicy::UnsafeNone => "unsafe-none",
117 CrossOriginEmbedderPolicy::RequireCorp => "require-corp",
118 CrossOriginEmbedderPolicy::Credentialless => "credentialless",
119 }
120 }
121}
122
123impl Into<Header> for CrossOriginEmbedderPolicy {
124 fn into(self) -> Header {
125 ("Cross-Origin-Embedder-Policy", self.as_str().to_owned())
126 }
127}
128
129/// Manages `Cross-Origin-Opener-Policy` header
130///
131/// The Cross-Origin-Opener-Policy HTTP response header restricts how selected resources are allowed to interact with the document's browsing context in response to user navigation. Each resource can declare an opener policy which applies to the resource's corresponding browsing context.
132///
133/// # Values
134///
135/// - same-origin: The resource's browsing context is the same-origin as the document's browsing context.
136/// - same-origin-allow-popups: The resource's browsing context is the same-origin as the document's browsing context, and the resource is allowed to open new browsing contexts.
137/// - unsafe-none: The resource's browsing context is cross-origin with the document's browsing context.
138///
139/// # Examples
140///
141/// ```
142/// use helmet_core::CrossOriginOpenerPolicy;
143///
144/// let cross_origin_opener_policy = CrossOriginOpenerPolicy::same_origin();
145/// ```
146#[derive(Clone)]
147pub enum CrossOriginOpenerPolicy {
148 SameOrigin,
149 SameOriginAllowPopups,
150 UnsafeNone,
151}
152
153impl CrossOriginOpenerPolicy {
154 pub fn same_origin() -> Self {
155 Self::SameOrigin
156 }
157
158 pub fn same_origin_allow_popups() -> Self {
159 Self::SameOriginAllowPopups
160 }
161
162 pub fn unsafe_none() -> Self {
163 Self::UnsafeNone
164 }
165}
166
167impl CrossOriginOpenerPolicy {
168 fn as_str(&self) -> &'static str {
169 match self {
170 CrossOriginOpenerPolicy::SameOrigin => "same-origin",
171 CrossOriginOpenerPolicy::SameOriginAllowPopups => "same-origin-allow-popups",
172 CrossOriginOpenerPolicy::UnsafeNone => "unsafe-none",
173 }
174 }
175}
176
177impl Into<Header> for CrossOriginOpenerPolicy {
178 fn into(self) -> Header {
179 ("Cross-Origin-Opener-Policy", self.as_str().to_owned())
180 }
181}
182
183/// Manages `Cross-Origin-Resource-Policy` header
184///
185/// The Cross-Origin-Resource-Policy HTTP response header conveys a desire that the browser blocks no-cors cross-origin/cross-site requests to the given resource.
186///
187/// # Values
188///
189/// - same-origin: The resource is same-origin to the document.
190/// - same-site: The resource is same-site to the document.
191/// - cross-origin: The resource is cross-origin to the document.
192///
193/// # Examples
194///
195/// ```
196/// use helmet_core::CrossOriginResourcePolicy;
197///
198/// let cross_origin_resource_policy = CrossOriginResourcePolicy::same_origin();
199/// ```
200#[derive(Clone)]
201pub enum CrossOriginResourcePolicy {
202 SameOrigin,
203 SameSite,
204 CrossOrigin,
205}
206
207impl CrossOriginResourcePolicy {
208 pub fn same_origin() -> Self {
209 Self::SameOrigin
210 }
211
212 pub fn same_site() -> Self {
213 Self::SameSite
214 }
215
216 pub fn cross_origin() -> Self {
217 Self::CrossOrigin
218 }
219}
220
221impl CrossOriginResourcePolicy {
222 fn as_str(&self) -> &'static str {
223 match self {
224 CrossOriginResourcePolicy::SameOrigin => "same-origin",
225 CrossOriginResourcePolicy::SameSite => "same-site",
226 CrossOriginResourcePolicy::CrossOrigin => "cross-origin",
227 }
228 }
229}
230
231impl Into<Header> for CrossOriginResourcePolicy {
232 fn into(self) -> Header {
233 ("Cross-Origin-Resource-Policy", self.as_str().to_owned())
234 }
235}
236
237/// Manages `Origin-Agent-Cluster` header
238///
239/// The Origin-Agent-Cluster HTTP request header indicates that the client prefers an "origin agent cluster" (OAC) for the origin of the resource being requested. An OAC is a cluster of servers that are controlled by the same entity as the origin server, and that are geographically close to the client. The OAC is used to provide the client with a better experience, for example by serving content from a server that is close to the client, or by serving content that is optimized for the client's device.
240///
241/// # Values
242///
243/// - 0: The client does not prefer an OAC.
244/// - 1: The client prefers an OAC.
245///
246/// # Examples
247///
248/// ```
249/// use helmet_core::OriginAgentCluster;
250///
251/// let origin_agent_cluster = OriginAgentCluster::new(true);
252/// ```
253#[derive(Clone)]
254pub struct OriginAgentCluster(bool);
255
256impl OriginAgentCluster {
257 pub fn new(prefer_mobile_experience: bool) -> Self {
258 Self(prefer_mobile_experience)
259 }
260}
261
262impl OriginAgentCluster {
263 fn as_str(&self) -> &'static str {
264 if self.0 {
265 "?1"
266 } else {
267 "?0"
268 }
269 }
270}
271
272impl Into<Header> for OriginAgentCluster {
273 fn into(self) -> Header {
274 ("Origin-Agent-Cluster", self.as_str().to_owned())
275 }
276}
277
278/// Manages `Referrer-Policy` header
279///
280/// The Referrer-Policy HTTP response header controls how much referrer information (sent via the Referer header) should be included with requests.
281///
282/// # Values
283///
284/// - no-referrer: The Referer header will be omitted entirely. No referrer information is sent along with requests.
285/// - no-referrer-when-downgrade: The Referer header will be omitted entirely. However, if the protected resource URL scheme is HTTPS, then the full path will still be sent as a referrer.
286/// - origin: Only send the origin of the document as the referrer in all cases. The document https://example.com/page.html will send the referrer https://example.com/.
287/// - origin-when-cross-origin: Send a full URL when performing a same-origin request, but only send the origin of the document for other cases.
288/// - same-origin: A referrer will be sent for same-site origins, but cross-origin requests will contain no referrer information.
289/// - strict-origin: Only send the origin of the document as the referrer when the protocol security level stays the same (HTTPS→HTTPS), but don't send it to a less secure destination (HTTPS→HTTP).
290/// - strict-origin-when-cross-origin: Send a full URL when performing a same-origin request, only send the origin when the protocol security level stays the same (HTTPS→HTTPS), and send no header to a less secure destination (HTTPS→HTTP).
291/// - unsafe-url: Send a full URL (stripped from parameters) when performing a same-origin or cross-origin request. This policy will leak origins and paths from TLS-protected resources to insecure origins. Carefully consider the impact of this setting.
292///
293/// # Examples
294///
295/// ```
296/// use helmet_core::ReferrerPolicy;
297///
298/// let referrer_policy = ReferrerPolicy::no_referrer();
299/// ```
300#[derive(Clone)]
301pub enum ReferrerPolicy {
302 NoReferrer,
303 NoReferrerWhenDowngrade,
304 Origin,
305 OriginWhenCrossOrigin,
306 SameOrigin,
307 StrictOrigin,
308 StrictOriginWhenCrossOrigin,
309 UnsafeUrl,
310}
311
312impl ReferrerPolicy {
313 pub fn no_referrer() -> Self {
314 Self::NoReferrer
315 }
316
317 pub fn no_referrer_when_downgrade() -> Self {
318 Self::NoReferrerWhenDowngrade
319 }
320
321 pub fn origin() -> Self {
322 Self::Origin
323 }
324
325 pub fn origin_when_cross_origin() -> Self {
326 Self::OriginWhenCrossOrigin
327 }
328
329 pub fn same_origin() -> Self {
330 Self::SameOrigin
331 }
332
333 pub fn strict_origin() -> Self {
334 Self::StrictOrigin
335 }
336
337 pub fn strict_origin_when_cross_origin() -> Self {
338 Self::StrictOriginWhenCrossOrigin
339 }
340
341 pub fn unsafe_url() -> Self {
342 Self::UnsafeUrl
343 }
344}
345
346impl ReferrerPolicy {
347 fn as_str(&self) -> &'static str {
348 match self {
349 ReferrerPolicy::NoReferrer => "no-referrer",
350 ReferrerPolicy::NoReferrerWhenDowngrade => "no-referrer-when-downgrade",
351 ReferrerPolicy::Origin => "origin",
352 ReferrerPolicy::OriginWhenCrossOrigin => "origin-when-cross-origin",
353 ReferrerPolicy::SameOrigin => "same-origin",
354 ReferrerPolicy::StrictOrigin => "strict-origin",
355 ReferrerPolicy::StrictOriginWhenCrossOrigin => "strict-origin-when-cross-origin",
356 ReferrerPolicy::UnsafeUrl => "unsafe-url",
357 }
358 }
359}
360
361impl Into<Header> for ReferrerPolicy {
362 fn into(self) -> Header {
363 ("Referrer-Policy", self.as_str().to_owned())
364 }
365}
366
367/// Manages `Strict-Transport-Security` header
368///
369/// The Strict-Transport-Security HTTP response header (often abbreviated as HSTS) lets a web site tell browsers that it should only be accessed using HTTPS, instead of using HTTP.
370///
371/// # Values
372///
373/// - max-age: The time, in seconds, that the browser should remember that a site is only to be accessed using HTTPS.
374/// - includeSubDomains: If this optional parameter is specified, this rule applies to all of the site's subdomains as well.
375/// - preload: If this optional parameter is specified, this rule applies to all of the site's subdomains as well.
376///
377/// # Examples
378///
379/// ```
380/// use helmet_core::StrictTransportSecurity;
381///
382/// let strict_transport_security = StrictTransportSecurity::default();
383///
384/// let custom_strict_transport_security = StrictTransportSecurity::default()
385/// .max_age(31536000)
386/// .include_sub_domains()
387/// .preload();
388/// ```
389#[derive(Clone)]
390pub struct StrictTransportSecurity {
391 max_age: u32,
392 include_sub_domains: bool,
393 preload: bool,
394}
395
396impl StrictTransportSecurity {
397 pub fn new() -> Self {
398 Self::default()
399 }
400
401 pub fn max_age(mut self, max_age: u32) -> Self {
402 self.max_age = max_age;
403 self
404 }
405
406 pub fn include_sub_domains(mut self) -> Self {
407 self.include_sub_domains = true;
408 self
409 }
410
411 pub fn preload(mut self) -> Self {
412 self.preload = true;
413 self
414 }
415}
416
417impl Default for StrictTransportSecurity {
418 fn default() -> Self {
419 Self {
420 max_age: 31536000,
421 include_sub_domains: false,
422 preload: false,
423 }
424 }
425}
426
427impl Display for StrictTransportSecurity {
428 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
429 write!(f, "max-age={}", self.max_age)?;
430 if self.include_sub_domains {
431 write!(f, "; includeSubDomains")?;
432 }
433 if self.preload {
434 write!(f, "; preload")?;
435 }
436 Ok(())
437 }
438}
439
440impl Into<Header> for StrictTransportSecurity {
441 fn into(self) -> Header {
442 ("Strict-Transport-Security", self.to_string())
443 }
444}
445
446/// Manages `X-Content-Type-Options` header
447///
448/// The X-Content-Type-Options response HTTP header is a marker used by the server to indicate that the MIME types advertised in the Content-Type headers should not be changed and be followed. This allows to opt-out of MIME type sniffing, or, in other words, it is a way to say that the webmasters knew what they were doing.
449///
450/// # Values
451///
452/// - nosniff: Prevents the browser from MIME-sniffing a response away from the declared content-type. This also applies to Google Chrome, when downloading extensions.
453///
454/// # Examples
455///
456/// ```
457/// use helmet_core::XContentTypeOptions;
458///
459/// let x_content_type_options = XContentTypeOptions::nosniff();
460/// ```
461#[derive(Clone)]
462pub enum XContentTypeOptions {
463 NoSniff,
464}
465
466impl XContentTypeOptions {
467 pub fn nosniff() -> Self {
468 Self::NoSniff
469 }
470}
471
472impl XContentTypeOptions {
473 fn as_str(&self) -> &'static str {
474 match self {
475 XContentTypeOptions::NoSniff => "nosniff",
476 }
477 }
478}
479
480impl Display for XContentTypeOptions {
481 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
482 match self {
483 XContentTypeOptions::NoSniff => write!(f, "nosniff"),
484 }
485 }
486}
487
488impl Into<Header> for XContentTypeOptions {
489 fn into(self) -> Header {
490 ("X-Content-Type-Options", self.as_str().to_owned())
491 }
492}
493
494/// Manages `X-DNS-Prefetch-Control` header
495///
496/// The X-DNS-Prefetch-Control HTTP response header controls DNS prefetching, a feature by which browsers proactively perform domain name resolution on both links that the user may choose to follow as well as URLs for items referenced by the document, including images, CSS, JavaScript, and so forth.
497///
498/// # Values
499///
500/// - off: Disable DNS prefetching.
501/// - on: Enable DNS prefetching, allowing the browser to proactively perform domain name resolution on both links that the user may choose to follow as well as URLs for items referenced by the document, including images, CSS, JavaScript, and so forth.
502///
503/// # Examples
504///
505/// ```
506/// use helmet_core::XDNSPrefetchControl;
507///
508/// let x_dns_prefetch_control = XDNSPrefetchControl::off();
509/// ```
510#[derive(Clone)]
511pub enum XDNSPrefetchControl {
512 Off,
513 On,
514}
515
516impl XDNSPrefetchControl {
517 pub fn off() -> Self {
518 Self::Off
519 }
520
521 pub fn on() -> Self {
522 Self::On
523 }
524}
525
526impl XDNSPrefetchControl {
527 fn as_str(&self) -> &'static str {
528 match self {
529 XDNSPrefetchControl::Off => "off",
530 XDNSPrefetchControl::On => "on",
531 }
532 }
533}
534
535impl Display for XDNSPrefetchControl {
536 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
537 match self {
538 XDNSPrefetchControl::Off => write!(f, "off"),
539 XDNSPrefetchControl::On => write!(f, "on"),
540 }
541 }
542}
543
544impl Into<Header> for XDNSPrefetchControl {
545 fn into(self) -> Header {
546 ("X-DNS-Prefetch-Control", self.as_str().to_owned())
547 }
548}
549
550/// Manages `X-Download-Options` header
551///
552/// The X-Download-Options HTTP response header indicates that the browser (Internet Explorer) should not display the option to "Open" a file that has been downloaded from an application, to prevent phishing attacks that could trick users into opening potentially malicious content that could infect their computer.
553///
554/// # Values
555///
556/// - noopen: Prevents Internet Explorer from executing downloads in your site’s context.
557///
558/// # Examples
559///
560/// ```
561/// use helmet_core::XDownloadOptions;
562///
563/// let x_download_options = XDownloadOptions::noopen();
564/// ```
565#[derive(Clone)]
566pub enum XDownloadOptions {
567 NoOpen,
568}
569
570impl XDownloadOptions {
571 pub fn noopen() -> Self {
572 Self::NoOpen
573 }
574}
575
576impl XDownloadOptions {
577 fn as_str(&self) -> &'static str {
578 match self {
579 XDownloadOptions::NoOpen => "noopen",
580 }
581 }
582}
583
584impl Display for XDownloadOptions {
585 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
586 match self {
587 XDownloadOptions::NoOpen => write!(f, "noopen"),
588 }
589 }
590}
591
592impl Into<Header> for XDownloadOptions {
593 fn into(self) -> Header {
594 ("X-Download-Options", self.as_str().to_owned())
595 }
596}
597
598/// Manages `X-Frame-Options` header
599///
600/// The X-Frame-Options HTTP response header can be used to to avoid click-jacking attacks by preventing the content to be included in other websites.
601///
602/// # Values
603///
604/// - deny: The page cannot be displayed in a frame, regardless of the site attempting to do so.
605/// - sameorigin: The page can only be displayed in a frame on the same origin as the page itself.
606/// - allow-from: The page can only be displayed in a frame on the specified origin. Requires a URI as an argument.
607///
608/// # Examples
609///
610/// ```
611/// use helmet_core::XFrameOptions;
612///
613/// let x_frame_options = XFrameOptions::deny();
614///
615/// let x_frame_options = XFrameOptions::same_origin();
616///
617/// let x_frame_options = XFrameOptions::allow_from("https://example.com");
618/// ```
619#[derive(Clone)]
620pub enum XFrameOptions {
621 Deny,
622 SameOrigin,
623 // deprecated - use Content-Security-Policy instead see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options#allow-from_origin
624 AllowFrom(String),
625}
626
627impl XFrameOptions {
628 pub fn deny() -> Self {
629 Self::Deny
630 }
631
632 pub fn same_origin() -> Self {
633 Self::SameOrigin
634 }
635
636 pub fn allow_from(uri: &str) -> Self {
637 Self::AllowFrom(uri.to_string())
638 }
639}
640
641impl Display for XFrameOptions {
642 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
643 match self {
644 XFrameOptions::Deny => write!(f, "DENY"),
645 XFrameOptions::SameOrigin => write!(f, "SAMEORIGIN"),
646 XFrameOptions::AllowFrom(uri) => write!(f, "ALLOW-FROM {}", uri),
647 }
648 }
649}
650
651impl Into<Header> for XFrameOptions {
652 fn into(self) -> Header {
653 ("X-Frame-Options", self.to_string())
654 }
655}
656
657/// Manages `X-Permitted-Cross-Domain-Policies` header
658///
659/// The X-Permitted-Cross-Domain-Policies HTTP response header determines whether cross-domain policy files (crossdomain.xml and clientaccesspolicy.xml) will be ignored by Flash and Adobe Acrobat in subsequent requests.
660///
661/// # Values
662///
663/// - none: No policy file is allowed.
664/// - master-only: Only a master policy file, but no other policy files, is allowed.
665/// - by-content-type: A policy file is allowed if its MIME type matches the Content-Type of the requested resource.
666/// - by-ftp-filename: A policy file is allowed if its URL matches the URL of the requested resource.
667/// - all: Any policy file is allowed.
668///
669/// # Examples
670///
671/// ```
672/// use helmet_core::XPermittedCrossDomainPolicies;
673///
674/// let x_permitted_cross_domain_policies = XPermittedCrossDomainPolicies::none();
675///
676/// let x_permitted_cross_domain_policies = XPermittedCrossDomainPolicies::master_only();
677///
678/// let x_permitted_cross_domain_policies = XPermittedCrossDomainPolicies::by_content_type();
679///
680/// let x_permitted_cross_domain_policies = XPermittedCrossDomainPolicies::by_ftp_filename();
681///
682/// let x_permitted_cross_domain_policies = XPermittedCrossDomainPolicies::all();
683/// ```
684#[derive(Clone)]
685pub enum XPermittedCrossDomainPolicies {
686 None,
687 MasterOnly,
688 ByContentType,
689 ByFtpFilename,
690 All,
691}
692
693impl XPermittedCrossDomainPolicies {
694 pub fn none() -> Self {
695 Self::None
696 }
697
698 pub fn master_only() -> Self {
699 Self::MasterOnly
700 }
701
702 pub fn by_content_type() -> Self {
703 Self::ByContentType
704 }
705
706 pub fn by_ftp_filename() -> Self {
707 Self::ByFtpFilename
708 }
709
710 pub fn all() -> Self {
711 Self::All
712 }
713}
714
715impl XPermittedCrossDomainPolicies {
716 fn as_str(&self) -> &'static str {
717 match self {
718 XPermittedCrossDomainPolicies::None => "none",
719 XPermittedCrossDomainPolicies::MasterOnly => "master-only",
720 XPermittedCrossDomainPolicies::ByContentType => "by-content-type",
721 XPermittedCrossDomainPolicies::ByFtpFilename => "by-ftp-filename",
722 XPermittedCrossDomainPolicies::All => "all",
723 }
724 }
725}
726
727impl Display for XPermittedCrossDomainPolicies {
728 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
729 match self {
730 XPermittedCrossDomainPolicies::None => write!(f, "none"),
731 XPermittedCrossDomainPolicies::MasterOnly => write!(f, "master-only"),
732 XPermittedCrossDomainPolicies::ByContentType => write!(f, "by-content-type"),
733 XPermittedCrossDomainPolicies::ByFtpFilename => write!(f, "by-ftp-filename"),
734 XPermittedCrossDomainPolicies::All => write!(f, "all"),
735 }
736 }
737}
738
739impl Into<Header> for XPermittedCrossDomainPolicies {
740 fn into(self) -> Header {
741 (
742 "X-Permitted-Cross-Domain-Policies",
743 self.as_str().to_owned(),
744 )
745 }
746}
747
748/// Manages `X-XSS-Protection` header
749///
750/// The HTTP X-XSS-Protection response header is a feature of Internet Explorer, Chrome and Safari that stops pages from loading when they detect reflected cross-site scripting (XSS) attacks. Although these protections are largely unnecessary in modern browsers when sites implement a strong Content-Security-Policy that disables the use of inline JavaScript ('unsafe-inline'), they can still provide protections for users of older web browsers that don't yet support CSP.
751///
752/// # Values
753///
754/// - 0: Disables XSS filtering.
755/// - 1: Enables XSS filtering (usually default in browsers).
756/// - 1; mode=block: Enables XSS filtering. Rather than sanitizing the page, the browser will prevent rendering of the page if an attack is detected.
757/// - 1; report=<reporting-URI>: Enables XSS filtering. If a cross-site scripting attack is detected, the browser will sanitize the page and report the violation. This uses the functionality of the CSP report-uri directive to send a report.
758///
759/// # Examples
760///
761/// ```
762/// use helmet_core::XXSSProtection;
763///
764/// let x_xss_protection = XXSSProtection::on();
765///
766/// let x_xss_protection = XXSSProtection::off();
767///
768/// let x_xss_protection = XXSSProtection::on().mode_block();
769///
770/// let x_xss_protection = XXSSProtection::on().report("https://example.com");
771///
772/// let x_xss_protection = XXSSProtection::on().mode_block().report("https://example.com");
773/// ```
774#[derive(Clone)]
775pub struct XXSSProtection {
776 on: bool,
777 mode_block: bool,
778 report: Option<String>,
779}
780
781impl XXSSProtection {
782 /// Disables XSS filtering.
783 pub fn off() -> Self {
784 Self {
785 on: false,
786 mode_block: false,
787 report: None,
788 }
789 }
790
791 /// Enables XSS filtering (usually default in browsers).
792 pub fn on() -> Self {
793 Self {
794 on: true,
795 mode_block: false,
796 report: None,
797 }
798 }
799
800 /// Enables XSS filtering. Rather than sanitizing the page, the browser will prevent rendering of the page if an attack is detected.
801 pub fn mode_block(mut self) -> Self {
802 self.mode_block = true;
803 self
804 }
805
806 /// Enables XSS filtering. If a cross-site scripting attack is detected, the browser will sanitize the page and report the violation. This uses the functionality of the CSP report-uri directive to send a report.
807 pub fn report(mut self, report: &str) -> Self {
808 self.report = Some(report.to_string());
809 self
810 }
811}
812
813impl Display for XXSSProtection {
814 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
815 if self.on {
816 write!(f, "1")?;
817 if self.mode_block {
818 write!(f, "; mode=block")?;
819 }
820 if let Some(report) = &self.report {
821 write!(f, "; report={}", report)?;
822 }
823 } else {
824 write!(f, "0")?;
825 }
826 Ok(())
827 }
828}
829
830impl Into<Header> for XXSSProtection {
831 fn into(self) -> Header {
832 ("X-XSS-Protection", self.to_string())
833 }
834}
835
836/// Manages `X-Powered-By` header
837///
838/// ntex does not set `X-Powered-By` header by default.
839/// Instead of silencing the header, Helmet allows you to set it to a custom value.
840/// This can be useful against primitive fingerprinting.
841///
842/// # Examples
843///
844/// ```
845/// use helmet_core::XPoweredBy;
846///
847/// let x_powered_by = XPoweredBy::new("PHP 4.2.0");
848/// ```
849#[derive(Clone)]
850pub struct XPoweredBy(String);
851
852impl XPoweredBy {
853 /// Set the `X-Powered-By` header to a custom value.
854 pub fn new(comment: &str) -> Self {
855 Self(comment.to_string())
856 }
857}
858
859impl Display for XPoweredBy {
860 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
861 write!(f, "{}", self.0)?;
862 Ok(())
863 }
864}
865
866impl Into<Header> for XPoweredBy {
867 fn into(self) -> Header {
868 ("X-Powered-By", self.to_string())
869 }
870}
871
872/// Manages `Content-Security-Policy` header
873///
874/// The HTTP Content-Security-Policy response header allows web site administrators to control resources the user agent is allowed to load for a given page. With a few exceptions, policies mostly involve specifying server origins and script endpoints. This helps guard against cross-site scripting attacks (XSS).
875///
876/// # Directives
877///
878/// - child-src: Defines valid sources for web workers and nested browsing contexts loaded using elements such as `<frame>` and `<iframe>`.
879/// - connect-src: Applies to XMLHttpRequest (AJAX), WebSocket or EventSource. If not allowed the browser emulates a 400 HTTP status code.
880/// - default-src: The default-src is the default policy for loading content such as JavaScript, Images, CSS, Font's, AJAX requests, Frames, HTML5 Media. See the list of directives to see which values are allowed as default.
881/// - font-src: Defines valid sources for fonts loaded using @font-face.
882/// - frame-src: Defines valid sources for nested browsing contexts loading using elements such as `<frame>` and `<iframe>`.
883/// - img-src: Defines valid sources of images and favicons.
884/// - manifest-src: Specifies which manifest can be applied to the resource.
885/// - media-src: Defines valid sources for loading media using the `<audio>` and `<video>` elements.
886/// - object-src: Defines valid sources for the `<object>`, `<embed>`, and `<applet>` elements.
887/// - prefetch-src: Specifies which referrer to use when fetching the resource.
888/// - script-src: Defines valid sources for JavaScript.
889/// - script-src-elem: Defines valid sources for JavaScript inline event handlers.
890/// - script-src-attr: Defines valid sources for JavaScript inline event handlers.
891/// - style-src: Defines valid sources for stylesheets.
892/// - style-src-elem: Defines valid sources for stylesheets inline event handlers.
893/// - style-src-attr: Defines valid sources for stylesheets inline event handlers.
894/// - worker-src: Defines valid sources for Worker, SharedWorker, or ServiceWorker scripts.
895/// - base-uri: Restricts the URLs which can be used in a document's `<base>` element.
896/// - sandbox: Enables a sandbox for the requested resource similar to the iframe sandbox attribute. The sandbox applies a same origin policy, prevents popups, plugins and script execution is blocked. You can keep the sandbox value empty to keep all restrictions in place, or add values: allow-forms allow-same-origin allow-scripts allow-popups, allow-modals, allow-orientation-lock, allow-pointer-lock, allow-presentation, allow-popups-to-escape-sandbox, allow-top-navigation, allow-top-navigation-by-user-activation.
897/// - form-action: Restricts the URLs which can be used as the target of a form submissions from a given context.
898/// - frame-ancestors: Specifies valid parents that may embed a page using `<frame>`, `<iframe>`, `<object>`, `<embed>`, or `<applet>`.
899/// - report-to: Enables reporting of violations.
900/// - require-trusted-types-for: Specifies which trusted types are required by a resource.
901/// - trusted-types: Specifies which trusted types are defined by a resource.
902/// - upgrade-insecure-requests: Block HTTP requests on insecure elements.
903///
904/// # Examples
905///
906/// ```
907/// use helmet_core::ContentSecurityPolicy;
908///
909/// let content_security_policy = ContentSecurityPolicy::default()
910/// .child_src(vec!["'self'", "https://youtube.com"])
911/// .connect_src(vec!["'self'", "https://youtube.com"])
912/// .default_src(vec!["'self'", "https://youtube.com"])
913/// .font_src(vec!["'self'", "https://youtube.com"]);
914/// ```
915#[derive(Clone)]
916pub enum ContentSecurityPolicyDirective<'a> {
917 /// Warning: Instead of child-src, if you want to regulate nested browsing contexts and workers, you should use the frame-src and worker-src directives, respectively.
918 ChildSrc(Vec<&'a str>),
919 /// Applies to XMLHttpRequest (AJAX), WebSocket or EventSource. If not allowed the browser emulates a 400 HTTP status code.
920 ConnectSrc(Vec<&'a str>),
921 /// The default-src is the default policy for loading content such as JavaScript, Images, CSS, Font's, AJAX requests, Frames, HTML5 Media. See the list of directives to see which values are allowed as default.
922 DefaultSrc(Vec<&'a str>),
923 /// Defines valid sources for fonts loaded using @font-face.
924 FontSrc(Vec<&'a str>),
925 /// Defines valid sources for nested browsing contexts loading using elements such as `<frame>` and `<iframe>`.
926 FrameSrc(Vec<&'a str>),
927 /// Defines valid sources of images and favicons.
928 ImgSrc(Vec<&'a str>),
929 /// Specifies which manifest can be applied to the resource.
930 ManifestSrc(Vec<&'a str>),
931 /// Defines valid sources for loading media using the `<audio>` and `<video>` elements.
932 MediaSrc(Vec<&'a str>),
933 /// Defines valid sources for the `<object>`, `<embed>`, and `<applet>` elements.
934 ObjectSrc(Vec<&'a str>),
935 /// Specifies which referrer to use when fetching the resource.
936 PrefetchSrc(Vec<&'a str>),
937 /// Defines valid sources for JavaScript.
938 ScriptSrc(Vec<&'a str>),
939 /// Defines valid sources for JavaScript inline event handlers.
940 ScriptSrcElem(Vec<&'a str>),
941 /// Defines valid sources for JavaScript inline event handlers.
942 ScriptSrcAttr(Vec<&'a str>),
943 /// Defines valid sources for stylesheets.
944 StyleSrc(Vec<&'a str>),
945 /// Defines valid sources for stylesheets inline event handlers.
946 StyleSrcElem(Vec<&'a str>),
947 /// Defines valid sources for stylesheets inline event handlers.
948 StyleSrcAttr(Vec<&'a str>),
949 /// Defines valid sources for Worker, SharedWorker, or ServiceWorker scripts.
950 WorkerSrc(Vec<&'a str>),
951 // Document directives
952 /// Restricts the URLs which can be used in a document's `<base>` element.
953 BaseUri(Vec<&'a str>),
954 /// Enables a sandbox for the requested resource similar to the iframe sandbox attribute. The sandbox applies a same origin policy, prevents popups, plugins and script execution is blocked. You can keep the sandbox value empty to keep all restrictions in place, or add values: allow-forms allow-same-origin allow-scripts allow-popups, allow-modals, allow-orientation-lock, allow-pointer-lock, allow-presentation, allow-popups-to-escape-sandbox, allow-top-navigation, allow-top-navigation-by-user-activation.
955 Sandbox(Vec<&'a str>),
956 // Navigation directives
957 /// Restricts the URLs which can be used as the target of a form submissions from a given context.
958 FormAction(Vec<&'a str>),
959 /// Specifies valid parents that may embed a page using `<frame>`, `<iframe>`, `<object>`, `<embed>`, or `<applet>`.
960 FrameAncestors(Vec<&'a str>),
961 // Reporting directives
962 /// Enables reporting of violations.
963 ///
964 /// report-uri is deprecated, however, it is still supported by browsers that don't yet support report-to. ReportTo will apply both to report-uri and report-to with the same values, to support browsers that support both.
965 ReportTo(Vec<&'a str>),
966 // Other
967 /// Specifies which trusted types are required by a resource.
968 RequireTrustedTypesFor(Vec<&'a str>),
969 /// Specifies which trusted types are defined by a resource.
970 TrustedTypes(Vec<&'a str>),
971 /// Block HTTP requests on insecure elements.
972 UpgradeInsecureRequests,
973}
974
975impl<'a> ContentSecurityPolicyDirective<'a> {
976 /// child-src: Defines valid sources for web workers and nested browsing contexts loaded using elements such as `<frame>`` and `<iframe>`.
977 pub fn child_src(values: Vec<&'a str>) -> Self {
978 Self::ChildSrc(values)
979 }
980
981 /// connect-src: Applies to XMLHttpRequest (AJAX), WebSocket or EventSource. If not allowed the browser emulates a 400 HTTP status code.
982 pub fn connect_src(values: Vec<&'a str>) -> Self {
983 Self::ConnectSrc(values)
984 }
985
986 /// default-src: The default-src is the default policy for loading content such as JavaScript, Images, CSS, Font's, AJAX requests, Frames, HTML5 Media. See the list of directives to see which values are allowed as default.
987 pub fn default_src(values: Vec<&'a str>) -> Self {
988 Self::DefaultSrc(values)
989 }
990
991 /// font-src: Defines valid sources for fonts loaded using @font-face.
992 pub fn font_src(values: Vec<&'a str>) -> Self {
993 Self::FontSrc(values)
994 }
995
996 /// frame-src: Defines valid sources for nested browsing contexts loading using elements such as `<frame>` and `<iframe>`.
997 pub fn frame_src(values: Vec<&'a str>) -> Self {
998 Self::FrameSrc(values)
999 }
1000
1001 /// img-src: Defines valid sources of images and favicons.
1002 pub fn img_src(values: Vec<&'a str>) -> Self {
1003 Self::ImgSrc(values)
1004 }
1005
1006 /// manifest-src: Specifies which manifest can be applied to the resource.
1007 pub fn manifest_src(values: Vec<&'a str>) -> Self {
1008 Self::ManifestSrc(values)
1009 }
1010
1011 /// media-src: Defines valid sources for loading media using the `<audio>` and `<video>` elements.
1012 pub fn media_src(values: Vec<&'a str>) -> Self {
1013 Self::MediaSrc(values)
1014 }
1015
1016 /// object-src: Defines valid sources for the `<object>`, `<embed>`, and `<applet>` elements.
1017 pub fn object_src(values: Vec<&'a str>) -> Self {
1018 Self::ObjectSrc(values)
1019 }
1020
1021 /// prefetch-src: Specifies which referrer to use when fetching the resource.
1022 pub fn prefetch_src(values: Vec<&'a str>) -> Self {
1023 Self::PrefetchSrc(values)
1024 }
1025
1026 /// script-src: Defines valid sources for JavaScript.
1027 pub fn script_src(values: Vec<&'a str>) -> Self {
1028 Self::ScriptSrc(values)
1029 }
1030
1031 /// script-src-elem: Defines valid sources for JavaScript inline event handlers.
1032 pub fn script_src_elem(values: Vec<&'a str>) -> Self {
1033 Self::ScriptSrcElem(values)
1034 }
1035
1036 /// script-src-attr: Defines valid sources for JavaScript inline event handlers.
1037 pub fn script_src_attr(values: Vec<&'a str>) -> Self {
1038 Self::ScriptSrcAttr(values)
1039 }
1040
1041 /// style-src: Defines valid sources for stylesheets.
1042 pub fn style_src(values: Vec<&'a str>) -> Self {
1043 Self::StyleSrc(values)
1044 }
1045
1046 /// style-src-elem: Defines valid sources for stylesheets inline event handlers.
1047 pub fn style_src_elem(values: Vec<&'a str>) -> Self {
1048 Self::StyleSrcElem(values)
1049 }
1050
1051 /// style-src-attr: Defines valid sources for stylesheets inline event handlers.
1052 pub fn style_src_attr(values: Vec<&'a str>) -> Self {
1053 Self::StyleSrcAttr(values)
1054 }
1055
1056 /// worker-src: Defines valid sources for Worker, SharedWorker, or ServiceWorker scripts.
1057 pub fn worker_src(values: Vec<&'a str>) -> Self {
1058 Self::WorkerSrc(values)
1059 }
1060
1061 /// base-uri: Restricts the URLs which can be used in a document's `<base>` element.
1062 pub fn base_uri(values: Vec<&'a str>) -> Self {
1063 Self::BaseUri(values)
1064 }
1065
1066 /// sandbox: Enables a sandbox for the requested resource similar to the iframe sandbox attribute. The sandbox applies a same origin policy, prevents popups, plugins and script execution is blocked. You can keep the sandbox value empty to keep all restrictions in place, or add values: allow-forms allow-same-origin allow-scripts allow-popups, allow-modals, allow-orientation-lock, allow-pointer-lock, allow-presentation, allow-popups-to-escape-sandbox, allow-top-navigation, allow-top-navigation-by-user-activation.
1067 pub fn sandbox(values: Vec<&'a str>) -> Self {
1068 Self::Sandbox(values)
1069 }
1070
1071 /// form-action: Restricts the URLs which can be used as the target of a form submissions from a given context.
1072 pub fn form_action(values: Vec<&'a str>) -> Self {
1073 Self::FormAction(values)
1074 }
1075
1076 /// frame-ancestors: Specifies valid parents that may embed a page using `<frame>`, `<iframe>`, `<object>`, `<embed>`, or `<applet>`.
1077 pub fn frame_ancestors(values: Vec<&'a str>) -> Self {
1078 Self::FrameAncestors(values)
1079 }
1080
1081 /// report-to: Enables reporting of violations.
1082 pub fn report_to(values: Vec<&'a str>) -> Self {
1083 Self::ReportTo(values)
1084 }
1085
1086 /// require-trusted-types-for: Specifies which trusted types are required by a resource.
1087 pub fn require_trusted_types_for(values: Vec<&'a str>) -> Self {
1088 Self::RequireTrustedTypesFor(values)
1089 }
1090
1091 /// trusted-types: Specifies which trusted types are defined by a resource.
1092 pub fn trusted_types(values: Vec<&'a str>) -> Self {
1093 Self::TrustedTypes(values)
1094 }
1095
1096 /// Block HTTP requests on insecure elements.
1097 pub fn upgrade_insecure_requests() -> Self {
1098 Self::UpgradeInsecureRequests
1099 }
1100}
1101
1102impl Display for ContentSecurityPolicyDirective<'_> {
1103 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1104 match self {
1105 ContentSecurityPolicyDirective::ChildSrc(values) => {
1106 write!(f, "child-src {}", values.join(" "))
1107 }
1108 ContentSecurityPolicyDirective::ConnectSrc(values) => {
1109 write!(f, "connect-src {}", values.join(" "))
1110 }
1111 ContentSecurityPolicyDirective::DefaultSrc(values) => {
1112 write!(f, "default-src {}", values.join(" "))
1113 }
1114 ContentSecurityPolicyDirective::FontSrc(values) => {
1115 write!(f, "font-src {}", values.join(" "))
1116 }
1117 ContentSecurityPolicyDirective::FrameSrc(values) => {
1118 write!(f, "frame-src {}", values.join(" "))
1119 }
1120 ContentSecurityPolicyDirective::ImgSrc(values) => {
1121 write!(f, "img-src {}", values.join(" "))
1122 }
1123 ContentSecurityPolicyDirective::ManifestSrc(values) => {
1124 write!(f, "manifest-src {}", values.join(" "))
1125 }
1126 ContentSecurityPolicyDirective::MediaSrc(values) => {
1127 write!(f, "media-src {}", values.join(" "))
1128 }
1129 ContentSecurityPolicyDirective::ObjectSrc(values) => {
1130 write!(f, "object-src {}", values.join(" "))
1131 }
1132 ContentSecurityPolicyDirective::PrefetchSrc(values) => {
1133 write!(f, "prefetch-src {}", values.join(" "))
1134 }
1135 ContentSecurityPolicyDirective::ScriptSrc(values) => {
1136 write!(f, "script-src {}", values.join(" "))
1137 }
1138 ContentSecurityPolicyDirective::ScriptSrcElem(values) => {
1139 write!(f, "script-src-elem {}", values.join(" "))
1140 }
1141 ContentSecurityPolicyDirective::ScriptSrcAttr(values) => {
1142 write!(f, "script-src-attr {}", values.join(" "))
1143 }
1144 ContentSecurityPolicyDirective::StyleSrc(values) => {
1145 write!(f, "style-src {}", values.join(" "))
1146 }
1147 ContentSecurityPolicyDirective::StyleSrcElem(values) => {
1148 write!(f, "style-src-elem {}", values.join(" "))
1149 }
1150 ContentSecurityPolicyDirective::StyleSrcAttr(values) => {
1151 write!(f, "style-src-attr {}", values.join(" "))
1152 }
1153 ContentSecurityPolicyDirective::WorkerSrc(values) => {
1154 write!(f, "worker-src {}", values.join(" "))
1155 }
1156 ContentSecurityPolicyDirective::BaseUri(values) => {
1157 write!(f, "base-uri {}", values.join(" "))
1158 }
1159 ContentSecurityPolicyDirective::Sandbox(values) => {
1160 write!(f, "sandbox {}", values.join(" "))
1161 }
1162 ContentSecurityPolicyDirective::FormAction(values) => {
1163 write!(f, "form-action {}", values.join(" "))
1164 }
1165 ContentSecurityPolicyDirective::FrameAncestors(values) => {
1166 write!(f, "frame-ancestors {}", values.join(" "))
1167 }
1168 ContentSecurityPolicyDirective::ReportTo(values) => {
1169 let values = values.join(" ");
1170 write!(f, "report-to {}; report-uri {}", values, values)
1171 }
1172 ContentSecurityPolicyDirective::RequireTrustedTypesFor(values) => {
1173 write!(f, "require-trusted-types-for {}", values.join(" "))
1174 }
1175 ContentSecurityPolicyDirective::TrustedTypes(values) => {
1176 write!(f, "trusted-types {}", values.join(" "))
1177 }
1178 ContentSecurityPolicyDirective::UpgradeInsecureRequests => {
1179 write!(f, "upgrade-insecure-requests")
1180 }
1181 }
1182 }
1183}
1184
1185/// Manages `Content-Security-Policy` header
1186///
1187/// The HTTP Content-Security-Policy response header allows web site administrators to control resources the user agent is allowed to load for a given page. With a few exceptions, policies mostly involve specifying server origins and script endpoints. This helps guard against cross-site scripting attacks (XSS).
1188///
1189/// # Examples
1190///
1191/// ```
1192/// use helmet_core::ContentSecurityPolicy;
1193///
1194/// let content_security_policy = ContentSecurityPolicy::default()
1195/// .child_src(vec!["'self'", "https://youtube.com"])
1196/// .connect_src(vec!["'self'", "https://youtube.com"])
1197/// .default_src(vec!["'self'", "https://youtube.com"])
1198/// .font_src(vec!["'self'", "https://youtube.com"]);
1199/// ```
1200///
1201/// ## Report only
1202///
1203/// In report only mode, the browser will not block the request, but will send a report to the specified URI.
1204///
1205/// Make sure to set the `report-to` directive.
1206///
1207/// ```
1208/// use helmet_core::ContentSecurityPolicy;
1209///
1210/// let content_security_policy = ContentSecurityPolicy::default()
1211/// .child_src(vec!["'self'", "https://youtube.com"])
1212/// .report_to(vec!["https://example.com/report"])
1213/// .report_only();
1214/// ```
1215#[derive(Clone)]
1216pub struct ContentSecurityPolicy<'a> {
1217 directives: Vec<ContentSecurityPolicyDirective<'a>>,
1218 report_only: bool,
1219}
1220
1221impl<'a> ContentSecurityPolicy<'a> {
1222 pub fn new() -> Self {
1223 Self {
1224 directives: Vec::new(),
1225 report_only: false,
1226 }
1227 }
1228
1229 fn directive(mut self, directive: ContentSecurityPolicyDirective<'a>) -> Self {
1230 self.directives.push(directive);
1231 self
1232 }
1233
1234 /// child-src: Defines valid sources for web workers and nested browsing contexts loaded using elements such as `<frame>` and `<iframe>`.
1235 pub fn child_src(self, values: Vec<&'a str>) -> Self {
1236 self.directive(ContentSecurityPolicyDirective::child_src(values))
1237 }
1238
1239 /// connect-src: Applies to XMLHttpRequest (AJAX), WebSocket or EventSource. If not allowed the browser emulates a 400 HTTP status code.
1240 pub fn connect_src(self, values: Vec<&'a str>) -> Self {
1241 self.directive(ContentSecurityPolicyDirective::connect_src(values))
1242 }
1243
1244 /// default-src: The default-src is the default policy for loading content such as JavaScript, Images, CSS, Font's, AJAX requests, Frames, HTML5 Media. See the list of directives to see which values are allowed as default.
1245 pub fn default_src(self, values: Vec<&'a str>) -> Self {
1246 self.directive(ContentSecurityPolicyDirective::default_src(values))
1247 }
1248
1249 /// font-src: Defines valid sources for fonts loaded using @font-face.
1250 pub fn font_src(self, values: Vec<&'a str>) -> Self {
1251 self.directive(ContentSecurityPolicyDirective::font_src(values))
1252 }
1253
1254 /// frame-src: Defines valid sources for nested browsing contexts loading using elements such as `<frame>` and `<iframe>`.
1255 pub fn frame_src(self, values: Vec<&'a str>) -> Self {
1256 self.directive(ContentSecurityPolicyDirective::frame_src(values))
1257 }
1258
1259 /// img-src: Defines valid sources of images and favicons.
1260 pub fn img_src(self, values: Vec<&'a str>) -> Self {
1261 self.directive(ContentSecurityPolicyDirective::img_src(values))
1262 }
1263
1264 /// manifest-src: Specifies which manifest can be applied to the resource.
1265 pub fn manifest_src(self, values: Vec<&'a str>) -> Self {
1266 self.directive(ContentSecurityPolicyDirective::manifest_src(values))
1267 }
1268
1269 /// media-src: Defines valid sources for loading media using the `<audio>` and `<video>` elements.
1270 pub fn media_src(self, values: Vec<&'a str>) -> Self {
1271 self.directive(ContentSecurityPolicyDirective::media_src(values))
1272 }
1273
1274 /// object-src: Defines valid sources for the `<object>`, `<embed>`, and `<applet>` elements.
1275 pub fn object_src(self, values: Vec<&'a str>) -> Self {
1276 self.directive(ContentSecurityPolicyDirective::object_src(values))
1277 }
1278
1279 /// prefetch-src: Specifies which referrer to use when fetching the resource.
1280 pub fn prefetch_src(self, values: Vec<&'a str>) -> Self {
1281 self.directive(ContentSecurityPolicyDirective::prefetch_src(values))
1282 }
1283
1284 /// script-src: Defines valid sources for JavaScript.
1285 pub fn script_src(self, values: Vec<&'a str>) -> Self {
1286 self.directive(ContentSecurityPolicyDirective::script_src(values))
1287 }
1288
1289 /// script-src-elem: Defines valid sources for JavaScript inline event handlers.
1290 pub fn script_src_elem(self, values: Vec<&'a str>) -> Self {
1291 self.directive(ContentSecurityPolicyDirective::script_src_elem(values))
1292 }
1293
1294 /// script-src-attr: Defines valid sources for JavaScript inline event handlers.
1295 pub fn script_src_attr(self, values: Vec<&'a str>) -> Self {
1296 self.directive(ContentSecurityPolicyDirective::script_src_attr(values))
1297 }
1298
1299 /// style-src: Defines valid sources for stylesheets.
1300 pub fn style_src(self, values: Vec<&'a str>) -> Self {
1301 self.directive(ContentSecurityPolicyDirective::style_src(values))
1302 }
1303
1304 /// style-src-elem: Defines valid sources for stylesheets inline event handlers.
1305 pub fn style_src_elem(self, values: Vec<&'a str>) -> Self {
1306 self.directive(ContentSecurityPolicyDirective::style_src_elem(values))
1307 }
1308
1309 /// style-src-attr: Defines valid sources for stylesheets inline event handlers.
1310 pub fn style_src_attr(self, values: Vec<&'a str>) -> Self {
1311 self.directive(ContentSecurityPolicyDirective::style_src_attr(values))
1312 }
1313
1314 /// worker-src: Defines valid sources for Worker, SharedWorker, or ServiceWorker scripts.
1315 pub fn worker_src(self, values: Vec<&'a str>) -> Self {
1316 self.directive(ContentSecurityPolicyDirective::worker_src(values))
1317 }
1318
1319 /// base-uri: Restricts the URLs which can be used in a document's `<base>` element.
1320 pub fn base_uri(self, values: Vec<&'a str>) -> Self {
1321 self.directive(ContentSecurityPolicyDirective::base_uri(values))
1322 }
1323
1324 /// sandbox: Enables a sandbox for the requested resource similar to the iframe sandbox attribute. The sandbox applies a same origin policy, prevents popups, plugins and script execution is blocked. You can keep the sandbox value empty to keep all restrictions in place, or add values: allow-forms allow-same-origin allow-scripts allow-popups, allow-modals, allow-orientation-lock, allow-pointer-lock, allow-presentation, allow-popups-to-escape-sandbox, allow-top-navigation, allow-top-navigation-by-user-activation.
1325 pub fn sandbox(self, values: Vec<&'a str>) -> Self {
1326 self.directive(ContentSecurityPolicyDirective::sandbox(values))
1327 }
1328
1329 /// form-action: Restricts the URLs which can be used as the target of a form submissions from a given context.
1330 pub fn form_action(self, values: Vec<&'a str>) -> Self {
1331 self.directive(ContentSecurityPolicyDirective::form_action(values))
1332 }
1333
1334 /// frame-ancestors: Specifies valid parents that may embed a page using `<frame>`, `<iframe>`, `<object>`, `<embed>`, or `<applet>`.
1335 pub fn frame_ancestors(self, values: Vec<&'a str>) -> Self {
1336 self.directive(ContentSecurityPolicyDirective::frame_ancestors(values))
1337 }
1338
1339 /// report-to: Enables reporting of violations.
1340 pub fn report_to(self, values: Vec<&'a str>) -> Self {
1341 self.directive(ContentSecurityPolicyDirective::report_to(values))
1342 }
1343
1344 /// require-trusted-types-for: Specifies which trusted types are required by a resource.
1345 pub fn require_trusted_types_for(self, values: Vec<&'a str>) -> Self {
1346 self.directive(ContentSecurityPolicyDirective::require_trusted_types_for(
1347 values,
1348 ))
1349 }
1350
1351 /// trusted-types: Specifies which trusted types are defined by a resource.
1352 pub fn trusted_types(self, values: Vec<&'a str>) -> Self {
1353 self.directive(ContentSecurityPolicyDirective::trusted_types(values))
1354 }
1355
1356 /// Block HTTP requests on insecure elements.
1357 pub fn upgrade_insecure_requests(self) -> Self {
1358 self.directive(ContentSecurityPolicyDirective::upgrade_insecure_requests())
1359 }
1360
1361 /// Enable report only mode
1362 ///
1363 /// When set to true, the `Content-Security-Policy-Report-Only` header is set instead of `Content-Security-Policy`.
1364 ///
1365 /// Defaults to false.
1366 ///
1367 /// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only
1368 pub fn report_only(mut self) -> Self {
1369 self.report_only = true;
1370 self
1371 }
1372}
1373
1374impl Display for ContentSecurityPolicy<'_> {
1375 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1376 let directives = self
1377 .directives
1378 .iter()
1379 .map(|d| d.to_string())
1380 .collect::<Vec<String>>()
1381 .join("; ");
1382 write!(f, "{}", directives)
1383 }
1384}
1385
1386impl Default for ContentSecurityPolicy<'_> {
1387 /// Default policy for the Content-Security-Policy header.
1388 ///
1389 /// values:
1390 /// ```text
1391 /// default-src 'self';
1392 /// base-uri 'self';
1393 /// font-src 'self' https: data:;
1394 /// form-action 'self';
1395 /// frame-ancestors 'self';
1396 /// img-src 'self' data:;
1397 /// object-src 'none';
1398 /// script-src 'self';
1399 /// script-src-attr 'none';
1400 /// style-src 'self' https: 'unsafe-inline';
1401 /// upgrade-insecure-requests
1402 /// ```
1403 fn default() -> Self {
1404 Self::new()
1405 .default_src(vec!["'self'"])
1406 .base_uri(vec!["'self'"])
1407 .font_src(vec!["'self'", "https:", "data:"])
1408 .form_action(vec!["'self'"])
1409 .frame_ancestors(vec!["'self'"])
1410 .img_src(vec!["'self'", "data:"])
1411 .object_src(vec!["'none'"])
1412 .script_src(vec!["'self'"])
1413 .script_src_attr(vec!["'none'"])
1414 .style_src(vec!["'self'", "https:", "'unsafe-inline'"])
1415 .upgrade_insecure_requests()
1416 }
1417}
1418
1419impl Into<Header> for ContentSecurityPolicy<'_> {
1420 fn into(self) -> Header {
1421 (
1422 if self.report_only {
1423 "Content-Security-Policy-Report-Only"
1424 } else {
1425 "Content-Security-Policy"
1426 },
1427 self.to_string(),
1428 )
1429 }
1430}
1431
1432/// Helmet security headers middleware for ntex services
1433///
1434/// # Examples
1435///
1436/// ```
1437/// use helmet_core::Helmet;
1438///
1439/// let helmet = Helmet::default();
1440/// ```
1441///
1442/// ## Adding custom headers
1443///
1444/// ```
1445/// use helmet_core::{Helmet, StrictTransportSecurity};
1446///
1447/// let helmet = Helmet::new()
1448/// .add(StrictTransportSecurity::new().max_age(31536000).include_sub_domains());
1449/// ```
1450
1451#[derive(Clone)]
1452pub struct Helmet {
1453 pub headers: Vec<Header>,
1454}
1455
1456#[allow(clippy::should_implement_trait)]
1457impl Helmet {
1458 /// Create new `Helmet` instance without any headers applied
1459 pub fn new() -> Self {
1460 Self {
1461 headers: Vec::new(),
1462 }
1463 }
1464
1465 /// Add header to the middleware
1466 pub fn add(mut self, header: impl Into<Header>) -> Self {
1467 self.headers.push(header.into());
1468 self
1469 }
1470}
1471
1472impl Default for Helmet {
1473 /// Default `Helmet` instance with all headers applied
1474 ///
1475 /// ```text
1476 /// Content-Security-Policy: default-src 'self'; base-uri 'self'; font-src 'self' https: data:; form-action 'self'; frame-ancestors 'self'; img-src 'self' data:; object-src 'none'; script-src 'self'; script-src-attr 'none'; style-src 'self' https: 'unsafe-inline'; upgrade-insecure-requests
1477 /// Cross-Origin-Opener-Policy: same-origin
1478 /// Cross-Origin-Resource-Policy: same-origin
1479 /// Origin-Agent-Cluster: ?1
1480 /// Referrer-Policy: no-referrer
1481 /// Strict-Transport-Security: max-age=15552000; includeSubDomains
1482 /// X-Content-Type-Options: nosniff
1483 /// X-DNS-Prefetch-Control: off
1484 /// X-Download-Options: noopen
1485 /// X-Frame-Options: sameorigin
1486 /// X-Permitted-Cross-Domain-Policies: none
1487 /// X-XSS-Protection: 0
1488 /// ```
1489 fn default() -> Self {
1490 Self::new()
1491 .add(ContentSecurityPolicy::default())
1492 .add(CrossOriginOpenerPolicy::same_origin())
1493 .add(CrossOriginResourcePolicy::same_origin())
1494 .add(OriginAgentCluster(true))
1495 .add(ReferrerPolicy::no_referrer())
1496 .add(
1497 StrictTransportSecurity::new()
1498 .max_age(15552000)
1499 .include_sub_domains(),
1500 )
1501 .add(XContentTypeOptions::nosniff())
1502 .add(XDNSPrefetchControl::off())
1503 .add(XDownloadOptions::noopen())
1504 .add(XFrameOptions::same_origin())
1505 .add(XPermittedCrossDomainPolicies::none())
1506 .add(XXSSProtection::off())
1507 }
1508}