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}