Conclusion
HTTP headers are something that is often ignored by developers. Most of the time, it’s because we are too preoccupied with trying to make our APIs work and behave the way we want them to.
HTTP headers are generally an afterthought. This can lead to vulnerabilities and sharing of data that can be easily used to exploit your application. It is not that hard to view HTTP headers in the browser. A user simply needs to right-click, navigate to dev tools, then over to the Network tab and check the headers on a file that was fetched from the server. This will let a malicious user see what kind of techniques they can use to exploit your APIs.
By design, HTTP headers are available for all to see. The browser uses this information to prevent certain things from happening to your site — such as cross-domain hijacking and enforcing the usage of HTTPS.
Using Helmet.js with your Express application is a quick and simple way to create a layer of security by switching from Express defaults to a more secure set of defaults. In addition to this, Helmet.js also lets you configure your HTTP headers with ease through the available modules.
Tránh các lỗ hổng đã biết khác
Dưới đây là một số gợi ý bạn nên tham khảo để tăng cường bảo mật cho website của mình (đọc full tại đây https://blog.risingstack.com/node-js-security-checklist/)
-
Triển khai
rate-limiting
để ngăn chặn tấn công DDOS -
Sử dụng
csurf middleware
để ngăn chặn (CSRF). - Luôn lọc và tiền xử lý user input để ngăn chặn tấn công cross-site scripting (XSS) và command injection.
- Sử dụng parameterized queries hoặc prepared statements để ngăn chặn SQL injection.
- Sử dụng sqlmap để chẩn đoán trước lỗi SQL injection vulnerabilities.
- Sử dụng nmap and sslyze để test cài đặt SSL ciphers, keys…
-
Sử dụng
safe-regex
để đảm bảo tất cả các
regular expressions
không bị ảnh hưởng bởi regular expression denial of service
Tham khảo: https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS https://blog.risingstack.com/node-js-security-checklist/ https://letsencrypt.org/isrg/ https://wiki.mozilla.org/Security/Server_Side_TLS#Recommended_Server_Configurations https://expressjs.com/en/advanced/best-practice-security.html https://msdn.microsoft.com/en-us/library/windows/desktop/aa380515(v=vs.85).aspx
All rights reserved
Helmet.js is a useful Node.js module that helps you secure HTTP headers returned by your Express apps. HTTP headers are an important part of the HTTP protocol, but are generally transparent from the end-user perspective. The headers provide important metadata about the HTTP request or response so the client (browser) and server can send additional information in a transaction.
Why Secure HTTP headers?
Since users do not see HTTP headers, developers have a tendency to ignore them. However, HTTP headers can leak sensitive information about your app inadvertently, so it’s important to configure and use them in a secure way.
A popular way Express apps leak information is through the
X-Powered-By
header. This header informs the browser which server vendor and version you’re using. By default, Express exposes the
X-Powered-By
header and leaks “Express” (usually without a version number). Hackers typically cross-reference this information with a list of publicly disclosed known vulnerabilities, which makes your app a prime target for easy exploits — especially if you’re running an unpatched version of Express.
What is Helmet.js?
Fortunately, Helmet.js makes securing HTTP headers easy for Node.js developers. Helmet.js is a collection of 12 Node modules that interface with Express. Each module provides configuration options for securing different HTTP headers. Here’s a list of the Node modules that are included with Helmet.js:
HTTP Header | Helmet.js Default? | Related Node Module |
Content-Security-Policy | contentSecurityPolicy for setting Content Security Policy | |
Expect-CT | expectCt for handling Certificate Transparency | |
X-DNS-Prefetch-Control | dnsPrefetchControl://helmetjs.github.io/docs/dns-prefetch-control) controls browser DNS prefetching | |
X-Frame-Options | frameguard to prevent clickjacking | |
X-Powered-By | hidePoweredBy to remove the X-Powered-By header | |
Public-Key-Pins | hpkp for HTTP Public Key Pinning | |
Strict-Transport-Security | hsts for HTTP Strict Transport Security | |
X-Download-Options | ieNoOpen sets X-Download-Options for IE8+ | |
Cache-Control | noCache to disable client-side caching | |
X-Content-Type-Options | noSniff to keep clients from sniffing the MIME type | |
Referrer-Policy | referrerPolicyto hide the Referer header | |
X-XSS-Protection | xssFilter adds some small XSS protections |
Sourced from: https://github.com/helmetjs/helmet
For some HTTP headers, Helmet.js automatically defaults to the “secure” option. Others, like
Content-Security-Policy
, require the developer to make an explicit configuration. This is usually because the “best practice” may break functionality or degrade user experience — so configurations must be tuned accordingly.
Helmet.js’s Github page does a great job providing an overview of each HTTP header, the attack scenario, and different Helmet.js configurations you can use. We won’t go into the specifics of each header in this post; instead, we’ll focus on three areas:
- How to inspect your HTTP headers
- How to install Helmet
- An example configuration: Content-Security-Policy
Next, click on the “Network” tab and select an HTTP request made by the browser. Since I am testing on my local machine, I’ve clicked ‘localhost’.
Chances are your Express application isn’t using Helmet.js or securely configuring HTTP headers, so you may see something like this:
How Helmet.js works and how to use it
Helmet.js comes with a collection of Node modules that you can use to interface to Express to increase the HTTP header security. How does it work? It lets you configure the headers and prevent common vulnerabilities such as clickjacking, implementation of strict HTTP, and download options for vulnerable browsers such as IE8.
When you use Helmet.js, you can also configure Content-Security-Policy to force subsequent developers working on public-facing APIs that require HTTP to approach the code with a security-first mindset.
Here is a list of HTTP headers supported by Helmet.js and how to use them.
Content-Security-Policy
helmet.contentSecurityPolicy(options) lets you set the Content-Security-Policy which allows you to mitigate cross-site scripting attacks. If no directive is applied by the developer, the following policy is set as the default:
Here is an example of the module in use:
useDefaults applies all the defaults as stated above and overrides it with the supplied directives directly below.
But what is a Content-Security-Policy — or CSP?
A CSP lets the browser know how to process certain directions and minimize cross-site scripting vulnerabilities. When CSP isn’t set on your headers, the browser is set to accept all HTTP responses by default. This includes resources from external domains.
By default, Helmet.js doesn’t add CSP as part of its default configuration as it can block things like CDN file inclusion — which can negatively impact a user’s experience. While a blanket exclusion of external loading of scripts is not recommended, you can create a whitelist of domains that is monitored and maintained by the development team.
Expect-CT
helmet.expectCT sets the Expect-CT header. This prevents mis-issued SSL certificates. There are three parameters that you can use.
- maxAge – determines the number of sections to expect Certificate Transparency.
- enforce – if true, the user agent should refuse future connections that violate the Certificate Transparency policy. If not set, it defaults to false.
- reportUri – if anything fails, it will report the failure to the URL supplied.
Here is an example of the module in use:
X-DNS-Prefetch-Control
helmet.dnsPrefetchControl lets you set the X-DNS-Prefetch-Control header in Express. This helps control DNS prefetching and improves user privacy.
Here’s how to use it:
X-Frame-Options
helmet.frameguard sets the X-Frame-Options in the header to prevent clickjacking attacks.
Here is how you can use it:
action takes either deny or sameorigin. By default, Helmet sets this to sameorigin.
X-Powered-By
helmet.hidePoweredBy removes the X-Powered-By broswer, which can give valuable information to malicious users to exploit. In Express, this information is sent to the public by default.
Here is how you can use it:
Strict-Transport-Security
helmet.hsts sets the Strict-Transport-Security header. This tells the browser to prefer HTTPS over HTTP. The maxAge parameter lets the number of seconds browsers should remember to prefer HTTPS. By default, this figure is 15552000 — or 180 days.
You can also include subdomains as well via includeSubDomains. Here is how to use it:
X-Download-Options
helmet.isNoOpen sets the X-Download-Options header. This is specific to the vulnerabilities in IE 8 and forces potentially unsafe downloads to be saved and prevents the execution of HTML in your site’s context.
Here is how to use it:
X-Content-Type-Options
helmet.noSniff sets the X-Content-Type-Options head to nosniff. This prevents MIME type sniffing.
Here is how to use it:
Referrer-Policy
helmet.referrerPolicy sets the Referrer-Policy header. This controls the information inside the Referer header.
Here is an example of how to use it:
By default, Helmet.js sets this to no-referrer.
X-XSS-Protection
helmet.xssFilter prevents cross-site scripting. While browsers come with a filter that prevents this by default, it is not evenly applied and bugginess can range depending on if the end-user is using Chrome, IE, Firefox, Safari, or something else.
Using helmet.xssFilter puts another layer of security on your API. Here is how to use it:
Sử dụng Helmet
Helmet là một package được viêt để giúp bạn bảo vệ ứng dụng của mình khỏi những lỗ hổng đã biết bằng cách thiết lập các Http headers một cách phù hợp Thực tế thì Helmet chỉ là một tập hợp các Middleware nhỏ làm nhiệm vụ thiết lập các Http headers liên quan đến bảo mật, cụ thể như sau:
-
csp Thiết lập header
Content-Security-Policy
giúp ngăn chặn tấn công cross-site scripting và các tấn công cross-site injections khác. -
hidePoweredBy Xóa header
X-Powered-By header
khỏi response, giúp dấu đi thông tin mã nguồn bạn sử dụng. -
hpkp Thêm header
Public Key Pinning
giúp bản vệ ứng dụng khỏi tấn công
man-in-the-middle
với chứng chỉ giả mạo. -
hsts Cài đặt header
Strict-Transport-Security
giúp thực thi kết nối bảo mật (HTTP over SSL/TLS) đến server. -
ieNoOpen set header
X-Download-Options
cho IE8+. -
noCache set header
Cache-Control
và
Pragma
để tắt client-side caching. -
noSniff set header
X-Content-Type-Options
giúp ngăn chặn trình duyệt khỏi MIME-sniffing. -
frameguard set header
X-Frame-Options
để bảo vệ ứng dụng khỏi
clickjacking
. -
xssFilter set header
X-XSS-Protection
giúp kích hoạt bộ lọc
Cross-site scripting (XSS)
.
Cài đặt và sử dụng Helmet
npm install --save helmet
var helmet = require('helmet') app.use(helmet())
Nếu bạn không muốn sử dụng Helmet thì tốt nhất vẫn nên tắt header
X-Powered-By
. Hacker có thể sử dụng header này để xác định ứng dụng của bạn sử dụng Express.js
app.disable('x-powered-by')
Lưu ý rằng tắt header
x-powered-by
không đảm bảo chắc chắn được hacker không thể xác định app của bạn viết trên Express.js, tuy nhiên nó là cách khá đơn giản và cũng có hiệu quả rất tốt
Reference
Content-Security-Policy
Default:
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
The
Content-Security-Policy
header mitigates a large number of attacks, such as cross-site scripting. See MDN’s introductory article on Content Security Policy.
This header is powerful but likely requires some configuration.
To configure this header, pass an object with a nested
directives
object. Each key is a directive name in camel case (such as
defaultSrc
) or kebab case (such as
default-src
). Each value is an array (or other iterable) of strings or functions for that directive. If a function appears in the array, it will be called with the request and response objects.
// Sets all of the defaults, but overrides `script-src` // and disables the default `style-src`. app.use( helmet({ contentSecurityPolicy: { directives: { "script-src": ["'self'", "example.com"], "style-src": null, }, }, }) );
// Sets the `script-src` directive to // "'self' 'nonce-e33...'" (or similar) app.use((req, res, next) => { res.locals.cspNonce = crypto.randomBytes(32).toString("hex"); next(); }); app.use( helmet({ contentSecurityPolicy: { directives: { scriptSrc: ["'self'", (req, res) => `'nonce-${res.locals.cspNonce}'`], }, }, }) );
These directives are merged into a default policy, which you can disable by setting
useDefaults
to
false
.
// Sets "Content-Security-Policy: default-src 'self'; // script-src 'self' example.com;object-src 'none'; // upgrade-insecure-requests" app.use( helmet({ contentSecurityPolicy: { useDefaults: false, directives: { defaultSrc: ["'self'"], scriptSrc: ["'self'", "example.com"], objectSrc: ["'none'"], upgradeInsecureRequests: [], }, }, }) );
You can get the default directives object with
helmet.contentSecurityPolicy.getDefaultDirectives()
. Here is the default policy (whitespace added for readability):
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
The
default-src
directive can be explicitly disabled by setting its value to
helmet.contentSecurityPolicy.dangerouslyDisableDefaultSrc
, but this is not recommended.
You can set the
Content-Security-Policy-Report-Only
instead.
// Sets the Content-Security-Policy-Report-Only header app.use( helmet({ contentSecurityPolicy: { directives: { /* ... */ }, reportOnly: true, }, }) );
Helmet performs very little validation on your CSP. You should rely on CSP checkers like CSP Evaluator instead.
To disable the
Content-Security-Policy
header:
app.use( helmet({ contentSecurityPolicy: false, }) );
You can use this as standalone middleware with
app.use(helmet.contentSecurityPolicy())
.
Cross-Origin-Embedder-Policy
This header is not set by default.
The
Cross-Origin-Embedder-Policy
header helps control what resources can be loaded cross-origin. See MDN’s article on this header for more.
// Helmet does not set Cross-Origin-Embedder-Policy // by default. app.use(helmet()); // Sets "Cross-Origin-Embedder-Policy: require-corp" app.use(helmet({ crossOriginEmbedderPolicy: true })); // Sets "Cross-Origin-Embedder-Policy: credentialless" app.use(helmet({ crossOriginEmbedderPolicy: { policy: "credentialless" } }));
You can use this as standalone middleware with
app.use(helmet.crossOriginEmbedderPolicy())
.
Cross-Origin-Opener-Policy
Default:
Cross-Origin-Opener-Policy: same-origin
The
Cross-Origin-Opener-Policy
header helps process-isolate your page. For more, see MDN’s article on this header.
// Sets "Cross-Origin-Opener-Policy: same-origin" app.use(helmet()); // Sets "Cross-Origin-Opener-Policy: same-origin-allow-popups" app.use( helmet({ crossOriginOpenerPolicy: { policy: "same-origin-allow-popups" }, }) );
To disable the
Cross-Origin-Opener-Policy
header:
app.use( helmet({ crossOriginOpenerPolicy: false, }) );
You can use this as standalone middleware with
app.use(helmet.crossOriginOpenerPolicy())
.
Cross-Origin-Resource-Policy
Default:
Cross-Origin-Resource-Policy: same-origin
The
Cross-Origin-Resource-Policy
header blocks others from loading your resources cross-origin in some cases. For more, see “Consider deploying Cross-Origin Resource Policy and MDN’s article on this header.
// Sets "Cross-Origin-Resource-Policy: same-origin" app.use(helmet()); // Sets "Cross-Origin-Resource-Policy: same-site" app.use(helmet({ crossOriginResourcePolicy: { policy: "same-site" } }));
To disable the
Cross-Origin-Resource-Policy
header:
app.use( helmet({ crossOriginResourcePolicy: false, }) );
You can use this as standalone middleware with
app.use(helmet.crossOriginResourcePolicy())
.
Origin-Agent-Cluster
Default:
Origin-Agent-Cluster: ?1
The
Origin-Agent-Cluster
header provides a mechanism to allow web applications to isolate their origins from other processes. Read more about it in the spec.
This header takes no options and is set by default.
// Sets "Origin-Agent-Cluster: ?1" app.use(helmet());
To disable the
Origin-Agent-Cluster
header:
app.use( helmet({ originAgentCluster: false, }) );
You can use this as standalone middleware with
app.use(helmet.originAgentCluster())
.
Referrer-Policy
Default:
Referrer-Policy: no-referrer
The
Referrer-Policy
header which controls what information is set in the
Referer
request header. See “Referer header: privacy and security concerns” and the header’s documentation on MDN for more.
// Sets "Referrer-Policy: no-referrer" app.use(helmet());
policy
is a string or array of strings representing the policy. If passed as an array, it will be joined with commas, which is useful when setting a fallback policy. It defaults to
no-referrer
.
// Sets "Referrer-Policy: no-referrer" app.use( helmet({ referrerPolicy: { policy: "no-referrer", }, }) ); // Sets "Referrer-Policy: origin,unsafe-url" app.use( helmet({ referrerPolicy: { policy: ["origin", "unsafe-url"], }, }) );
To disable the
Referrer-Policy
header:
app.use( helmet({ referrerPolicy: false, }) );
You can use this as standalone middleware with
app.use(helmet.referrerPolicy())
.
Strict-Transport-Security
Default:
Strict-Transport-Security: max-age=15552000; includeSubDomains
The
Strict-Transport-Security
header tells browsers to prefer HTTPS instead of insecure HTTP. See the documentation on MDN for more.
// Sets "Strict-Transport-Security: max-age=15552000; includeSubDomains" app.use(helmet());
maxAge
is the number of seconds browsers should remember to prefer HTTPS. If passed a non-integer, the value is rounded down. It defaults to
15552000
, which is 180 days.
includeSubDomains
is a boolean which dictates whether to include the
includeSubDomains
directive, which makes this policy extend to subdomains. It defaults to
true
.
preload
is a boolean. If true, it adds the
preload
directive, expressing intent to add your HSTS policy to browsers. See the “Preloading Strict Transport Security” section on MDN for more. It defaults to
false
.
// Sets "Strict-Transport-Security: max-age=123456; includeSubDomains" app.use( helmet({ strictTransportSecurity: { maxAge: 123456, }, }) ); // Sets "Strict-Transport-Security: max-age=123456" app.use( helmet({ strictTransportSecurity: { maxAge: 123456, includeSubDomains: false, }, }) ); // Sets "Strict-Transport-Security: max-age=123456; includeSubDomains; preload" app.use( helmet({ strictTransportSecurity: { maxAge: 63072000, preload: true, }, }) );
To disable the
Strict-Transport-Security
header:
app.use( helmet({ strictTransportSecurity: false, }) );
You can use this as standalone middleware with
app.use(helmet.strictTransportSecurity())
.
X-Content-Type-Options
Default:
X-Content-Type-Options: nosniff
The
X-Content-Type-Options
mitigates MIME type sniffing which can cause security issues. See documentation for this header on MDN for more.
This header takes no options and is set by default.
// Sets "X-Content-Type-Options: nosniff" app.use(helmet());
To disable the
X-Content-Type-Options
header:
app.use( helmet({ xContentTypeOptions: false, }) );
You can use this as standalone middleware with
app.use(helmet.xContentTypeOptions())
.
X-DNS-Prefetch-Control
Default:
X-DNS-Prefetch-Control: off
The
X-DNS-Prefetch-Control
header helps control DNS prefetching, which can improve user privacy at the expense of performance. See documentation on MDN for more.
// Sets "X-DNS-Prefetch-Control: off" app.use(helmet());
allow
is a boolean dictating whether to enable DNS prefetching. It defaults to
false
.
Examples:
// Sets "X-DNS-Prefetch-Control: off" app.use( helmet({ xDnsPrefetchControl: { allow: false }, }) ); // Sets "X-DNS-Prefetch-Control: on" app.use( helmet({ xDnsPrefetchControl: { allow: true }, }) );
To disable the
X-DNS-Prefetch-Control
header and use the browser’s default value:
app.use( helmet({ xDnsPrefetchControl: false, }) );
You can use this as standalone middleware with
app.use(helmet.xDnsPrefetchControl())
.
X-Download-Options
Default:
X-Download-Options: noopen
The
X-Download-Options
header is specific to Internet Explorer 8. It forces potentially-unsafe downloads to be saved, mitigating execution of HTML in your site’s context. For more, see this old post on MSDN.
This header takes no options and is set by default.
// Sets "X-Download-Options: noopen" app.use(helmet());
To disable the
X-Download-Options
header:
app.use( helmet({ xDownloadOptions: false, }) );
You can use this as standalone middleware with
app.use(helmet.xDownloadOptions())
.
X-Frame-Options
Default:
X-Frame-Options: SAMEORIGIN
The legacy
X-Frame-Options
header to help you mitigate clickjacking attacks. This header is superseded by the
frame-ancestors
Content Security Policy directive but is still useful on old browsers or if no CSP is used. For more, see the documentation on MDN.
// Sets "X-Frame-Options: SAMEORIGIN" app.use(helmet());
action
is a string that specifies which directive to use—either
DENY
or
SAMEORIGIN
. (A legacy directive,
ALLOW-FROM
, is not supported by Helmet. Read more here.) It defaults to
SAMEORIGIN
.
Examples:
// Sets "X-Frame-Options: DENY" app.use( helmet({ xFrameOptions: { action: "deny" }, }) ); // Sets "X-Frame-Options: SAMEORIGIN" app.use( helmet({ xFrameOptions: { action: "sameorigin" }, }) );
To disable the
X-Frame-Options
header:
app.use( helmet({ xFrameOptions: false, }) );
You can use this as standalone middleware with
app.use(helmet.xFrameOptions())
.
X-Permitted-Cross-Domain-Policies
Default:
X-Permitted-Cross-Domain-Policies: none
The
X-Permitted-Cross-Domain-Policies
header tells some clients (mostly Adobe products) your domain’s policy for loading cross-domain content. See the description on OWASP for more.
// Sets "X-Permitted-Cross-Domain-Policies: none" app.use(helmet());
permittedPolicies
is a string that must be
"none"
,
"master-only"
,
"by-content-type"
, or
"all"
. It defaults to
"none"
.
Examples:
// Sets "X-Permitted-Cross-Domain-Policies: none" app.use( helmet({ xPermittedCrossDomainPolicies: { permittedPolicies: "none", }, }) ); // Sets "X-Permitted-Cross-Domain-Policies: by-content-type" app.use( helmet({ xPermittedCrossDomainPolicies: { permittedPolicies: "by-content-type", }, }) );
To disable the
X-Permitted-Cross-Domain-Policies
header:
app.use( helmet({ xPermittedCrossDomainPolicies: false, }) );
You can use this as standalone middleware with
app.use(helmet.xPermittedCrossDomainPolicies())
.
X-Powered-By
Default: the
X-Powered-By
header, if present, is removed.
Helmet removes the
X-Powered-By
header, which is set by default in Express and some other frameworks. Removing the header offers very limited security benefits (see this discussion) and is mostly removed to save bandwidth, but may thwart simplistic attackers.
Note: Express has a built-in way to disable the
X-Powered-By
header, which you may wish to use instead.
The removal of this header takes no options. The header is removed by default.
To disable this behavior:
// Not required, but recommended for Express users: app.disable("x-powered-by"); // Ask Helmet to ignore the X-Powered-By header. app.use( helmet({ xPoweredBy: false, }) );
You can use this as standalone middleware with
app.use(helmet.xPoweredBy())
.
X-XSS-Protection
Default:
X-XSS-Protection: 0
Helmet disables browsers’ buggy cross-site scripting filter by setting the legacy
X-XSS-Protection
header to . See discussion about disabling the header here and documentation on MDN.
This header takes no options and is set by default.
To disable the
X-XSS-Protection
header:
// This is not recommended. app.use( helmet({ xXssProtection: false, }) );
You can use this as standalone middleware with
app.use(helmet.xXssProtection())
.
Node.js Securing Apps with Helmet.js
is a Node.js module that helps in securing HTTP headers. It is implemented in express applications. Therefore, we can say that helmet.js helps in securing express applications. It sets up various HTTP headers to prevent attacks like Cross-Site-Scripting(XSS), clickjacking, etc.
Why security of HTTP headers are important:
Sometimes developers ignore the HTTP headers. Since HTTP headers can leak sensitive information about the application, therefore, it is important to use the headers in a secure way.
Node-Modules included in Helmet.js are:
Helmet.js comes with more built-in modules for increasing the security of the Express application.
- Content-Security-Policy: It sets up the Security Policy.
- Expect-CT: It is used for handling Certificate Transparency.
- X-DNS-Prefetch-Control: It is used for controlling the fetching of browser DNS.
- X-Frame-Options: It is used to prevent ClickJacking.
- X-Powered-By: It is used to remove X-Powered-By header. X-Powered-By header leaks the version of the server and its vendor.
- Public-Key-Pins: It is used for HTTP public key pinning.
- Strict-Transport-Security: It is used for HTTP Strict Transport policy.
- X-Download-Options: It restricts to various Download-Options.
- Cache control: It is used for disabling Client-Side caching.
- X-Content-Type-Options: It is used to prevent the Sniffing attack.
- Referrer-Policy: It is used to hide the referrer header.
- X-XSS-Protection: It is used to add protection to XSS attacks.
How to inspect HTTP Header:
For inspecting the header, first right-click on a page that you want to inspect. Now, click on
inspect element
. After that open the
Network
tab. The network tab will look like this:
It will be empty at first. In the network tab, all the HTTP requests made by the browser will be shown up.
Pre-requisites:
- An IDE of your choice.
- Node.js installed in your system.
- Knowledge of Node.js and express applications.
Setting up a basic express application:
-
First initialize the application with package.json file. Write the following command:
npm init
-
Install express module by using the following command:
npm install express –save
Shown below is our package.json file:
{
“name”: “HelmetJs”,
“version”: “1.0.0”,
“description”: “”,
“main”: “index.js”,
“scripts”: {
“test”: “echo \”Error: no test specified\” && exit 1″
},
“author”: “Pranjal Srivastava”,
“license”: “ISC”,
“dependencies”: {
“express”: “^4.17.1”,
}
} -
Create a file in which we will write our javascript code. For example, app.js. You can name your file whatever you want. Now, write the following code for setting up the server:
const express = require(
'express'
);
const app = express();
app.get(
'/'
, (req, res) => {
res.send(
"This is the Demo page for"
" setting up express server !"
});
app.listen(3000, (err) => {
if
(err) { console.log(err); }
else
{ console.log(
'Server started "
});
-
Run app.js file with the following command:
node app.js
The output of above command is shown below:
Server started at http://localhost:3000
-
Open the browser and go to http://localhost:3000. Again open the Network tab and there you will see the list of requests made by the browser. Select the localhost requests and you will see the list of response headers like this:
HTTP/1.1 304 Not Modified
X-Powered-By: Express
ETag: W/”35-QqeUaYjSJ35gtyT3DcgtpQlitTU”
Date: Thu, 04 Jun 2020 15:55:00 GMT
Connection: keep-alive
Setting up and implementing Helmet.js in an express application:
-
For installing the helmet.js module, write the following command:
npm install helmet –save
-
In app.js file, write the following code to make use of helmet module:
const express = require(
'express'
);
const helmet = require(
'helmet'
);
const app = express();
app.use(helmet());
app.get(
'/'
, (req, res) => {
res.send(
"This is the Demo page for"
" setting up express server !"
});
app.listen(3000, (err) => {
if
(err) { console.log(err); }
else
{ console.log(
'Server started "
});
-
Start the server with the following command:
node app.js
-
Open the Network tab by clicking on Inspect Element. Click on localhost and you will notice an additional set of headers in response. The headers are as follows:
HTTP/1.1 304 Not Modified
X-DNS-Prefetch-Control: off
X-Frame-Options: SAMEORIGIN
Strict-Transport-Security: max-age=15552000; includeSubDomains
X-Download-Options: noopen
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
ETag: W/”35-QqeUaYjSJ35gtyT3DcgtpQlitTU”
Date: Thu, 04 Jun 2020 16:11:37 GMT
Connection: keep-aliveHere, the new set of headers are applied by our helmet.js module. These headers are added for an additional level of security.
Conclusion: Helmet.js
module is very useful for NodeJs developers as it adds security to the express applications. In this tutorial, we learned about helmet.js and seen its implementation in a basic express application.
Whether you’re preparing for your first job interview or aiming to upskill in this ever-evolving tech landscape, GeeksforGeeks Courses are your key to success. We provide top-quality content at affordable prices, all geared towards accelerating your growth in a time-bound manner. Join the millions we’ve already empowered, and we’re here to do the same for you. Don’t miss out – check it out now!
Looking for a place to share your ideas, learn, and connect? Our Community portal is just the spot! Come join us and see what all the buzz is about!
Last Updated :
08 Oct, 2021
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment…
Express.js Best Security Paractices
Bài đăng này đã không được cập nhật trong 6 năm
Express.js là một trong những framework phổ biến nhất trong làng dev Node.js, nó là một framework đơn giản nhưng đủ mạnh để giúp chúng ta tiếp cận cũng như phát triển website dựa trên framwork này. Cũng giống như với các framework khác, với Express.js chúng ta cũng có khá nhiều điểm cần lưu ý để đảm bảo ứng dụng của mình hoạt động linh hoạt và an toàn trên môi trường production. Thuật ngữ “production” được dùng để chỉ định giai đoạn trong vòng đời phát triển phần mềm mà khi đó ứng dụng hoặc api đã được public đến người dùng cuối hoặc khách hàng. Ngược lại, giao đoan “development” là giai đoạn khi mà chúng ta vẫn còn đang tiếp tục công việc coding hoặc testing. Hai môi trường Production và Development thường có những cài đặt, cấu hình khác nhau nhằm phục vụ cho việc debug, testing khi development và đảm bảo performance, security khi lên production; trong đó thì có rất nhiều thứ hợp lý và hữu ích khi development nhưng lại hoàn toàn không nên hoặc bị cấm khi lên production (như là logging, debugging…) Dưới đây là một số lưu ý khi triển khai production cho một ứng dụng Express.js
Get started
Here’s a sample Express app that uses Helmet:
import express from “express”; import helmet from “helmet”; const app = express(); // Use Helmet! app.use(helmet()); app.get(“/”, (req, res) => { res.send(“Hello world!”); }); app.listen(8000);
You can also
require("helmet")
if you prefer.
By default, Helmet sets the following headers:
-
Content-Security-Policy
: A powerful allow-list of what can happen on your page which mitigates many attacks -
Cross-Origin-Opener-Policy
: Helps process-isolate your page -
Cross-Origin-Resource-Policy
: Blocks others from loading your resources cross-origin -
Origin-Agent-Cluster
: Changes process isolation to be origin-based -
Referrer-Policy
: Controls the
Referer
header -
Strict-Transport-Security
: Tells browsers to prefer HTTPS -
X-Content-Type-Options
: Avoids MIME sniffing -
X-DNS-Prefetch-Control
: Controls DNS prefetching -
X-Download-Options
: Forces downloads to be saved (Internet Explorer only) -
X-Frame-Options
: Legacy header that mitigates clickjacking attacks -
X-Permitted-Cross-Domain-Policies
: Controls cross-domain behavior for Adobe products, like Acrobat -
X-Powered-By
: Info about the web server. Removed because it could be used in simple attacks -
X-XSS-Protection
: Legacy header that tries to mitigate XSS attacks, but makes things worse, so Helmet disables it
Each header can be configured. For example, here’s how you configure the
Content-Security-Policy
header:
// This sets custom options for the // Content-Security-Policy header. app.use( helmet({ contentSecurityPolicy: { directives: { “script-src”: [“‘self'”, “example.com”], }, }, }), );
Headers can also be disabled. For example, here’s how you disable the
Content-Security-Policy
and
X-Download-Options
headers:
// This disables the Content-Security-Policy // and X-Download-Options headers. app.use( helmet({ contentSecurityPolicy: false, xDownloadOptions: false, }), );
I am the author here. Thanks! I am glad you found the article useful and comprehensive.
Express.js is the most popular web framework for developing web applications in Node.js. It comes with several features to make API development faster and easier.
However, Express falls short when it comes to security, not ensuring an adequate level of protection from common vulnerabilities. Fortunately, it can be easily extended thanks to middleware, a set of functions executed during the processing of HTTP requests.
Helmet.js is middleware-based technology that improves security by safeguarding HTTP headers returned by a Node.js app. Here, you will learn what Helmet is, why you need it, and how to integrate it into Node.js to secure HTTP headers in an Express.js application. We will cover:
Let’s dig into Helmet in Node.js!
Helmet.js is an open source JavaScript library that helps you secure your Node.js application by setting several HTTP headers. It acts as a middleware for Express and similar technologies, automatically adding or removing HTTP headers to comply with web security standards.
Although not a silver bullet, Helmet makes it harder for attackers to exploit known vulnerabilities. It helps to protect Node.js Express apps from common security threats such as Cross-Site Scripting (XSS) and click-jacking attacks.
Helmet is particularly useful because Express applications do not come with security HTTP headers out of the box. This explains why the
helmet
npm package has more than 2,000,000 weekly downloads, while its GitHub repo boasts over 9.4k stars!
Let’s now dig deeper into why adopting Helmet in Node.js is so important.
Without Helmet, default headers returned by Express expose sensitive information and make your Node.js app vulnerable to malicious actors. In contrast, using Helmet in Node.js protects your application from XSS attacks, Content Security Policy vulnerabilities, and other security issues.
Let’s explore this question further through an example. You are going to set up a Node.js Express app and see what level of security its default HTTP headers offer.
First, make sure you have Node.js and npm installed on your machine. If you aren’t set up yet, start by downloading Node.js and following the installation wizard to set it up.
Now, let’s set up an Express project. Run the command below to create the
express-demo
project folder:
mkdir express-demo
Then, enter the
express-demo
folder in your terminal by running the following:
cd express-demo
Launch the following command to initialize a default npm project:
npm init -y
The
npm init
command will configure a blank npm project for you. Note that the
-y
flag will automatically answer “yes” to all questions that npm would otherwise ask you during the process.
You need to add Express to your project’s dependencies. Install the Express module with the below:
npm install express
Then, create an
index.js
file in the
express-demo
folder and initialize it with these lines:
// index.js const express = require(“express”) // creating an Express instance const app = express() const PORT = process.env.PORT || 3000 // initializing a basic API that // returns the “Hello, World!” message app.get(“/”, (req, res) => { res.json(“Hello, World!”) }) // running the server app.listen(PORT, () => { console.log(`Starting Express server on http://localhost:${PORT}`) })
This is nothing more than a basic Express server setup with a single endpoint.
Start the server with this command:
node index.js
The Express server should now be running at
http://localhost:3000
. Launch the command below in your terminal to test the endpoint:
curl http://localhost:3000/
This should print the following output:
“Hello, World!”
Et voilà! You now have a working Express app!
Let’s now use the demo application we just created to verify the default behavior of Express when it comes to security HTTP headers.
Repeat the
curl
command above with the
--include
flag to get also the HTTP response headers:
curl http://localhost:3000/ –include
If you do not have cURL installed on your computer, use an HTTP client such as Postman or Insomnia to inspect the HTTP headers of the response.
In the response header section, you should be seeing the following:
X-Powered-By: Express Content-Type: application/json; charset=utf-8 Content-Length: 15 ETag: W/”f-pob1Yw/KBE+3vrbZz9GAyq5P2gE” Date: Fri, 20 Jan 2023 16:29:40 GMT Connection: keep-alive Keep-Alive: timeout=5
Note the
X-Powered-By
header. As with all headers that begin with
X-
, it is a non-standard header. Specifically, backend technologies generally use
X-Powered-By
to indicate the name and version number of the framework or library used by the server to generate the HTTP response.
As recommended by OWASP, a nonprofit foundation that works to improve web security,
X-Powered-By
should be omitted. This is because you should never give attackers details about your tech stack. Otherwise, they could use that info to exploit known vulnerabilities in that framework or library.
Now, let’s check what the Security Headers online project has to say about the security level of your Express app.
Since Security Headers only allows you to test public addresses, you need to make your local Express server publicly available. You can either deploy your Express app to a server or take advantage of ngrok, which allows you to expose a local web server to the Internet.
Download ngrok, extract it, and open the folder in the terminal. Then, launch the following command to host your local server with ngrok:
ngrok http 3000
You should get a similar result to the below:
The “Forwarding” field contains the URL to publicly access your local server. Since the endpoint to test is , copy the URL, add a trailing character, and paste it in the Security Headers input as shown below:
Click the “Scan” button, and you should get the following result:
As you can see here, the Security Headers project gives the demo app a worrying “F” grade. The reason is that the API response developed with Express without Helmet is missing all the most relevant HTTP security headers.
This is also why the official Express “Production Best Practices: Security” page mentions adopting Helmet as a best practice for production applications. Let’s now learn how to integrate Helmet in Node.js!
Let’s expand the Express demo project implemented earlier to secure it with Helmet. As you are about to learn, this only takes a couple of lines of code.
First, you need to add Helmet.js to your project’s dependencies. Install the
helmet
npm package with the following command:
npm i helmet
Your
package.json
file will now contain
helmet
in the
dependencies
fields.
Integrating Helmet into your Node.js Express app is simple. In case of problems, follow the official guide.
In your
index.js
file, import
helmet
with the following command:
const helmet = require(“helmet”)
Now, register
helmet
in your Express application with the below:
app.use(helmet())
Remember that
helmet()
is nothing more than an Express middleware. Specifically, the top-level
helmet()
function is a wrapper of 15 sub-middlewares. So, by registering
helmet()
, you are adding 15 Express middlewares to your apps.
Note that each middleware takes care of setting one HTTP security header.
Your
index.js
file will now look as follows:
// index.js const express = require(“express”) const helmet = require(“helmet”) const PORT = process.env.PORT || 3000 const app = express() // enabling the Helmet middleware app.use(helmet()) // initializing a basic API that // returns the “Hello, World!” message app.get(“/”, (req, res) => { res.json(“Hello, World!”) }) // running the server app.listen(PORT, () => { console.log(`Starting Express server on http://localhost:${PORT}`) })
That’s it! Adding Helmet to your Node.js app only involve two lines of code!
Let’s repeat the security test performed earlier. Stop your Node.js local server and relaunch it with this command:
node index.js
Repeat the
curl
command or use an HTTP client to see the HTTP headers of the new response:
curl http://localhost:3000/ –include
The response HTTP header section will now include the following:
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 Cross-Origin-Embedder-Policy: require-corp Cross-Origin-Opener-Policy: same-origin Cross-Origin-Resource-Policy: same-origin X-DNS-Prefetch-Control: off X-Frame-Options: SAMEORIGIN Strict-Transport-Security: max-age=15552000; includeSubDomains X-Download-Options: noopen X-Content-Type-Options: nosniff Origin-Agent-Cluster: ?1 X-Permitted-Cross-Domain-Policies: none Referrer-Policy: no-referrer X-XSS-Protection: 0 Content-Type: application/json; charset=utf-8 Content-Length: 15 ETag: W/”f-pob1Yw/KBE+3vrbZz9GAyq5P2gE” Date: Fri, 20 Jan 2023 18:15:32 GMT Connection: keep-alive Keep-Alive: timeout=5
As you can see, there are many new HTTP headers in the response. Also,
X-Powered-By
was removed.
If you shut down ngrok, run it again with the following:
ngrok http 3000
Otherwise, visit the Security Headers website right away. Just like before, copy the URL provided by ngrok and click “Scan.” This time, the outcome will be different:
Note that the API response now involves all the major HTTP Security headers, except for
Permissions-Policy
. This allowed the Express app to go from an “F” grade to an “A” grade. What a huge change with just two lines of code!
Also, as mentioned on GitHub by one of the lead developers of Helmet.js, Helmet does not automatically support
Permissions-Policy
only because the header specification is still in a draft state. So, this may change soon.
As you just learned, Helmet sets a lot of headers by default. Since security policies change over time, it is critical to always keep
helmet
up-to-date. This way, the security headers introduced by Helmet will always comply with security standards.
All of those headers have an impact on the security of your application, but some are more relevant than others. Let’s now focus on the most important security headers to understand why they are useful, how Helmet treats them by default, and how you can configure them with Helmet.
Content-Security-Policyheader
Content Security Policy, also known as CSP, is a security measure that helps you mitigate several attacks, such as cross-site scripting (XSS) and data injection attacks.
Specifically, CSP allows you to specify what sources of content a web page is allowed to load and execute. For example, you can use CSP to block a web page from loading images and iframes from other websites.
You can configure CSP through the
Content-Security-Policy
HTTP header. By default, Helmet gives the
Content-Security-Policy
header the following value:
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
With this policy, your web pages cannot load remote fonts or styles. This is because
font-src
and
style-src
are set to
self
, respectively. The CSP policy defined by Helmet by default is very restrictive, but you can change it with
contentSecurityPolicy()
as follows:
// overriding “font-src” and “style-src” while // maintaining the other default values helmet.contentSecurityPolicy({ useDefaults: true, directives: { “font-src”: [“‘self'”, “external-website.com”], // allowing styles from any website “style-src”: null, }, })
useDefaults
applies the default values. Then, the following directives override the defaults. Set
useDefaults
to
false
to define a CSP policy from scratch.
Referrer-Policyheader
The
Referrer-Policy
HTTP header defines what data should be sent as referrer information in the
Referer
header. By default,
Referer
generally contains the current URL from which an HTTP request is performed.
For example, if you click on a link to a third-party website,
Referer
will contain the address of the current web page. As a result, the third-party website could use the header to track you or understand what you were visiting.
If the current address contains private user information, the third-party site will be able to steal it from the
Referer
header. Because of this, even though this header is typically used for caching or analytics, it opens up some privacy concerns because it can leak sensitive information.
Helmet sets it to
no-referrer
by default. This means that the
Referer
header will always be empty. So, requests performed by web pages served by your Node.js app will not include any referrer information.
If you want to change this restrictive policy, you can do it with
refererPolicy
as below:
// setting “Referrer-Policy” to “no-referrer” app.use( helmet.referrerPolicy({ policy: “no-referrer”, }) )
Strict-Transport-Securityheader
The
Strict-Transport-Security
HTTP header, also known as HSTS, specifies that a site or resource should only be accessed via HTTPS. In detail, the
maxAge
parameter defines the number of seconds browsers should remember to prefer HTTPS over HTTP.
By default, Helmet sets the
Strict-Transport-Security
header as follows:
max-age=15552000; includeSubDomains
Note that
15552000
seconds corresponds to 180 days, as well as that
includeSubDomains
extends the HSTS policy to all the site’s subdomains.
You can configure the
Strict-Transport-Security
header with the
hsts
Helmet function as follows:
app.use( helmet.hsts({ // 60 days maxAge: 86400, // removing the “includeSubDomains” option includeSubDomains: false, }) )
X-Content-Type-Optionsheader
The
X-Content-Type-Options
HTTP header defines that the MIME types used in the
Content-Type
header must be followed. This mitigates MIME type sniffing, which can lead to XSS attacks and cause other vulnerabilities.
For example, attackers could hide HTML code in a
.png
file. The browser might perform MIME type sniffing to determine the content type of the resource.
Since the file contains HTML code, the browser will determine that it is an HTML file rather than a JPG image. Thus, the browser will execute the attacker’s code accordingly when rendering the page.
By default, Helmet sets
X-Content-Type-Options
to
nosniff
. This disables and prevents MIME type sniffing.
Note that the
noSniff()
Helmet function contained in
helmet()
does not accept parameters. If you want to disable this behavior and go against recommended security policies, you can prevent Helmet from importing
nosniff()
with the following:
app.use( // not loading the noSniff() middleware helmet({ noSniff: false, }) )
X-Frame-Optionsheader
The
X-Frame-Options
HTTP response header specifies whether or not a browser should be allowed to render a page in the , , and HTML elements.
By preventing the content of your site from being embedded in other sites, you can avoid click-jacking attacks. A click-jacking attack involves tricking users into clicking on something different from what they perceive or expect.
By default, Helmet sets
X-Frame-Options
to
SAMEORIGIN
. This allows a web page to be embedded in a frame on pages with the same origin as the page itself. You can set this header in Helmet with
frameguard()
as follows:
// setting “X-Frame-Options” to “DENY” app.use( helmet.frameguard({ action: “deny”, }) );
If you want to omit the
X-Frame-Options
header entirely, you can disable the
frameguard()
middleware with the following:
app.use( // not including the frameguard() middleware helmet({ frameguard: false, }) )
Note that this is not recommended for security reasons.
In this article, you learned what Helmet.js is and why it plays such an important role when it comes to securing a Node.js app.
As you saw here, APIs developed in Express do not involve security HTTP headers. So, default Express apps come with some security concerns.
With Helmet, you can add a security layer to Node.js with just a single line of code, safeguarding your application from the most common attacks and vulnerabilities.
Deploying a Node-based web app or website is the easy part. Making sure your Node instance continues to serve resources to your app is where things get tougher. If you’re interested in ensuring requests to the backend or third-party services are successful, try LogRocket.
LogRocket is like a DVR for web and mobile apps, recording literally everything that happens while a user interacts with your app. Instead of guessing why problems happen, you can aggregate and report on problematic network requests to quickly understand the root cause.
LogRocket instruments your app to record baseline performance timings such as page load time, time to first byte, slow network requests, and also logs Redux, NgRx, and Vuex actions/state. Start monitoring for free.
By building these four simple projects, you’ll learn how CSS variables can help you write reusable, elegant code and streamline the way you build websites.
In this article, we’ll learn what a component library is and how to build our component library with React and TypeScript.
Chakra UI has emerged as a highly relevant design library. Let’s discuss what makes Chakra UI a great choice for modern applications.
Brant Snow is the Vice President of Technology at Extensiv, an omnichannel software solutions provider for warehouse, inventory, and order […]
I am the author here. Thanks! I am glad you found the article useful and comprehensive.
Really helpfull
Yet another great LogRocket article! The articles alone is why I would consider using LogRocket for the project I’m currently working on.
I’ll be in touch soon.
I’m using Helmet and CORS packages to my node.js application. But I don’t know what’s the difference of both packages and the performance impact to the application. Also, by using these packages, will it secure the my node.js application or adds security to the client?
2 Answers
Helmet is a nodejs package that helps protect your server from some well-known web vulnerabilities by setting HTTP response headers appropriately, it comes with a collection of several middleware functions that set security headers that are returned from your express application.
The top-level
helmet
function is a wrapper around 15 smaller middlewares.
Some security attacks help secure your express server from common attacks such as clickjacking, and cross-site scripting attacks, it also helps enforce secure HTTPS connections to your server, download options for vulnerable browsers, and a host of other vulnerabilities. As you see it’s an important package to have in your express app, it’s actually listed among packages to use under production’s best practices from the official express website.
Cors on the other hand is a node.js package that provides your express app with middlewares to enable Cross-origin resource sharing (CORS) which is a mechanism that allows resources on your express app from being shared with external domains, its important in making cross-domain requests possible in case it’s needed.
A typical use case is developing a full-stack application where the static content like the HTML pages are not located within the domain of your express app, like in the case of local development where an angular or react app running on
localhost:4200
needs to access your express app resource served from
localhost:3000
, without CORS enabled this request will not be possible.
The Cors package equally exposes a reach interface to restrict access of resources to whitelisted domains, below is an example from the node.js CORS package
var express = require('express') var cors = require('cors') var app = express() var whitelist = ['http://example1.com', 'http://example2.com'] var corsOptions = { origin: function (origin, callback) { if (whitelist.indexOf(origin) !== -1) { callback(null, true) } else { callback(new Error('Not allowed by CORS')) } } } app.get('/products/:id', cors(corsOptions), function (req, res, next) { res.json({msg: 'This is CORS-enabled for a whitelisted domain.'}) })
Notice the whitelisted domains
http://example1.com
and
http://example2.com
allowed to access the
/products/:id
route of the express server.
Summary
Helmet and Cors are 2 important node.js packages with different purposes. Helmet secures your express app by setting response HTTP headers appropriately, while Cors enables your express application access control to allow restricted resources from being accessed from external domains.
Performance-wise, both helmet and cors bring basic middleware functions with little or no performance effect, setting a couple of important HTTP headers will not negatively impact your server, I don’t think so. and as a matter of fact now you know the importance of using this packages in your express app and what it brings.
- 6I maintain Helmet and I upvoted this answer. Jul 9, 2022 at 17:23
- If we use proxy server like nginx, will it still protect the node.js app? @EvanHahn Jul 10, 2022 at 4:48
- 1Yes, as long as nginx doesn’t disable the headers. Jul 11, 2022 at 14:13
In my opinion CORS is the best, you can easily eliminate the worst error which is “breaking cors law”, and also adding some security to your node.js application, by stricting it to accept connections from origins you want to. So, yes, it will secure your node.js app if you know how to set it right
- Hi thanks for the quick answer. But my concern is Helmet given as the best solution in the express official website expressjs.com/en/advanced/… Also I need to know about the differences between them. Jul 9, 2022 at 15:26
- Furthermore, if we use proxy server like nginx, will it still protect the node.js app? Jul 9, 2022 at 15:27
- You could try using Helmet alongside with cors. Helmet provides security for your app for clickjacking, enforces HTTPS connection to server, and prevents cross-site scripting attacks injecting scripts into your app to gain connection. And yes, if you use proxy server nothing will change, proxy server only makes the server more available from other sources like other links etc.– SkayuJul 9, 2022 at 15:31
- If we use both Helmet and Cors, it will impact to the performance of my application as too many headers were applied. And for the second question, if we use a proxy server, it will not get the Helmet protection as it not served the HTTP content Jul 9, 2022 at 15:36
Helmet helps secure Express apps by setting HTTP response headers.
Reference
Content-Security-Policy
Default:
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
The
Content-Security-Policy
header mitigates a large number of attacks, such as cross-site scripting. See MDN’s introductory article on Content Security Policy.
This header is powerful but likely requires some configuration.
To configure this header, pass an object with a nested
directives
object. Each key is a directive name in camel case (such as
defaultSrc
) or kebab case (such as
default-src
). Each value is an array (or other iterable) of strings or functions for that directive. If a function appears in the array, it will be called with the request and response objects.
// Sets all of the defaults, but overrides `script-src` // and disables the default `style-src`. app.use( helmet({ contentSecurityPolicy: { directives: { "script-src": ["'self'", "example.com"], "style-src": null, }, }, }) );
// Sets the `script-src` directive to // "'self' 'nonce-e33...'" (or similar) app.use((req, res, next) => { res.locals.cspNonce = crypto.randomBytes(32).toString("hex"); next(); }); app.use( helmet({ contentSecurityPolicy: { directives: { scriptSrc: ["'self'", (req, res) => `'nonce-${res.locals.cspNonce}'`], }, }, }) );
These directives are merged into a default policy, which you can disable by setting
useDefaults
to
false
.
// Sets "Content-Security-Policy: default-src 'self'; // script-src 'self' example.com;object-src 'none'; // upgrade-insecure-requests" app.use( helmet({ contentSecurityPolicy: { useDefaults: false, directives: { defaultSrc: ["'self'"], scriptSrc: ["'self'", "example.com"], objectSrc: ["'none'"], upgradeInsecureRequests: [], }, }, }) );
You can get the default directives object with
helmet.contentSecurityPolicy.getDefaultDirectives()
. Here is the default policy (whitespace added for readability):
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
The
default-src
directive can be explicitly disabled by setting its value to
helmet.contentSecurityPolicy.dangerouslyDisableDefaultSrc
, but this is not recommended.
You can set the
Content-Security-Policy-Report-Only
instead.
// Sets the Content-Security-Policy-Report-Only header app.use( helmet({ contentSecurityPolicy: { directives: { /* ... */ }, reportOnly: true, }, }) );
Helmet performs very little validation on your CSP. You should rely on CSP checkers like CSP Evaluator instead.
To disable the
Content-Security-Policy
header:
app.use( helmet({ contentSecurityPolicy: false, }) );
You can use this as standalone middleware with
app.use(helmet.contentSecurityPolicy())
.
Cross-Origin-Embedder-Policy
This header is not set by default.
The
Cross-Origin-Embedder-Policy
header helps control what resources can be loaded cross-origin. See MDN’s article on this header for more.
// Helmet does not set Cross-Origin-Embedder-Policy // by default. app.use(helmet()); // Sets "Cross-Origin-Embedder-Policy: require-corp" app.use(helmet({ crossOriginEmbedderPolicy: true })); // Sets "Cross-Origin-Embedder-Policy: credentialless" app.use(helmet({ crossOriginEmbedderPolicy: { policy: "credentialless" } }));
You can use this as standalone middleware with
app.use(helmet.crossOriginEmbedderPolicy())
.
Cross-Origin-Opener-Policy
Default:
Cross-Origin-Opener-Policy: same-origin
The
Cross-Origin-Opener-Policy
header helps process-isolate your page. For more, see MDN’s article on this header.
// Sets "Cross-Origin-Opener-Policy: same-origin" app.use(helmet()); // Sets "Cross-Origin-Opener-Policy: same-origin-allow-popups" app.use( helmet({ crossOriginOpenerPolicy: { policy: "same-origin-allow-popups" }, }) );
To disable the
Cross-Origin-Opener-Policy
header:
app.use( helmet({ crossOriginOpenerPolicy: false, }) );
You can use this as standalone middleware with
app.use(helmet.crossOriginOpenerPolicy())
.
Cross-Origin-Resource-Policy
Default:
Cross-Origin-Resource-Policy: same-origin
The
Cross-Origin-Resource-Policy
header blocks others from loading your resources cross-origin in some cases. For more, see “Consider deploying Cross-Origin Resource Policy and MDN’s article on this header.
// Sets "Cross-Origin-Resource-Policy: same-origin" app.use(helmet()); // Sets "Cross-Origin-Resource-Policy: same-site" app.use(helmet({ crossOriginResourcePolicy: { policy: "same-site" } }));
To disable the
Cross-Origin-Resource-Policy
header:
app.use( helmet({ crossOriginResourcePolicy: false, }) );
You can use this as standalone middleware with
app.use(helmet.crossOriginResourcePolicy())
.
Origin-Agent-Cluster
Default:
Origin-Agent-Cluster: ?1
The
Origin-Agent-Cluster
header provides a mechanism to allow web applications to isolate their origins from other processes. Read more about it in the spec.
This header takes no options and is set by default.
// Sets "Origin-Agent-Cluster: ?1" app.use(helmet());
To disable the
Origin-Agent-Cluster
header:
app.use( helmet({ originAgentCluster: false, }) );
You can use this as standalone middleware with
app.use(helmet.originAgentCluster())
.
Referrer-Policy
Default:
Referrer-Policy: no-referrer
The
Referrer-Policy
header which controls what information is set in the
Referer
request header. See “Referer header: privacy and security concerns” and the header’s documentation on MDN for more.
// Sets "Referrer-Policy: no-referrer" app.use(helmet());
policy
is a string or array of strings representing the policy. If passed as an array, it will be joined with commas, which is useful when setting a fallback policy. It defaults to
no-referrer
.
// Sets "Referrer-Policy: no-referrer" app.use( helmet({ referrerPolicy: { policy: "no-referrer", }, }) ); // Sets "Referrer-Policy: origin,unsafe-url" app.use( helmet({ referrerPolicy: { policy: ["origin", "unsafe-url"], }, }) );
To disable the
Referrer-Policy
header:
app.use( helmet({ referrerPolicy: false, }) );
You can use this as standalone middleware with
app.use(helmet.referrerPolicy())
.
Strict-Transport-Security
Default:
Strict-Transport-Security: max-age=15552000; includeSubDomains
The
Strict-Transport-Security
header tells browsers to prefer HTTPS instead of insecure HTTP. See the documentation on MDN for more.
// Sets "Strict-Transport-Security: max-age=15552000; includeSubDomains" app.use(helmet());
maxAge
is the number of seconds browsers should remember to prefer HTTPS. If passed a non-integer, the value is rounded down. It defaults to
15552000
, which is 180 days.
includeSubDomains
is a boolean which dictates whether to include the
includeSubDomains
directive, which makes this policy extend to subdomains. It defaults to
true
.
preload
is a boolean. If true, it adds the
preload
directive, expressing intent to add your HSTS policy to browsers. See the “Preloading Strict Transport Security” section on MDN for more. It defaults to
false
.
// Sets "Strict-Transport-Security: max-age=123456; includeSubDomains" app.use( helmet({ strictTransportSecurity: { maxAge: 123456, }, }) ); // Sets "Strict-Transport-Security: max-age=123456" app.use( helmet({ strictTransportSecurity: { maxAge: 123456, includeSubDomains: false, }, }) ); // Sets "Strict-Transport-Security: max-age=123456; includeSubDomains; preload" app.use( helmet({ strictTransportSecurity: { maxAge: 63072000, preload: true, }, }) );
To disable the
Strict-Transport-Security
header:
app.use( helmet({ strictTransportSecurity: false, }) );
You can use this as standalone middleware with
app.use(helmet.strictTransportSecurity())
.
X-Content-Type-Options
Default:
X-Content-Type-Options: nosniff
The
X-Content-Type-Options
mitigates MIME type sniffing which can cause security issues. See documentation for this header on MDN for more.
This header takes no options and is set by default.
// Sets "X-Content-Type-Options: nosniff" app.use(helmet());
To disable the
X-Content-Type-Options
header:
app.use( helmet({ xContentTypeOptions: false, }) );
You can use this as standalone middleware with
app.use(helmet.xContentTypeOptions())
.
X-DNS-Prefetch-Control
Default:
X-DNS-Prefetch-Control: off
The
X-DNS-Prefetch-Control
header helps control DNS prefetching, which can improve user privacy at the expense of performance. See documentation on MDN for more.
// Sets "X-DNS-Prefetch-Control: off" app.use(helmet());
allow
is a boolean dictating whether to enable DNS prefetching. It defaults to
false
.
Examples:
// Sets "X-DNS-Prefetch-Control: off" app.use( helmet({ xDnsPrefetchControl: { allow: false }, }) ); // Sets "X-DNS-Prefetch-Control: on" app.use( helmet({ xDnsPrefetchControl: { allow: true }, }) );
To disable the
X-DNS-Prefetch-Control
header and use the browser’s default value:
app.use( helmet({ xDnsPrefetchControl: false, }) );
You can use this as standalone middleware with
app.use(helmet.xDnsPrefetchControl())
.
X-Download-Options
Default:
X-Download-Options: noopen
The
X-Download-Options
header is specific to Internet Explorer 8. It forces potentially-unsafe downloads to be saved, mitigating execution of HTML in your site’s context. For more, see this old post on MSDN.
This header takes no options and is set by default.
// Sets "X-Download-Options: noopen" app.use(helmet());
To disable the
X-Download-Options
header:
app.use( helmet({ xDownloadOptions: false, }) );
You can use this as standalone middleware with
app.use(helmet.xDownloadOptions())
.
X-Frame-Options
Default:
X-Frame-Options: SAMEORIGIN
The legacy
X-Frame-Options
header to help you mitigate clickjacking attacks. This header is superseded by the
frame-ancestors
Content Security Policy directive but is still useful on old browsers or if no CSP is used. For more, see the documentation on MDN.
// Sets "X-Frame-Options: SAMEORIGIN" app.use(helmet());
action
is a string that specifies which directive to use—either
DENY
or
SAMEORIGIN
. (A legacy directive,
ALLOW-FROM
, is not supported by Helmet. Read more here.) It defaults to
SAMEORIGIN
.
Examples:
// Sets "X-Frame-Options: DENY" app.use( helmet({ xFrameOptions: { action: "deny" }, }) ); // Sets "X-Frame-Options: SAMEORIGIN" app.use( helmet({ xFrameOptions: { action: "sameorigin" }, }) );
To disable the
X-Frame-Options
header:
app.use( helmet({ xFrameOptions: false, }) );
You can use this as standalone middleware with
app.use(helmet.xFrameOptions())
.
X-Permitted-Cross-Domain-Policies
Default:
X-Permitted-Cross-Domain-Policies: none
The
X-Permitted-Cross-Domain-Policies
header tells some clients (mostly Adobe products) your domain’s policy for loading cross-domain content. See the description on OWASP for more.
// Sets "X-Permitted-Cross-Domain-Policies: none" app.use(helmet());
permittedPolicies
is a string that must be
"none"
,
"master-only"
,
"by-content-type"
, or
"all"
. It defaults to
"none"
.
Examples:
// Sets "X-Permitted-Cross-Domain-Policies: none" app.use( helmet({ xPermittedCrossDomainPolicies: { permittedPolicies: "none", }, }) ); // Sets "X-Permitted-Cross-Domain-Policies: by-content-type" app.use( helmet({ xPermittedCrossDomainPolicies: { permittedPolicies: "by-content-type", }, }) );
To disable the
X-Permitted-Cross-Domain-Policies
header:
app.use( helmet({ xPermittedCrossDomainPolicies: false, }) );
You can use this as standalone middleware with
app.use(helmet.xPermittedCrossDomainPolicies())
.
X-Powered-By
Default: the
X-Powered-By
header, if present, is removed.
Helmet removes the
X-Powered-By
header, which is set by default in Express and some other frameworks. Removing the header offers very limited security benefits (see this discussion) and is mostly removed to save bandwidth, but may thwart simplistic attackers.
Note: Express has a built-in way to disable the
X-Powered-By
header, which you may wish to use instead.
The removal of this header takes no options. The header is removed by default.
To disable this behavior:
// Not required, but recommended for Express users: app.disable("x-powered-by"); // Ask Helmet to ignore the X-Powered-By header. app.use( helmet({ xPoweredBy: false, }) );
You can use this as standalone middleware with
app.use(helmet.xPoweredBy())
.
X-XSS-Protection
Default:
X-XSS-Protection: 0
Helmet disables browsers’ buggy cross-site scripting filter by setting the legacy
X-XSS-Protection
header to . See discussion about disabling the header here and documentation on MDN.
This header takes no options and is set by default.
To disable the
X-XSS-Protection
header:
// This is not recommended. app.use( helmet({ xXssProtection: false, }) );
You can use this as standalone middleware with
app.use(helmet.xXssProtection())
.
Helmet
Helmet helps secure Express apps by setting HTTP response headers.
Bảo mật với cookie
Để đảm bảo rẳng cookies không khiến ứng dụng của bạn bị hack, tuyệt đối không sử dụng cookie name mặc định cũng như cần phải thiết lập đúng cách các options với cookie Đối với việc bảo mật cookies, chúng ta có thể sử dụng 2 packages sau:
-
express-session thay thế middleware mặc định
express.session
lên phiên bản Express 3.x. -
cookie-session thay thế middleware mặc định
express.cookieSession
lên phiên bản Express 3.x. Điểm khác biệt chính giữa hai packages này nằm ở cách chúng lưu trữ dữ liệu cookie session.
express-session
lưu trữ dữ liệu session tại server, nó chỉ sử dụng cookie để lữu trữ Session ID. Mặc định nó sẽ sử dụng bộ lưu trữ in-memory và cách lưu trữ này không được thiết kế để chạy với môi trường production. Với môi trường Production, bạn sẽ cần phải cài đặt một bộ lưu trữ session có tính linh hoạt cao và có khả năng mở rộng, xem danh sách được hỗ trợ: https://github.com/expressjs/session#compatible-session-stores
cookie-session
thì ngược lại, nó triển khai một bộ lưu trữ
cookie-backed
:
cookie-session
sẽ serializes toàn bộ dữ liệu session thành cookie. Chỉ sử dụng cách này khi dữ liệu session nhỏ và có thể dễ dàng để mã hóa. Mặc dù browser có thể hỗ trợ tối thiểu 4096 bytes cho mỗi cookie nhưng để đảm bảo bạn không bị quá giới hạn này thì tốt nhất không để cho size vượt quá 4093 bytes với mỗi cookie domain. Bạn cũng nên lưu ý rằng dữ liệu cookie là mở và có thể can thiệp bởi client, do đó trong trường hợp dữ liệu cookie là quan trọng thì tốt hơn nên sử dụng
express-session
.
Không sử dụng cookie name mặc định
Cũng giống như với việc dấu đi header
X-Powered-By
, chúng ta cũng nên thay đổi tên mặc định của cookie, điều này sẽ giúp ẩn dấu thông tin framework ta sử dụng
var session = require('express-session') app.set('trust proxy', 1) // trust first proxy app.use(session({ secret: 's3Cur3', name: 'sessionId' }))
Thiết lập các options nâng cao bảo mật
Cài đặt các options sau đây để giúp tăng cường bảo mật cho cookie:
- secure – Đảm bảo rằng browser sẽ chỉ gửi cookie qua HTTPS.
- httpOnly – Đảm bảo rằng cookie chỉ được gửi qua HTTP(S), không phải thông qua client JavaScript, giúp ngăn chặn tấn công cross-site scripting.
- domain – Chỉ định domain của cookie; Cookie chỉ hợp lệ đối với domain phát sinh request.
- path – Chỉ định path của cookie.
- expires – Thiết lập thời gian hết hạn cho cookie. Ví dụ về thiết lập bảo mật cho cookie
var session = require('cookie-session') var express = require('express') var app = express() var expiryDate = new Date(Date.now() + 60 * 60 * 1000) // 1 hour app.use(session({ name: 'session', keys: ['key1', 'key2'], cookie: { secure: true, httpOnly: true, domain: 'example.com', path: 'foo/bar', expires: expiryDate } }))
Cập nhật tất cả các packages hiện tại
NPM là một công cụ rất mạnh mẽ hỗ trợ quản lý các dependencies của ứng dụng, tuy nhiên các packages có thể tồn tại các lỗ hổng bảo mật có thể ảnh hưởng đến ứng dụng của bạn. Ứng dụng của bạn không thể đảm bảo được bảo mật nếu một trong các packages có lỗ hổng. Sử dụng các packages sau để kiểm tra bảo mật các packages bạn sử dụng:
Use either or both of the following two tools to help ensure the security of third-party packages that you use: nsp and Snyk.
nsp là một công cụ command-line giúp kiểm tra bảo mật dựa trên db các lỗ hổng đã biết.
$ npm i nsp -g
nsp check
Snyk cung cấp cả cli và Github integration để có thể check lỗ hổng nhanh và toàn diện hơn
$ npm install -g snyk $ cd your-app
snyk test
snyk wizard
Get started
Here’s a sample Express app that uses Helmet:
import express from "express"; import helmet from "helmet"; const app = express(); // Use Helmet! app.use(helmet()); app.get("/", (req, res) => { res.send("Hello world!"); }); app.listen(8000);
You can also
require("helmet")
if you prefer.
By default, Helmet sets the following headers:
-
Content-Security-Policy
: A powerful allow-list of what can happen on your page which mitigates many attacks -
Cross-Origin-Opener-Policy
: Helps process-isolate your page -
Cross-Origin-Resource-Policy
: Blocks others from loading your resources cross-origin -
Origin-Agent-Cluster
: Changes process isolation to be origin-based -
Referrer-Policy
: Controls the
Referer
header -
Strict-Transport-Security
: Tells browsers to prefer HTTPS -
X-Content-Type-Options
: Avoids MIME sniffing -
X-DNS-Prefetch-Control
: Controls DNS prefetching -
X-Download-Options
: Forces downloads to be saved (Internet Explorer only) -
X-Frame-Options
: Legacy header that mitigates clickjacking attacks -
X-Permitted-Cross-Domain-Policies
: Controls cross-domain behavior for Adobe products, like Acrobat -
X-Powered-By
: Info about the web server. Removed because it could be used in simple attacks -
X-XSS-Protection
: Legacy header that tries to mitigate XSS attacks, but makes things worse, so Helmet disables it
Each header can be configured. For example, here’s how you configure the
Content-Security-Policy
header:
// This sets custom options for the // Content-Security-Policy header. app.use( helmet({ contentSecurityPolicy: { directives: { "script-src": ["'self'", "example.com"], }, }, }) );
Headers can also be disabled. For example, here’s how you disable the
Content-Security-Policy
and
X-Download-Options
headers:
// This disables the Content-Security-Policy // and X-Download-Options headers. app.use( helmet({ contentSecurityPolicy: false, xDownloadOptions: false, }) );
Get started
Here’s a sample Express app that uses Helmet:
import express from "express"; import helmet from "helmet"; const app = express(); // Use Helmet! app.use(helmet()); app.get("/", (req, res) => { res.send("Hello world!"); }); app.listen(8000);
You can also
require("helmet")
if you prefer.
By default, Helmet sets the following headers:
-
Content-Security-Policy
: A powerful allow-list of what can happen on your page which mitigates many attacks -
Cross-Origin-Opener-Policy
: Helps process-isolate your page -
Cross-Origin-Resource-Policy
: Blocks others from loading your resources cross-origin -
Origin-Agent-Cluster
: Changes process isolation to be origin-based -
Referrer-Policy
: Controls the
Referer
header -
Strict-Transport-Security
: Tells browsers to prefer HTTPS -
X-Content-Type-Options
: Avoids MIME sniffing -
X-DNS-Prefetch-Control
: Controls DNS prefetching -
X-Download-Options
: Forces downloads to be saved (Internet Explorer only) -
X-Frame-Options
: Legacy header that mitigates clickjacking attacks -
X-Permitted-Cross-Domain-Policies
: Controls cross-domain behavior for Adobe products, like Acrobat -
X-Powered-By
: Info about the web server. Removed because it could be used in simple attacks -
X-XSS-Protection
: Legacy header that tries to mitigate XSS attacks, but makes things worse, so Helmet disables it
Each header can be configured. For example, here’s how you configure the
Content-Security-Policy
header:
// This sets custom options for the // Content-Security-Policy header. app.use( helmet({ contentSecurityPolicy: { directives: { "script-src": ["'self'", "example.com"], }, }, }) );
Headers can also be disabled. For example, here’s how you disable the
Content-Security-Policy
and
X-Download-Options
headers:
// This disables the Content-Security-Policy // and X-Download-Options headers. app.use( helmet({ contentSecurityPolicy: false, xDownloadOptions: false, }) );
Không sử dụng những phiên bản có lỗi hoặc không được khuyến khích (deprecated)
Phiên bản mới nhất (hiện tại) của Express.js là 4.16.1, với rất nhiều tính năng cải tiến về tốc độ cũng như bảo mật; các phiên bản tiền nhiệm như Express 2.x hoặc Express 3.x cũng rất mạnh mẽ và được đánh giá cao, tuy nhiên các phiên bản cũ này đã không còn được hỗ trợ nữa. Điều đó có nghĩa là tất cả những vấn đề về hiệu năng hay bảo mật của Express 2.x và Express 3.x sẽ không còn được khắc phục nữa. Vậy nên nếu bạn đang làm một ứng dụng mới sử dụng Express.js thì hãy nên sử dụng phiên bản mới nhất; nếu bạn vẫn đang sử dụng Express.js cũ cho các ứng dụng của mình thì nên xem xét cập nhật lên Express 4 nếu có thể. Ngoài ra thì để đảm bảo phiên bản mình sử dụng không phải là phiên bản lỗi thì bạn cũng có thể kiểm tra danh sách các phiên bản có lỗi tại đây
Sử dụng Transport Layer Security (TLS)
Nếu ứng dụng của bạn có làm việc với những dữ liệu quan trọng, hãy sử dụng Transport Layer Security (TLS) để bảo mật các kết nối và dữ liệu của mình. Công nghệ này sẽ mã hóa dữ liệu trước khi nó được gửi đi từ client lên server, điều này sẽ giúp ngăn chặn một số kỹ thuật hacking phổ biến. Mặc dù với Ajax và Post requets thì có vẻ như dữ liệu truyền đi đã bị che dấu (chúng ta không nhìn thấy nó như với GET request), tuy nhiên thì trong thực tế chúng vẫn có thể bị tấn công bởi các công cụ hỗ trợ packet sniffing hoặc tấn công man-in-the-middle Mã hóa Secure Socket Layer (SSL) được sử dụng rất phổ biến và chắc hẳn bạn đã gặp nó rất nhiều rồi. TLS đơn giản chỉ là quá trình tiền theo của SSL. Nói theo một cách khác thì nếu bạn đã sử dụng SSL trước đó thì hãy nên xem xét để nâng cấp lên TLS, TLS có thể được cài đặt rất dễ dàng thông qua Nginx. Bạn có thể tìm hiểu về cấu hình TLS với Nginx tại đây Ngoài ra thì bạn nên thử Let’s Encrypt, đó là một công cụ miễn phí, tự động hoàn toàn với chứng chỉ xác thực được cung cấp bởi Internet Security Research Group (ISRG)
Getting Started
How to Inspect Your HTTP Headers
First, you should become comfortable inspecting HTTP traffic generated by your app. All modern browsers have a “Developer Tool” feature that lets you inspect network traffic requested by the browser. In this example, we’ll use Chrome. You can find Developer Tools from the Chrome menu:
Next, click on the “Network” tab and select an HTTP request made by the browser. Since I am testing on my local machine, I’ve clicked ‘localhost’.
Chances are your Express application isn’t using Helmet.js or securely configuring HTTP headers, so you may see something like this:
You’ll notice that none of the security headers listed in the table above appear in the image. In fact, we are leaking our use of Express! Fortunately, this is a quick fix with Helmet.js.
How to Install Helmet.js
First, use npm to download Helmet.js (we’re assuming you already have Express installed):
npm install helmet --save
Then, include it in your app:
var express = require('express'); var app = express(); var helmet = require('helmet'); app.use(helmet());
Helmet will now implement it’s default HTTP header configurations when you start your Express app! You should see the HTTP response headers look something like this:
Notice how Helmet.js disables the
X-Powered-By
header? Pretty cool 🙂
Want a demo of Veracode Interactive Analysis?
Veracode Interactive Analysis (IAST) helps teams instantly discover vulnerabilities in their applications at runtime by embedding security into their development processes and integrating directly into their CI/CD pipelines. Get a demo.
If you’ve ever delved into Node.js, then there’s a high chance that you’ll also encounter Express.js — a minimalist web framework built to create Node.js web applications. It comes with HTTP utilities for rapidly developing APIs and provides the foundations of other major and popular Node.js frameworks such as Feathers, LoopBack, Blueprint, and Nest.js.
While Express is generally robust for assisting your full stack application builds and prototypes, it is not perfect when it comes to security. The reason for this is because Express is designed for creating web applications — not securing your Node.js server from vulnerabilities. The defaults leave the HTTP headers mostly open, in part, to assist with the rapid application development. This is where Helmet.js steps in.
Helmet.js fills in the gap between Node.js and Express.js by securing HTTP headers that are returned by your Express apps. HTTP, by design, is open in nature and highly insecure. It can leak sensitive information about your app and leave your data open to anyone with some tech skills to see.
In short, using the preset default HTTP headers is a sure way to quickly get your app and running, but at the potential cost of anyone having access to it in a malicious way. What makes it worse is that because end users tend to be uneducated over the importance of HTTPS over HTTP, developers tend to ignore it unless otherwise forced to use HTTPS by their security policies.
In this article, we will go over how to install Helmet.js, what the different headers are, and how to use them in Helmet.js.
Reference
Content-Security-Policy
Default:
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
The
Content-Security-Policy
header mitigates a large number of attacks, such as cross-site scripting. See MDN’s introductory article on Content Security Policy.
This header is powerful but likely requires some configuration.
To configure this header, pass an object with a nested
directives
object. Each key is a directive name in camel case (such as
defaultSrc
) or kebab case (such as
default-src
). Each value is an array (or other iterable) of strings or functions for that directive. If a function appears in the array, it will be called with the request and response objects.
// Sets all of the defaults, but overrides `script-src` // and disables the default `style-src`. app.use( helmet({ contentSecurityPolicy: { directives: { “script-src”: [“‘self'”, “example.com”], “style-src”: null, }, }, }), );
// Sets the `script-src` directive to // “‘self’ ‘nonce-e33ccde670f149c1789b1e1e113b0916′” // (or similar) app.use((req, res, next) => { res.locals.cspNonce = crypto.randomBytes(16).toString(“hex”); next(); }); app.use( helmet({ contentSecurityPolicy: { directives: { scriptSrc: [“‘self'”, (req, res) => `’nonce-${res.locals.cspNonce}’`], }, }, }), );
These directives are merged into a default policy, which you can disable by setting
useDefaults
to
false
.
// Sets “Content-Security-Policy: default-src ‘self’; // script-src ‘self’ example.com;object-src ‘none’; // upgrade-insecure-requests” app.use( helmet({ contentSecurityPolicy: { useDefaults: false, directives: { defaultSrc: [“‘self'”], scriptSrc: [“‘self'”, “example.com”], objectSrc: [“‘none'”], upgradeInsecureRequests: [], }, }, }), );
You can get the default directives object with
helmet.contentSecurityPolicy.getDefaultDirectives()
. Here is the default policy (whitespace added for readability):
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
The
default-src
directive can be explicitly disabled by setting its value to
helmet.contentSecurityPolicy.dangerouslyDisableDefaultSrc
, but this is not recommended.
You can set the
Content-Security-Policy-Report-Only
instead.
// Sets the Content-Security-Policy-Report-Only header app.use( helmet({ contentSecurityPolicy: { directives: { /* … */ }, reportOnly: true, }, }), );
Helmet performs very little validation on your CSP. You should rely on CSP checkers like CSP Evaluator instead.
To disable the
Content-Security-Policy
header:
app.use( helmet({ contentSecurityPolicy: false, }), );
You can use this as standalone middleware with
app.use(helmet.contentSecurityPolicy())
.
Cross-Origin-Embedder-Policy
This header is not set by default.
The
Cross-Origin-Embedder-Policy
header helps control what resources can be loaded cross-origin. See MDN’s article on this header for more.
// Helmet does not set Cross-Origin-Embedder-Policy // by default. app.use(helmet()); // Sets “Cross-Origin-Embedder-Policy: require-corp” app.use(helmet({ crossOriginEmbedderPolicy: true })); // Sets “Cross-Origin-Embedder-Policy: credentialless” app.use(helmet({ crossOriginEmbedderPolicy: { policy: “credentialless” } }));
You can use this as standalone middleware with
app.use(helmet.crossOriginEmbedderPolicy())
.
Cross-Origin-Opener-Policy
Default:
Cross-Origin-Opener-Policy: same-origin
The
Cross-Origin-Opener-Policy
header helps process-isolate your page. For more, see MDN’s article on this header.
// Sets “Cross-Origin-Opener-Policy: same-origin” app.use(helmet()); // Sets “Cross-Origin-Opener-Policy: same-origin-allow-popups” app.use( helmet({ crossOriginOpenerPolicy: { policy: “same-origin-allow-popups” }, }), );
To disable the
Cross-Origin-Opener-Policy
header:
app.use( helmet({ crossOriginOpenerPolicy: false, }), );
You can use this as standalone middleware with
app.use(helmet.crossOriginOpenerPolicy())
.
Cross-Origin-Resource-Policy
Default:
Cross-Origin-Resource-Policy: same-origin
The
Cross-Origin-Resource-Policy
header blocks others from loading your resources cross-origin in some cases. For more, see “Consider deploying Cross-Origin Resource Policy and MDN’s article on this header.
// Sets “Cross-Origin-Resource-Policy: same-origin” app.use(helmet()); // Sets “Cross-Origin-Resource-Policy: same-site” app.use(helmet({ crossOriginResourcePolicy: { policy: “same-site” } }));
To disable the
Cross-Origin-Resource-Policy
header:
app.use( helmet({ crossOriginResourcePolicy: false, }), );
You can use this as standalone middleware with
app.use(helmet.crossOriginResourcePolicy())
.
Origin-Agent-Cluster
Default:
Origin-Agent-Cluster: ?1
The
Origin-Agent-Cluster
header provides a mechanism to allow web applications to isolate their origins from other processes. Read more about it in the spec.
This header takes no options and is set by default.
// Sets “Origin-Agent-Cluster: ?1” app.use(helmet());
To disable the
Origin-Agent-Cluster
header:
app.use( helmet({ originAgentCluster: false, }), );
You can use this as standalone middleware with
app.use(helmet.originAgentCluster())
.
Referrer-Policy
Default:
Referrer-Policy: no-referrer
The
Referrer-Policy
header which controls what information is set in the
Referer
request header. See “Referer header: privacy and security concerns” and the header’s documentation on MDN for more.
// Sets “Referrer-Policy: no-referrer” app.use(helmet());
policy
is a string or array of strings representing the policy. If passed as an array, it will be joined with commas, which is useful when setting a fallback policy. It defaults to
no-referrer
.
// Sets “Referrer-Policy: no-referrer” app.use( helmet({ referrerPolicy: { policy: “no-referrer”, }, }), ); // Sets “Referrer-Policy: origin,unsafe-url” app.use( helmet({ referrerPolicy: { policy: [“origin”, “unsafe-url”], }, }), );
To disable the
Referrer-Policy
header:
app.use( helmet({ referrerPolicy: false, }), );
You can use this as standalone middleware with
app.use(helmet.referrerPolicy())
.
Strict-Transport-Security
Default:
Strict-Transport-Security: max-age=15552000; includeSubDomains
The
Strict-Transport-Security
header tells browsers to prefer HTTPS instead of insecure HTTP. See the documentation on MDN for more.
// Sets “Strict-Transport-Security: max-age=15552000; includeSubDomains” app.use(helmet());
maxAge
is the number of seconds browsers should remember to prefer HTTPS. If passed a non-integer, the value is rounded down. It defaults to
15552000
, which is 180 days.
includeSubDomains
is a boolean which dictates whether to include the
includeSubDomains
directive, which makes this policy extend to subdomains. It defaults to
true
.
preload
is a boolean. If true, it adds the
preload
directive, expressing intent to add your HSTS policy to browsers. See the “Preloading Strict Transport Security” section on MDN for more. It defaults to
false
.
// Sets “Strict-Transport-Security: max-age=123456; includeSubDomains” app.use( helmet({ strictTransportSecurity: { maxAge: 123456, }, }), ); // Sets “Strict-Transport-Security: max-age=123456” app.use( helmet({ strictTransportSecurity: { maxAge: 123456, includeSubDomains: false, }, }), ); // Sets “Strict-Transport-Security: max-age=123456; includeSubDomains; preload” app.use( helmet({ strictTransportSecurity: { maxAge: 63072000, preload: true, }, }), );
To disable the
Strict-Transport-Security
header:
app.use( helmet({ strictTransportSecurity: false, }), );
You can use this as standalone middleware with
app.use(helmet.strictTransportSecurity())
.
X-Content-Type-Options
Default:
X-Content-Type-Options: nosniff
The
X-Content-Type-Options
mitigates MIME type sniffing which can cause security issues. See documentation for this header on MDN for more.
This header takes no options and is set by default.
// Sets “X-Content-Type-Options: nosniff” app.use(helmet());
To disable the
X-Content-Type-Options
header:
app.use( helmet({ xContentTypeOptions: false, }), );
You can use this as standalone middleware with
app.use(helmet.xContentTypeOptions())
.
X-DNS-Prefetch-Control
Default:
X-DNS-Prefetch-Control: off
The
X-DNS-Prefetch-Control
header helps control DNS prefetching, which can improve user privacy at the expense of performance. See documentation on MDN for more.
// Sets “X-DNS-Prefetch-Control: off” app.use(helmet());
allow
is a boolean dictating whether to enable DNS prefetching. It defaults to
false
.
Examples:
// Sets “X-DNS-Prefetch-Control: off” app.use( helmet({ xDnsPrefetchControl: { allow: false }, }), ); // Sets “X-DNS-Prefetch-Control: on” app.use( helmet({ xDnsPrefetchControl: { allow: true }, }), );
To disable the
X-DNS-Prefetch-Control
header and use the browser’s default value:
app.use( helmet({ xDnsPrefetchControl: false, }), );
You can use this as standalone middleware with
app.use(helmet.xDnsPrefetchControl())
.
X-Download-Options
Default:
X-Download-Options: noopen
The
X-Download-Options
header is specific to Internet Explorer 8. It forces potentially-unsafe downloads to be saved, mitigating execution of HTML in your site’s context. For more, see this old post on MSDN.
This header takes no options and is set by default.
// Sets “X-Download-Options: noopen” app.use(helmet());
To disable the
X-Download-Options
header:
app.use( helmet({ xDownloadOptions: false, }), );
You can use this as standalone middleware with
app.use(helmet.xDownloadOptions())
.
X-Frame-Options
Default:
X-Frame-Options: SAMEORIGIN
The legacy
X-Frame-Options
header to help you mitigate clickjacking attacks. This header is superseded by the
frame-ancestors
Content Security Policy directive but is still useful on old browsers or if no CSP is used. For more, see the documentation on MDN.
// Sets “X-Frame-Options: SAMEORIGIN” app.use(helmet());
action
is a string that specifies which directive to use—either
DENY
or
SAMEORIGIN
. (A legacy directive,
ALLOW-FROM
, is not supported by Helmet. Read more here.) It defaults to
SAMEORIGIN
.
Examples:
// Sets “X-Frame-Options: DENY” app.use( helmet({ xFrameOptions: { action: “deny” }, }), ); // Sets “X-Frame-Options: SAMEORIGIN” app.use( helmet({ xFrameOptions: { action: “sameorigin” }, }), );
To disable the
X-Frame-Options
header:
app.use( helmet({ xFrameOptions: false, }), );
You can use this as standalone middleware with
app.use(helmet.xFrameOptions())
.
X-Permitted-Cross-Domain-Policies
Default:
X-Permitted-Cross-Domain-Policies: none
The
X-Permitted-Cross-Domain-Policies
header tells some clients (mostly Adobe products) your domain’s policy for loading cross-domain content. See the description on OWASP for more.
// Sets “X-Permitted-Cross-Domain-Policies: none” app.use(helmet());
permittedPolicies
is a string that must be
"none"
,
"master-only"
,
"by-content-type"
, or
"all"
. It defaults to
"none"
.
Examples:
// Sets “X-Permitted-Cross-Domain-Policies: none” app.use( helmet({ xPermittedCrossDomainPolicies: { permittedPolicies: “none”, }, }), ); // Sets “X-Permitted-Cross-Domain-Policies: by-content-type” app.use( helmet({ xPermittedCrossDomainPolicies: { permittedPolicies: “by-content-type”, }, }), );
To disable the
X-Permitted-Cross-Domain-Policies
header:
app.use( helmet({ xPermittedCrossDomainPolicies: false, }), );
You can use this as standalone middleware with
app.use(helmet.xPermittedCrossDomainPolicies())
.
X-Powered-By
Default: the
X-Powered-By
header, if present, is removed.
Helmet removes the
X-Powered-By
header, which is set by default in Express and some other frameworks. Removing the header offers very limited security benefits (see this discussion) and is mostly removed to save bandwidth, but may thwart simplistic attackers.
Note: Express has a built-in way to disable the
X-Powered-By
header, which you may wish to use instead.
The removal of this header takes no options. The header is removed by default.
To disable this behavior:
// Not required, but recommended for Express users: app.disable(“x-powered-by”); // Ask Helmet to ignore the X-Powered-By header. app.use( helmet({ xPoweredBy: false, }), );
You can use this as standalone middleware with
app.use(helmet.xPoweredBy())
.
X-XSS-Protection
Default:
X-XSS-Protection: 0
Helmet disables browsers’ buggy cross-site scripting filter by setting the legacy
X-XSS-Protection
header to . See discussion about disabling the header here and documentation on MDN.
This header takes no options and is set by default.
To disable the
X-XSS-Protection
header:
// This is not recommended. app.use( helmet({ xXssProtection: false, }), );
You can use this as standalone middleware with
app.use(helmet.xXssProtection())
.
Helmet helps secure Express apps by setting HTTP response headers.
Keywords searched by users: helmet in node js
Categories: Sưu tầm 40 Helmet In Node Js
See more here: kientrucannam.vn
See more: https://kientrucannam.vn/vn/