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}