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