Add comprehensive security headers support with testing framework
This commit is contained in:
parent
c0502bc1a4
commit
68afb6fc6c
19
README.md
19
README.md
|
@ -75,7 +75,8 @@ The `security` section in the configuration allows you to control various securi
|
||||||
"hsts": false, // Enable HTTP Strict Transport Security
|
"hsts": false, // Enable HTTP Strict Transport Security
|
||||||
"scriptSources": [], // Additional allowed script sources
|
"scriptSources": [], // Additional allowed script sources
|
||||||
"bypassCSPInDev": false, // Use permissive CSP in development mode
|
"bypassCSPInDev": false, // Use permissive CSP in development mode
|
||||||
"allowUnsafeHashes": true // Allow 'unsafe-hashes' in production for event handlers
|
"allowUnsafeHashes": true, // Allow 'unsafe-hashes' in production for event handlers
|
||||||
|
"enableCrossOriginIsolation": false // Enable strict Cross-Origin isolation headers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -87,6 +88,7 @@ The `security` section in the configuration allows you to control various securi
|
||||||
* `scriptSources` - Additional script sources to allow - comma-separated list in env vars
|
* `scriptSources` - Additional script sources to allow - comma-separated list in env vars
|
||||||
* `bypassCSPInDev` - In development mode (NODE_ENV=development), use a more permissive CSP that includes 'unsafe-inline' (default: false)
|
* `bypassCSPInDev` - In development mode (NODE_ENV=development), use a more permissive CSP that includes 'unsafe-inline' (default: false)
|
||||||
* `allowUnsafeHashes` - Allow 'unsafe-hashes' in production mode for DOM event handlers (default: true)
|
* `allowUnsafeHashes` - Allow 'unsafe-hashes' in production mode for DOM event handlers (default: true)
|
||||||
|
* `enableCrossOriginIsolation` - Enable strict Cross-Origin isolation headers (COEP, COOP, CORP) which enhance security but may break certain integrations (default: false)
|
||||||
|
|
||||||
### Environment Variables for Security Settings
|
### Environment Variables for Security Settings
|
||||||
|
|
||||||
|
@ -96,6 +98,7 @@ You can set these options through environment variables:
|
||||||
* `HASTEBIN_SCRIPT_SOURCES` - Additional script sources (comma-separated)
|
* `HASTEBIN_SCRIPT_SOURCES` - Additional script sources (comma-separated)
|
||||||
* `HASTEBIN_BYPASS_CSP_IN_DEV` - Allow unsafe-inline in development (true/false)
|
* `HASTEBIN_BYPASS_CSP_IN_DEV` - Allow unsafe-inline in development (true/false)
|
||||||
* `HASTEBIN_ALLOW_UNSAFE_HASHES` - Allow unsafe-hashes in production (true/false)
|
* `HASTEBIN_ALLOW_UNSAFE_HASHES` - Allow unsafe-hashes in production (true/false)
|
||||||
|
* `HASTEBIN_ENABLE_CROSS_ORIGIN_ISOLATION` - Enable Cross-Origin isolation headers (true/false)
|
||||||
|
|
||||||
### CSP Implementation Details
|
### CSP Implementation Details
|
||||||
|
|
||||||
|
@ -106,6 +109,20 @@ The Content Security Policy implementation in Hastebin uses nonces to secure inl
|
||||||
3. **Production Mode**: In production, the CSP is configured to use nonces for all scripts, with optional 'unsafe-hashes' for event handlers
|
3. **Production Mode**: In production, the CSP is configured to use nonces for all scripts, with optional 'unsafe-hashes' for event handlers
|
||||||
4. **Templates**: The template system automatically injects nonces into script tags, so you don't need to manually add them to the HTML
|
4. **Templates**: The template system automatically injects nonces into script tags, so you don't need to manually add them to the HTML
|
||||||
|
|
||||||
|
### Additional Security Headers
|
||||||
|
|
||||||
|
Besides CSP, Hastebin implements several other security headers:
|
||||||
|
|
||||||
|
1. **X-Content-Type-Options**: `nosniff` - Prevents MIME-type sniffing
|
||||||
|
2. **X-Frame-Options**: `DENY` - Prevents clickjacking attacks
|
||||||
|
3. **X-XSS-Protection**: `1; mode=block` - An additional layer of XSS protection
|
||||||
|
4. **Referrer-Policy**: `strict-origin-when-cross-origin` - Controls referrer information
|
||||||
|
5. **Permissions-Policy**: Restricts browser features (camera, microphone, geolocation, etc.)
|
||||||
|
6. **Cross-Origin-Embedder-Policy**: `require-corp` - Enhances cross-origin isolation
|
||||||
|
7. **Cross-Origin-Resource-Policy**: `same-origin` - Protects resources from unauthorized requests
|
||||||
|
8. **Cross-Origin-Opener-Policy**: `same-origin` - Helps with cross-origin isolation
|
||||||
|
9. **Strict-Transport-Security**: `max-age=31536000; includeSubDomains; preload` - Ensures HTTPS usage (when enabled)
|
||||||
|
|
||||||
#### Running in Development Mode
|
#### Running in Development Mode
|
||||||
|
|
||||||
To run Hastebin with a more permissive CSP for development:
|
To run Hastebin with a more permissive CSP for development:
|
||||||
|
|
|
@ -35,7 +35,12 @@ const config = {
|
||||||
// Allow unsafe-hashes in production for event handlers (default: true)
|
// Allow unsafe-hashes in production for event handlers (default: true)
|
||||||
// This adds 'unsafe-hashes' to the policy for DOM event handlers
|
// This adds 'unsafe-hashes' to the policy for DOM event handlers
|
||||||
allowUnsafeHashes: process.env.HASTEBIN_ALLOW_UNSAFE_HASHES ?
|
allowUnsafeHashes: process.env.HASTEBIN_ALLOW_UNSAFE_HASHES ?
|
||||||
(process.env.HASTEBIN_ALLOW_UNSAFE_HASHES.toLowerCase() === 'true') : true
|
(process.env.HASTEBIN_ALLOW_UNSAFE_HASHES.toLowerCase() === 'true') : true,
|
||||||
|
|
||||||
|
// Enable Cross-Origin isolation headers (default: false)
|
||||||
|
// This adds COOP, COEP, and CORP headers - can break some integrations
|
||||||
|
enableCrossOriginIsolation: process.env.HASTEBIN_ENABLE_CROSS_ORIGIN_ISOLATION ?
|
||||||
|
(process.env.HASTEBIN_ENABLE_CROSS_ORIGIN_ISOLATION.toLowerCase() === 'true') : false
|
||||||
},
|
},
|
||||||
|
|
||||||
// Logging configuration
|
// Logging configuration
|
||||||
|
|
|
@ -1,22 +1,61 @@
|
||||||
services:
|
services:
|
||||||
redis:
|
redis:
|
||||||
image: eqalpha/keydb
|
image: git.nixc.us/colin/haste:production-redis
|
||||||
volumes:
|
volumes:
|
||||||
- redis_data:/data
|
- redis_data:/data
|
||||||
networks:
|
networks:
|
||||||
- default
|
- default
|
||||||
|
deploy:
|
||||||
|
placement:
|
||||||
|
constraints:
|
||||||
|
- node.hostname == macmini3
|
||||||
|
replicas: 1
|
||||||
|
restart_policy:
|
||||||
|
condition: on-failure
|
||||||
|
|
||||||
haste:
|
haste:
|
||||||
image: git.nixc.us/colin/haste:production-haste
|
image: git.nixc.us/colin/haste:production-haste
|
||||||
volumes:
|
volumes:
|
||||||
- public_system:/haste/public/system
|
- public_system:/haste/public/system
|
||||||
|
environment:
|
||||||
|
- NODE_ENV=production
|
||||||
|
- HASTEBIN_ENABLE_CSP=true
|
||||||
|
- HASTEBIN_ENABLE_HSTS=true
|
||||||
|
- HASTEBIN_ALLOW_UNSAFE_HASHES=true
|
||||||
|
- HASTEBIN_SCRIPT_SOURCES=
|
||||||
|
- HASTEBIN_BYPASS_CSP_IN_DEV=false
|
||||||
networks:
|
networks:
|
||||||
- traefik
|
- traefik
|
||||||
- default
|
- default
|
||||||
|
deploy:
|
||||||
|
placement:
|
||||||
|
constraints:
|
||||||
|
- node.hostname == macmini3
|
||||||
|
labels:
|
||||||
|
homepage.group: apps
|
||||||
|
homepage.name: HasteBin
|
||||||
|
homepage.href: https://haste.nixc.us/
|
||||||
|
homepage.description: HasteBin
|
||||||
|
us.nixc.autodeploy: "true"
|
||||||
|
traefik.enable: "true"
|
||||||
|
traefik.http.routers.production-haste_haste.rule: "Host(`haste.nixc.us`)"
|
||||||
|
traefik.http.routers.production-haste_haste.entrypoints: "websecure"
|
||||||
|
traefik.http.routers.production-haste_haste.tls: "true"
|
||||||
|
traefik.http.routers.production-haste_haste.tls.certresolver: "letsencryptresolver"
|
||||||
|
traefik.http.routers.production-haste_haste.service: "production-haste_haste"
|
||||||
|
traefik.http.services.production-haste_haste.loadbalancer.server.port: "7777"
|
||||||
|
traefik.docker.network: "traefik"
|
||||||
|
|
||||||
|
replicas: 1
|
||||||
|
restart_policy:
|
||||||
|
condition: on-failure
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
traefik:
|
traefik:
|
||||||
external: true
|
external: true
|
||||||
default:
|
default:
|
||||||
driver: overlay
|
driver: overlay
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
public_system:
|
public_system:
|
||||||
driver: local
|
driver: local
|
||||||
|
|
174
lib/csp.js
174
lib/csp.js
|
@ -6,104 +6,138 @@
|
||||||
const crypto = require('crypto');
|
const crypto = require('crypto');
|
||||||
const winston = require('winston');
|
const winston = require('winston');
|
||||||
|
|
||||||
// CSP middleware
|
// Security headers middleware (renamed from CSP middleware as it now handles more headers)
|
||||||
function cspMiddleware(config) {
|
function securityMiddleware(config) {
|
||||||
// Default to enabled if not specified
|
// Default to enabled if not specified
|
||||||
const enabled = config.security && typeof config.security.csp !== 'undefined' ?
|
const cspEnabled = config.security && typeof config.security.csp !== 'undefined' ?
|
||||||
config.security.csp : true;
|
config.security.csp : true;
|
||||||
|
|
||||||
// If CSP is disabled, return a no-op middleware
|
// If security is entirely disabled, return a no-op middleware
|
||||||
if (!enabled) {
|
// Note: This is different from just disabling CSP
|
||||||
|
if (config.security === false) {
|
||||||
return function(req, res, next) { next(); };
|
return function(req, res, next) { next(); };
|
||||||
}
|
}
|
||||||
|
|
||||||
return function(req, res, next) {
|
return function(req, res, next) {
|
||||||
// Only add CSP headers for HTML requests
|
// Only add security headers for HTML requests
|
||||||
const isHtmlRequest = req.url === '/' || req.url.match(/^\/[a-zA-Z0-9_-]+$/);
|
const isHtmlRequest = req.url === '/' || req.url.match(/^\/[a-zA-Z0-9_-]+$/);
|
||||||
|
|
||||||
if (isHtmlRequest) {
|
if (isHtmlRequest) {
|
||||||
// Generate a unique nonce for this request
|
// Apply CSP headers if enabled
|
||||||
const nonce = crypto.randomBytes(16).toString('base64');
|
if (cspEnabled) {
|
||||||
|
// Generate a unique nonce for this request
|
||||||
// Store nonce in request object for use in HTML template
|
const nonce = crypto.randomBytes(16).toString('base64');
|
||||||
req.cspNonce = nonce;
|
|
||||||
|
|
||||||
// Build the base script sources list
|
|
||||||
const scriptSources = ["'self'", `'nonce-${nonce}'`];
|
|
||||||
|
|
||||||
// Add any additional script sources from config
|
|
||||||
if (config.security && config.security.scriptSources && config.security.scriptSources.length > 0) {
|
|
||||||
config.security.scriptSources.forEach(source => {
|
|
||||||
if (source && !scriptSources.includes(source)) {
|
|
||||||
scriptSources.push(source);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add unsafe-hashes if configured (for event handlers)
|
|
||||||
if (config.security && config.security.allowUnsafeHashes) {
|
|
||||||
scriptSources.push("'unsafe-hashes'");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the policy - adjust based on environment
|
|
||||||
let cspDirectives;
|
|
||||||
|
|
||||||
// Development mode with potential bypass option
|
|
||||||
if (process.env.NODE_ENV === 'development') {
|
|
||||||
// Check if we should bypass strict CSP in development
|
|
||||||
const bypassCSPInDev = config.security && config.security.bypassCSPInDev;
|
|
||||||
|
|
||||||
if (bypassCSPInDev) {
|
// Store nonce in request object for use in HTML template
|
||||||
// Very permissive policy with unsafe-inline for development testing
|
req.cspNonce = nonce;
|
||||||
cspDirectives = [
|
|
||||||
"default-src 'self'",
|
// Build the base script sources list
|
||||||
"script-src 'self' 'unsafe-inline' 'unsafe-eval'",
|
const scriptSources = ["'self'", `'nonce-${nonce}'`];
|
||||||
"style-src 'self' 'unsafe-inline'",
|
|
||||||
"img-src 'self' data:",
|
// Add any additional script sources from config
|
||||||
"connect-src 'self'",
|
if (config.security && config.security.scriptSources && config.security.scriptSources.length > 0) {
|
||||||
"font-src 'self'"
|
config.security.scriptSources.forEach(source => {
|
||||||
];
|
if (source && !scriptSources.includes(source)) {
|
||||||
|
scriptSources.push(source);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add unsafe-hashes if configured (for event handlers)
|
||||||
|
if (config.security && config.security.allowUnsafeHashes) {
|
||||||
|
scriptSources.push("'unsafe-hashes'");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the policy - adjust based on environment
|
||||||
|
let cspDirectives;
|
||||||
|
|
||||||
|
// Development mode with potential bypass option
|
||||||
|
if (process.env.NODE_ENV === 'development') {
|
||||||
|
// Check if we should bypass strict CSP in development
|
||||||
|
const bypassCSPInDev = config.security && config.security.bypassCSPInDev;
|
||||||
|
|
||||||
winston.debug('Using permissive development CSP policy with unsafe-inline (bypass enabled)');
|
if (bypassCSPInDev) {
|
||||||
|
// Very permissive policy with unsafe-inline for development testing
|
||||||
|
cspDirectives = [
|
||||||
|
"default-src 'self'",
|
||||||
|
"script-src 'self' 'unsafe-inline' 'unsafe-eval'",
|
||||||
|
"style-src 'self' 'unsafe-inline'",
|
||||||
|
"img-src 'self' data:",
|
||||||
|
"connect-src 'self'",
|
||||||
|
"font-src 'self'"
|
||||||
|
];
|
||||||
|
|
||||||
|
winston.debug('Using permissive development CSP policy with unsafe-inline (bypass enabled)');
|
||||||
|
} else {
|
||||||
|
// Standard development mode - still using nonces
|
||||||
|
cspDirectives = [
|
||||||
|
"default-src 'self'",
|
||||||
|
`script-src ${scriptSources.join(' ')}`,
|
||||||
|
"style-src 'self' 'unsafe-inline'",
|
||||||
|
"img-src 'self' data:",
|
||||||
|
"connect-src 'self'",
|
||||||
|
"font-src 'self'"
|
||||||
|
];
|
||||||
|
|
||||||
|
winston.debug('Using development CSP policy with nonces (bypass disabled)');
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Standard development mode - still using nonces
|
// Production mode - strict policy with nonces
|
||||||
cspDirectives = [
|
cspDirectives = [
|
||||||
"default-src 'self'",
|
"default-src 'self'",
|
||||||
`script-src ${scriptSources.join(' ')}`,
|
`script-src ${scriptSources.join(' ')}`,
|
||||||
"style-src 'self' 'unsafe-inline'",
|
"style-src 'self' 'unsafe-inline'",
|
||||||
"img-src 'self' data:",
|
"img-src 'self' data:",
|
||||||
"connect-src 'self'",
|
"connect-src 'self'",
|
||||||
"font-src 'self'"
|
"font-src 'self'",
|
||||||
|
"frame-ancestors 'none'",
|
||||||
|
"base-uri 'self'",
|
||||||
|
"form-action 'none'",
|
||||||
|
"object-src 'none'"
|
||||||
];
|
];
|
||||||
|
|
||||||
winston.debug('Using development CSP policy with nonces (bypass disabled)');
|
winston.debug(`Using strict production CSP policy with nonces${config.security.allowUnsafeHashes ? " and unsafe-hashes" : ""}`);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// Production mode - strict policy with nonces
|
|
||||||
cspDirectives = [
|
|
||||||
"default-src 'self'",
|
|
||||||
`script-src ${scriptSources.join(' ')}`,
|
|
||||||
"style-src 'self' 'unsafe-inline'",
|
|
||||||
"img-src 'self' data:",
|
|
||||||
"connect-src 'self'",
|
|
||||||
"font-src 'self'",
|
|
||||||
"frame-ancestors 'none'",
|
|
||||||
"base-uri 'self'",
|
|
||||||
"form-action 'none'",
|
|
||||||
"object-src 'none'"
|
|
||||||
];
|
|
||||||
|
|
||||||
winston.debug(`Using strict production CSP policy with nonces${config.security.allowUnsafeHashes ? " and unsafe-hashes" : ""}`);
|
// Set the CSP header with the properly formatted policy
|
||||||
|
res.setHeader('Content-Security-Policy', cspDirectives.join('; '));
|
||||||
|
} else {
|
||||||
|
winston.debug('CSP is disabled by configuration');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the CSP header with the properly formatted policy
|
// Add other security headers - always applied regardless of CSP setting
|
||||||
res.setHeader('Content-Security-Policy', cspDirectives.join('; '));
|
|
||||||
|
|
||||||
// Add other security headers
|
// 1. X-Content-Type-Options - prevents MIME-type sniffing
|
||||||
res.setHeader('X-Content-Type-Options', 'nosniff');
|
res.setHeader('X-Content-Type-Options', 'nosniff');
|
||||||
|
|
||||||
|
// 2. X-Frame-Options - prevents clickjacking
|
||||||
res.setHeader('X-Frame-Options', 'DENY');
|
res.setHeader('X-Frame-Options', 'DENY');
|
||||||
|
|
||||||
|
// 3. X-XSS-Protection - legacy header, still used by some browsers
|
||||||
res.setHeader('X-XSS-Protection', '1; mode=block');
|
res.setHeader('X-XSS-Protection', '1; mode=block');
|
||||||
res.setHeader('Referrer-Policy', 'no-referrer');
|
|
||||||
|
// 4. Referrer-Policy - controls how much referrer information is included
|
||||||
|
res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');
|
||||||
|
|
||||||
|
// 5. Permissions-Policy - controls browser features
|
||||||
|
res.setHeader('Permissions-Policy', 'camera=(), microphone=(), geolocation=(), interest-cohort=()');
|
||||||
|
|
||||||
|
// Add Cross-Origin headers only if enabled in config
|
||||||
|
// These can be problematic for some applications, so we make them optional
|
||||||
|
const enableCrossOriginIsolation = config.security && config.security.enableCrossOriginIsolation;
|
||||||
|
|
||||||
|
if (enableCrossOriginIsolation) {
|
||||||
|
// 6. Cross-Origin-Embedder-Policy - for cross-origin isolation
|
||||||
|
res.setHeader('Cross-Origin-Embedder-Policy', 'require-corp');
|
||||||
|
|
||||||
|
// 7. Cross-Origin-Resource-Policy - protects resources from unauthorized requests
|
||||||
|
res.setHeader('Cross-Origin-Resource-Policy', 'same-origin');
|
||||||
|
|
||||||
|
// 8. Cross-Origin-Opener-Policy - helps with cross-origin isolation
|
||||||
|
res.setHeader('Cross-Origin-Opener-Policy', 'same-origin');
|
||||||
|
|
||||||
|
winston.debug('Added Cross-Origin isolation headers');
|
||||||
|
}
|
||||||
|
|
||||||
// If configured, add HSTS header
|
// If configured, add HSTS header
|
||||||
if (config.security && config.security.hsts) {
|
if (config.security && config.security.hsts) {
|
||||||
|
@ -116,4 +150,4 @@ function cspMiddleware(config) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Export the middleware
|
// Export the middleware
|
||||||
module.exports = cspMiddleware;
|
module.exports = securityMiddleware;
|
|
@ -11,7 +11,7 @@ var connect_st = require('st');
|
||||||
var connect_rate_limit = require('connect-ratelimit');
|
var connect_rate_limit = require('connect-ratelimit');
|
||||||
|
|
||||||
var DocumentHandler = require('./lib/document_handler');
|
var DocumentHandler = require('./lib/document_handler');
|
||||||
var cspMiddleware = require('./lib/csp');
|
var securityMiddleware = require('./lib/csp');
|
||||||
var templateHandler = require('./lib/template_handler');
|
var templateHandler = require('./lib/template_handler');
|
||||||
|
|
||||||
// Load the configuration
|
// Load the configuration
|
||||||
|
@ -116,7 +116,7 @@ var documentHandler = new DocumentHandler({
|
||||||
var app = connect();
|
var app = connect();
|
||||||
|
|
||||||
// Add CSP middleware early in the chain
|
// Add CSP middleware early in the chain
|
||||||
app.use(cspMiddleware(config));
|
app.use(securityMiddleware(config));
|
||||||
|
|
||||||
// Add CORS support
|
// Add CORS support
|
||||||
app.use(function(req, res, next) {
|
app.use(function(req, res, next) {
|
||||||
|
|
|
@ -56,7 +56,13 @@ const TESTS = {
|
||||||
name: 'Disabled CSP',
|
name: 'Disabled CSP',
|
||||||
env: { NODE_ENV: 'production', HASTEBIN_ENABLE_CSP: 'false' },
|
env: { NODE_ENV: 'production', HASTEBIN_ENABLE_CSP: 'false' },
|
||||||
expectedHeaders: {
|
expectedHeaders: {
|
||||||
'content-security-policy': false
|
'content-security-policy': false,
|
||||||
|
// Even with CSP disabled, these headers should still be present
|
||||||
|
'x-content-type-options': 'nosniff',
|
||||||
|
'x-frame-options': 'DENY',
|
||||||
|
'x-xss-protection': '1; mode=block',
|
||||||
|
'referrer-policy': 'strict-origin-when-cross-origin',
|
||||||
|
'permissions-policy': true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
cors: {
|
cors: {
|
||||||
|
@ -89,6 +95,24 @@ const TESTS = {
|
||||||
expectedHeaders: {
|
expectedHeaders: {
|
||||||
'content-security-policy': value => value.includes("'unsafe-inline'")
|
'content-security-policy': value => value.includes("'unsafe-inline'")
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
combinedSecurity: {
|
||||||
|
name: 'Combined Security Settings',
|
||||||
|
env: {
|
||||||
|
NODE_ENV: 'production',
|
||||||
|
HASTEBIN_ENABLE_CSP: 'false',
|
||||||
|
HASTEBIN_ENABLE_CROSS_ORIGIN_ISOLATION: 'true',
|
||||||
|
HASTEBIN_ENABLE_HSTS: 'true'
|
||||||
|
},
|
||||||
|
expectedHeaders: {
|
||||||
|
'content-security-policy': false,
|
||||||
|
'x-content-type-options': 'nosniff',
|
||||||
|
'x-frame-options': 'DENY',
|
||||||
|
'cross-origin-embedder-policy': 'require-corp',
|
||||||
|
'cross-origin-resource-policy': 'same-origin',
|
||||||
|
'cross-origin-opener-policy': 'same-origin',
|
||||||
|
'strict-transport-security': true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -229,7 +229,7 @@ run_tests() {
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -z "$test_filter" || "$test_filter" == *"noCsp"* ]]; then
|
if [[ -z "$test_filter" || "$test_filter" == *"noCsp"* ]]; then
|
||||||
if run_test "Disabled CSP" "NODE_ENV=production HASTEBIN_ENABLE_CSP=false" "content-security-policy:ABSENT"; then
|
if run_test "Disabled CSP" "NODE_ENV=production HASTEBIN_ENABLE_CSP=false" "content-security-policy:ABSENT,x-content-type-options:nosniff,x-frame-options:DENY"; then
|
||||||
passed=$((passed+1))
|
passed=$((passed+1))
|
||||||
else
|
else
|
||||||
failed=$((failed+1))
|
failed=$((failed+1))
|
||||||
|
@ -268,6 +268,14 @@ run_tests() {
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$test_filter" || "$test_filter" == *"combined"* ]]; then
|
||||||
|
if run_test "Combined Security Settings" "NODE_ENV=production HASTEBIN_ENABLE_CSP=false HASTEBIN_ENABLE_CROSS_ORIGIN_ISOLATION=true HASTEBIN_ENABLE_HSTS=true" "content-security-policy:ABSENT,x-content-type-options:nosniff,x-frame-options:DENY,cross-origin-embedder-policy:require-corp,strict-transport-security:max-age"; then
|
||||||
|
passed=$((passed+1))
|
||||||
|
else
|
||||||
|
failed=$((failed+1))
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
# Cleanup any remaining server process
|
# Cleanup any remaining server process
|
||||||
kill_server
|
kill_server
|
||||||
|
|
||||||
|
@ -285,7 +293,7 @@ run_tests() {
|
||||||
# Show help if requested
|
# Show help if requested
|
||||||
if [ $# -gt 0 ] && [ "$1" == "--help" ]; then
|
if [ $# -gt 0 ] && [ "$1" == "--help" ]; then
|
||||||
echo "Usage: $0 [--test=test1,test2,...]"
|
echo "Usage: $0 [--test=test1,test2,...]"
|
||||||
echo "Available tests: basic, csp, noCsp, cors, hsts, devMode, devBypass"
|
echo "Available tests: basic, csp, noCsp, cors, hsts, devMode, devBypass, combined"
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue