From 017d72b191eb3ab3dc58bd09a86a0b84db6abea3 Mon Sep 17 00:00:00 2001 From: Elie Habib Date: Wed, 1 Apr 2026 23:27:54 +0400 Subject: [PATCH] fix(csp): suppress localhost/loopback CSP violations from Smart TV browsers (#2603) Smart TV browsers (Tizen, webOS) inject scripts that call localhost services (e.g., localhost:9009/service/tvinfo). CSP correctly blocks these, but the violation listener was reporting them to Sentry. Matches any port on localhost and 127.0.0.1 over http/https. --- src/main.ts | 2 ++ tests/csp-filter.test.mjs | 14 ++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/src/main.ts b/src/main.ts index a8c3df0eb..4d963d0af 100644 --- a/src/main.ts +++ b/src/main.ts @@ -382,6 +382,8 @@ function shouldSuppressCspViolation( if (blockedURI === 'inline' && directive === 'script-src-elem') return true; // Null blocked URI from in-app browsers. if (blockedURI === 'null') return true; + // localhost/loopback — Smart TV browsers (Tizen, webOS) and dev tools inject local service calls. + if (/^https?:\/\/(localhost|127\.0\.0\.1)(:\d+)?\//.test(blockedURI)) return true; return false; } // Detect once whether BOTH the meta tag and HTTP header CSP allow https: in connect-src. diff --git a/tests/csp-filter.test.mjs b/tests/csp-filter.test.mjs index dd6e9a188..cc30933a8 100644 --- a/tests/csp-filter.test.mjs +++ b/tests/csp-filter.test.mjs @@ -140,6 +140,20 @@ describe('CSP violation filter (shouldSuppressCspViolation)', () => { }); }); + describe('localhost/loopback', () => { + it('suppresses http://localhost:9009 (Smart TV tuner service)', () => { + assert.ok(suppress('enforce', 'connect-src', 'http://localhost:9009/service/tvinfo', '', false)); + }); + + it('suppresses http://127.0.0.1:8080', () => { + assert.ok(suppress('enforce', 'connect-src', 'http://127.0.0.1:8080/api', '', false)); + }); + + it('suppresses https://localhost:3000', () => { + assert.ok(suppress('enforce', 'connect-src', 'https://localhost:3000/dev', '', false)); + }); + }); + describe('real violations pass through', () => { it('reports third-party script-src violation', () => { assert.ok(!suppress('enforce', 'script-src', 'https://evil.com/crypto-miner.js', '', true));