diff --git a/SECURITY.md b/SECURITY.md
index 628a7a6f..7046075e 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -21,7 +21,11 @@ We enforce a strict CSP through both Nginx and React-level meta tags.
- **Restrictions**: `'unsafe-inline'` is prohibited in production.
- **Allowed Sources**:
- Scripts/Styles: `'self'`
- - API Connections: `https://*.stellar.org`, `https://api.coingecko.com`
+ - API Connections/Wallets: `https://*.stellar.org`, `wss://*.stellar.org`, `https://*.sorobanrpc.com`, `https://api.coingecko.com`, `wss://*.walletconnect.com`, `https://*.walletconnect.com`, `https://*.walletconnect.org`, `https://albedo.link`, `https://*.albedo.link`
+ - Inline Scripts: Allowed via strict SHA-256 hash validation for the theme initialization script.
+
+### Adding New Wallet or API Endpoints
+To add a new endpoint or wallet integration, update the `Content-Security-Policy` header in `nginx.conf` and the corresponding meta tag in `index.html`. Add the domains to `connect-src` (for APIs/WebSocket) or `frame-src` (for iframes).
### 2. Automated Guardrails
- **Dependabot**: Monitors `npm` and `github-actions` ecosystems daily for updates.
diff --git a/index.html b/index.html
index 0fe4149a..5bf921ec 100644
--- a/index.html
+++ b/index.html
@@ -2,6 +2,7 @@
+
Stellar Developer Dashboard
diff --git a/nginx.conf b/nginx.conf
index b0094f36..beab4a61 100644
--- a/nginx.conf
+++ b/nginx.conf
@@ -9,7 +9,7 @@ server {
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
- add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self'; connect-src 'self' https://*.stellar.org https://api.coingecko.com; img-src 'self' data: https:; font-src 'self'; object-src 'none'; base-uri 'self'; upgrade-insecure-requests;" always;
+ add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'sha256-2cZtek/4Mta9v4mtLkqsK+tSR0rUJ9LWlEhKKvL5/Ts='; style-src 'self' https://fonts.googleapis.com; connect-src 'self' https://*.stellar.org wss://*.stellar.org https://*.sorobanrpc.com https://api.coingecko.com wss://*.walletconnect.com https://*.walletconnect.com https://*.walletconnect.org; img-src 'self' data: https:; font-src 'self' https://fonts.gstatic.com; frame-src 'self' https://albedo.link https://*.albedo.link; object-src 'none'; base-uri 'self'; upgrade-insecure-requests;" always;
# Health check endpoint
location /health {
diff --git a/tests/csp.test.js b/tests/csp.test.js
new file mode 100644
index 00000000..75899c20
--- /dev/null
+++ b/tests/csp.test.js
@@ -0,0 +1,55 @@
+import fs from 'fs';
+import path from 'path';
+import { fileURLToPath } from 'url';
+import assert from 'assert';
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+
+const nginxConfPath = path.resolve(__dirname, '../nginx.conf');
+const indexHtmlPath = path.resolve(__dirname, '../index.html');
+
+console.log('Running CSP tests...');
+
+try {
+ // Primary flow: nginx.conf should have a valid CSP header
+ const nginxContent = fs.readFileSync(nginxConfPath, 'utf8');
+ const cspRegex = /add_header Content-Security-Policy "(.*)" always;/;
+ const match = nginxContent.match(cspRegex);
+ assert(match, 'CSP header missing in nginx.conf');
+ const csp = match[1];
+
+ assert(csp.includes("default-src 'self'"), "CSP missing default-src 'self'");
+ assert(csp.includes("script-src 'self'"), "CSP missing script-src 'self'");
+ assert(csp.includes("connect-src"), "CSP missing connect-src");
+ console.log('✅ Primary flow: nginx.conf valid');
+
+ // Primary flow: index.html should have a valid CSP meta tag
+ const htmlContent = fs.readFileSync(indexHtmlPath, 'utf8');
+ const htmlCspRegex = / /;
+ const htmlMatch = htmlContent.match(htmlCspRegex);
+ assert(htmlMatch, 'CSP meta tag missing in index.html');
+ const htmlCsp = htmlMatch[1];
+
+ assert(htmlCsp.includes("default-src 'self'"), "HTML CSP missing default-src 'self'");
+ assert(htmlCsp.includes("script-src 'self'"), "HTML CSP missing script-src 'self'");
+ assert(htmlCsp.includes("connect-src"), "HTML CSP missing connect-src");
+ console.log('✅ Primary flow: index.html valid');
+
+ // Boundary case: should allow required Stellar endpoints but not wildcard everything
+ assert(csp.includes("https://*.stellar.org"), "Missing stellar.org");
+ assert(csp.includes("wss://*.walletconnect.com"), "Missing walletconnect.com");
+ assert(!csp.match(/connect-src [^;]*\s\*(?:\s|;)/), "connect-src is too permissive with wildcard");
+ console.log('✅ Boundary case: Required endpoints allowed securely');
+
+ // Failure case: should not allow arbitrary domains like http://evil.com
+ assert(!csp.includes("evil.com"), "CSP should not allow evil.com");
+ assert(!csp.includes("http://"), "CSP should not allow http://");
+ console.log('✅ Failure case: Malicious endpoints blocked');
+
+ console.log('All tests passed!');
+ process.exit(0);
+} catch (error) {
+ console.error('Test failed:', error.message);
+ process.exit(1);
+}