Cross-Site Script Inclusion (XSSI) is a sneaky data-leak where an attacker <script>
-loads your API and reads secrets if your endpoint returns executable JavaScript or unsafe JSON. Below is a concise, Symfony-focused guide with copy-paste fixes—perfect for dev readers and teams.
👉 Try our free website security scanner to spot XSSI and other issues.
Also see our blog: Pentest Testing Corp.
How XSSI happens (Symfony example)
Vulnerable: returning executable JS (not JSON). If an attacker includes it, your data becomes a global variable on their page.
// src/Controller/ProfileController.php #[Route('/api/profile.js', name: 'api_profile_js', methods: ['GET'])] public function profileAsJs(): Response { $data = ['email' => 'alice@example.com', 'role' => 'admin']; // ❌ Executable JavaScript — XSSI-prone $body = 'window.__profile = ' . json_encode($data) . ';'; return new Response($body, 200, ['Content-Type' => 'application/javascript']); }
Attacker page:
<script src="https://victim.example.com/api/profile.js"></script> <script> // now readable cross-site — data leaked console.log(window.__profile); </script>
📸 Screenshot of the Website Vulnerability Scanner tool homepage:
Screenshot of the free tools webpage where you can access security assessment tools.
Safer pattern #1: Strict JSON + anti-XSSI prefix
Return pure JSON (not JS) and add a harmless prefix that breaks execution if included via <script>
.
// src/Controller/ProfileController.php use Symfony\Component\HttpFoundation\Response; #[Route('/api/profile', name: 'api_profile', methods: ['GET'])] public function profile(): Response { $data = ['email' => 'alice@example.com', 'role' => 'admin']; $prefix = ")]}',\n"; // breaks script execution; clients strip it before JSON.parse $json = $prefix . json_encode($data, JSON_UNESCAPED_SLASHES); return new Response($json, 200, [ 'Content-Type' => 'application/json; charset=utf-8', 'X-Content-Type-Options' => 'nosniff', 'Cross-Origin-Resource-Policy' => 'same-site', ]); }
Client parsing tip:
// strip prefix before JSON.parse fetch('/api/profile').then(r => r.text()).then(t => { const clean = t.replace(/^\)\]\}',\n?/, ''); return JSON.parse(clean); });
Safer pattern #2: Block cross-origin inclusion at the edge
Add security headers globally via an event subscriber.
// src/EventSubscriber/SecurityHeadersSubscriber.php use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpKernel\Event\ResponseEvent; final class SecurityHeadersSubscriber implements EventSubscriberInterface { public static function getSubscribedEvents(): array { return ['kernel.response' => 'onKernelResponse']; } public function onKernelResponse(ResponseEvent $event): void { $r = $event->getResponse(); $r->headers->set('X-Content-Type-Options', 'nosniff'); $r->headers->set('Cross-Origin-Resource-Policy', 'same-site'); // Optional: CORP/CORB hardening $r->headers->set('Content-Type', $r->headers->get('Content-Type') ?: 'application/json; charset=utf-8'); } }
Safer pattern #3: Avoid GET for sensitive data + CSRF
Return sensitive data via POST and require a CSRF token.
# config/routes.yaml api_secure_profile: path: /api/secure/profile controller: App\Controller\SecureController::profile methods: [POST]
// src/Controller/SecureController.php use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; public function __construct(private CsrfTokenManagerInterface $csrf) {} public function profile(Request $req): JsonResponse { $token = $req->request->get('_token'); if (!$this->csrf->isTokenValid(new CsrfToken('api_profile', $token))) { return $this->json(['error' => 'invalid_csrf'], 403); } return $this->json(['ok' => true]); }
📸 Sample assessment report from our tool to check Website Vulnerability:
Sample vulnerability assessment report generated with our free tool, providing insights into possible vulnerabilities.
Bonus hardening checklist
- Disable JSONP and never return executable JS from APIs.
- Cookies: use
SameSite=Lax
orStrict
,HttpOnly
,Secure
. - CORS: only allow trusted origins; avoid
Access-Control-Allow-Origin: *
with credentials. - CSP on your pages:
script-src 'self'
(reduces risky third-party scripts). - Audit endpoints with our free tool for a website security test.
Services from Pentest Testing Corp.
- Managed IT Services — proactive ops, patching, threat monitoring.
- AI Application Cybersecurity — secure LLMs, prompt injection defenses, model gates.
- Offer Cybersecurity to Your Client — white-label security for agencies/MSPs.
Newsletter: Subscribe on LinkedIn
Read more on our blog → https://www.pentesttesting.com/blog/.
Top comments (0)