Skip to content

Commit c00a01d

Browse files
Implement security headers plugin for Docusaurus (#132)
- Added a new security headers plugin to enhance application security by preventing clickjacking, MIME type sniffing, and enforcing content security policies. - Configured the plugin to set appropriate HTTP headers in both development and production environments. - Created a static _headers file to define security headers for production deployment.
1 parent 991b86f commit c00a01d

File tree

3 files changed

+49
-0
lines changed

3 files changed

+49
-0
lines changed

docusaurus.config.ts

+2
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ const config: Config = {
7171
hideSearchBarWithNoSearchContext: false,
7272
},
7373
],
74+
// Add security headers plugin
75+
require.resolve('./src/plugins/security-headers-plugin'),
7476
],
7577

7678
themeConfig: {
+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/**
2+
* Security Headers Plugin for Docusaurus
3+
*
4+
* This plugin adds security headers to protect against clickjacking and other vulnerabilities.
5+
* It works by adding middleware to the development server and generating a _headers file for production.
6+
*/
7+
8+
module.exports = function securityHeadersPlugin(context, options) {
9+
return {
10+
name: 'security-headers-plugin',
11+
12+
// For development server
13+
configureDevServer(app) {
14+
app.use((req, res, next) => {
15+
// Prevent clickjacking
16+
res.setHeader('X-Frame-Options', 'DENY');
17+
18+
// Prevent MIME type sniffing
19+
res.setHeader('X-Content-Type-Options', 'nosniff');
20+
21+
// Control referrer information
22+
res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');
23+
24+
// Content Security Policy
25+
res.setHeader(
26+
'Content-Security-Policy',
27+
"default-src 'self'; script-src 'self' 'unsafe-inline' https://cdnjs.cloudflare.com https://cdn.jsdelivr.net https://www.googletagmanager.com; style-src 'self' 'unsafe-inline' https://cdnjs.cloudflare.com https://cdn.jsdelivr.net; img-src 'self' data: https://www.google-analytics.com; font-src 'self' https://cdnjs.cloudflare.com; frame-ancestors 'none'; connect-src 'self' https://www.google-analytics.com https://www.googletagmanager.com;"
28+
);
29+
30+
// HTTPS enforcement
31+
res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
32+
33+
// Permissions policy
34+
res.setHeader('Permissions-Policy', 'geolocation=(), microphone=(), camera=()');
35+
36+
next();
37+
});
38+
},
39+
};
40+
};

static/_headers

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/*
2+
X-Frame-Options: DENY
3+
X-Content-Type-Options: nosniff
4+
Referrer-Policy: strict-origin-when-cross-origin
5+
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' https://cdnjs.cloudflare.com https://cdn.jsdelivr.net https://www.googletagmanager.com; style-src 'self' 'unsafe-inline' https://cdnjs.cloudflare.com https://cdn.jsdelivr.net; img-src 'self' data: https://www.google-analytics.com; font-src 'self' https://cdnjs.cloudflare.com; frame-ancestors 'none'; connect-src 'self' https://www.google-analytics.com https://www.googletagmanager.com;
6+
Strict-Transport-Security: max-age=31536000; includeSubDomains
7+
Permissions-Policy: geolocation=(), microphone=(), camera=()

0 commit comments

Comments
 (0)