Skip to content

Commit e4b92af

Browse files
crivetimihaiShamsul Arefin
authored andcommitted
344 cors security headers (IBM#761)
* Update CORS Signed-off-by: Mihai Criveti <[email protected]> * Update CORS Signed-off-by: Mihai Criveti <[email protected]> * Update CORS ADRs Signed-off-by: Mihai Criveti <[email protected]> * Update CORS Signed-off-by: Mihai Criveti <[email protected]> * Update CORS Signed-off-by: Mihai Criveti <[email protected]> * Fix compose Signed-off-by: Mihai Criveti <[email protected]> * Update helm chart Signed-off-by: Mihai Criveti <[email protected]> * Update CORS docs Signed-off-by: Mihai Criveti <[email protected]> * Update test Signed-off-by: Mihai Criveti <[email protected]> --------- Signed-off-by: Mihai Criveti <[email protected]> Signed-off-by: Shamsul Arefin <[email protected]>
1 parent 595518f commit e4b92af

32 files changed

+2970
-255
lines changed

.env.example

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,13 +82,15 @@ PROTOCOL_VERSION=2025-03-26
8282
#####################################
8383

8484
# Admin UI basic-auth credentials
85+
# PRODUCTION: Change these to strong, unique values!
8586
BASIC_AUTH_USER=admin
8687
BASIC_AUTH_PASSWORD=changeme
8788

8889
# Require any form of authentication (true or false)
8990
AUTH_REQUIRED=true
9091

9192
# Secret used to sign JWTs (use long random value in prod)
93+
# PRODUCTION: Use a strong, random secret (minimum 32 characters)
9294
JWT_SECRET_KEY=my-test-key
9395

9496
# Algorithm used to sign JWTs (e.g., HS256)
@@ -119,9 +121,11 @@ AUTH_ENCRYPTION_SECRET=my-test-salt
119121
#####################################
120122

121123
# Enable the visual Admin UI (true/false)
124+
# PRODUCTION: Set to false for security
122125
MCPGATEWAY_UI_ENABLED=true
123126

124127
# Enable the Admin API endpoints (true/false)
128+
# PRODUCTION: Set to false for security
125129
MCPGATEWAY_ADMIN_API_ENABLED=true
126130

127131
# Enable bulk import endpoint for tools (true/false)
@@ -157,6 +161,57 @@ ALLOWED_ORIGINS='["http://localhost", "http://localhost:4444"]'
157161
# Enable CORS handling in the gateway
158162
CORS_ENABLED=true
159163

164+
# CORS allow credentials (true/false)
165+
CORS_ALLOW_CREDENTIALS=true
166+
167+
# Environment setting (development/production) - affects security defaults
168+
# development: Auto-configures CORS for localhost:3000, localhost:8080, etc.
169+
# production: Uses APP_DOMAIN for HTTPS origins, enforces secure cookies
170+
ENVIRONMENT=development
171+
172+
# Domain configuration for production CORS origins
173+
# In production, automatically creates origins: https://APP_DOMAIN, https://app.APP_DOMAIN, https://admin.APP_DOMAIN
174+
# For production: set to your actual domain (e.g., mycompany.com)
175+
APP_DOMAIN=localhost
176+
177+
# Security settings for cookies
178+
# production: Automatically enables secure cookies regardless of this setting
179+
# development: Set to false for HTTP development, true for HTTPS
180+
SECURE_COOKIES=true
181+
182+
# Cookie SameSite attribute for CSRF protection
183+
# strict: Maximum security, may break some OAuth flows
184+
# lax: Good balance of security and compatibility (recommended)
185+
# none: Requires Secure=true, allows cross-site usage
186+
COOKIE_SAMESITE=lax
187+
188+
#####################################
189+
# Security Headers Configuration
190+
#####################################
191+
192+
# Enable security headers middleware (true/false)
193+
SECURITY_HEADERS_ENABLED=true
194+
195+
# X-Frame-Options setting (DENY, SAMEORIGIN, or ALLOW-FROM uri)
196+
# DENY: Prevents all iframe embedding (recommended for security)
197+
# SAMEORIGIN: Allows embedding from same domain only
198+
# To disable: Set to empty string X_FRAME_OPTIONS=""
199+
X_FRAME_OPTIONS=DENY
200+
201+
# Other security headers (true/false)
202+
X_CONTENT_TYPE_OPTIONS_ENABLED=true
203+
X_XSS_PROTECTION_ENABLED=true
204+
X_DOWNLOAD_OPTIONS_ENABLED=true
205+
206+
# HSTS (HTTP Strict Transport Security) settings
207+
HSTS_ENABLED=true
208+
# HSTS max age in seconds (31536000 = 1 year)
209+
HSTS_MAX_AGE=31536000
210+
HSTS_INCLUDE_SUBDOMAINS=true
211+
212+
# Remove server identification headers (true/false)
213+
REMOVE_SERVER_HEADERS=true
214+
160215
# Enable HTTP Basic Auth for docs endpoints (in addition to Bearer token auth)
161216
# Uses the same credentials as BASIC_AUTH_USER and BASIC_AUTH_PASSWORD
162217
DOCS_ALLOW_BASIC_AUTH=false

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1389,7 +1389,7 @@ install-web-linters:
13891389
nodejsscan:
13901390
@echo "🔒 Running nodejsscan for JavaScript security vulnerabilities..."
13911391
$(call ensure_pip_package,nodejsscan)
1392-
@$(VENV_DIR)/bin/nodejsscan --directory ./mcpgateway/static || true
1392+
@$(VENV_DIR)/bin/nodejsscan --directory ./mcpgateway/static --directory ./mcpgateway/templates || true
13931393

13941394
lint-web: install-web-linters nodejsscan
13951395
@echo "🔍 Linting HTML files..."

README.md

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1053,10 +1053,28 @@ You can get started by copying the provided [.env.example](.env.example) to `.en
10531053
| Setting | Description | Default | Options |
10541054
| ------------------------- | ------------------------------ | ---------------------------------------------- | ---------- |
10551055
| `SKIP_SSL_VERIFY` | Skip upstream TLS verification | `false` | bool |
1056-
| `ALLOWED_ORIGINS` | CORS allow-list | `["http://localhost","http://localhost:4444"]` | JSON array |
1056+
| `ENVIRONMENT` | Deployment environment (affects security defaults) | `development` | `development`/`production` |
1057+
| `APP_DOMAIN` | Domain for production CORS origins | `localhost` | string |
1058+
| `ALLOWED_ORIGINS` | CORS allow-list | Auto-configured by environment | JSON array |
10571059
| `CORS_ENABLED` | Enable CORS | `true` | bool |
1060+
| `CORS_ALLOW_CREDENTIALS` | Allow credentials in CORS | `true` | bool |
1061+
| `SECURE_COOKIES` | Force secure cookie flags | `true` | bool |
1062+
| `COOKIE_SAMESITE` | Cookie SameSite attribute | `lax` | `strict`/`lax`/`none` |
1063+
| `SECURITY_HEADERS_ENABLED` | Enable security headers middleware | `true` | bool |
1064+
| `X_FRAME_OPTIONS` | X-Frame-Options header value | `DENY` | `DENY`/`SAMEORIGIN` |
1065+
| `HSTS_ENABLED` | Enable HSTS header | `true` | bool |
1066+
| `HSTS_MAX_AGE` | HSTS max age in seconds | `31536000` | int |
1067+
| `REMOVE_SERVER_HEADERS` | Remove server identification | `true` | bool |
10581068
| `DOCS_ALLOW_BASIC_AUTH` | Allow Basic Auth for docs (in addition to JWT) | `false` | bool |
10591069

1070+
> **CORS Configuration**: When `ENVIRONMENT=development`, CORS origins are automatically configured for common development ports (3000, 8080, gateway port). In production, origins are constructed from `APP_DOMAIN` (e.g., `https://yourdomain.com`, `https://app.yourdomain.com`). You can override this by explicitly setting `ALLOWED_ORIGINS`.
1071+
>
1072+
> **Security Headers**: The gateway automatically adds configurable security headers to all responses including CSP, X-Frame-Options, X-Content-Type-Options, X-Download-Options, and HSTS (on HTTPS). All headers can be individually enabled/disabled. Sensitive server headers are removed.
1073+
>
1074+
> **iframe Embedding**: By default, `X-Frame-Options: DENY` prevents iframe embedding for security. To allow embedding, set `X_FRAME_OPTIONS=SAMEORIGIN` (same domain) or disable with `X_FRAME_OPTIONS=""`. Also update CSP `frame-ancestors` directive if needed.
1075+
>
1076+
> **Cookie Security**: Authentication cookies are automatically configured with HttpOnly, Secure (in production), and SameSite attributes for CSRF protection.
1077+
>
10601078
> Note: do not quote the ALLOWED_ORIGINS values, this needs to be valid JSON, such as:
10611079
> ALLOWED_ORIGINS=["http://localhost", "http://localhost:4444"]
10621080
>

SECURITY.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ Applications consuming data from MCP Gateway should:
236236

237237
- **Never trust data implicitly** - validate all inputs
238238
- **Implement context-appropriate sanitization** for their UI framework
239-
- **Use Content Security Policy (CSP)** headers
239+
- **Use Content Security Policy (CSP)** headers (automatically provided by MCP Gateway)
240240
- **Escape data appropriately** for the output context (HTML, JavaScript, SQL, etc.)
241241
- **Implement their own authentication** and authorization
242242
- **Monitor for security anomalies** in rendered content
@@ -261,7 +261,9 @@ When deploying MCP Gateway in production:
261261
- [ ] Configure resource limits (CPU, memory) to prevent DoS attacks
262262
- [ ] Implement proper secrets management (never hardcode credentials)
263263
- [ ] Set up structured logging without exposing sensitive data
264-
- [ ] Configure CORS policies appropriately for your clients
264+
- [ ] Configure CORS policies appropriately for your clients (auto-configured by ENVIRONMENT setting)
265+
- [ ] Verify security headers are working (automatically added by SecurityHeadersMiddleware)
266+
- [ ] Configure iframe embedding policy (X-Frame-Options: DENY by default, set to SAMEORIGIN if embedding needed)
265267
- [ ] Disable debug mode and verbose error messages in production
266268
- [ ] Implement backup and disaster recovery procedures
267269
- [ ] Document incident response procedures

0 commit comments

Comments
 (0)