Safeguard
Application Security•

ASVS 5.0 V3.5.7: Keep Authorized Data Out of Script Responses

ASVS V3.5.7 (Level 3) says JavaScript files must not carry data that needs authorization, or any site can include them and read it. Patterns to avoid, fixes and tests.

Safeguard Security Team
3 min read

ASVS 5.0 requirement V3.5.7 says data that requires authorization must not be included in script resource responses, such as JavaScript files, to prevent Cross-Site Script Inclusion (XSSI). It is a Level 3 requirement.

Why it matters

Any page on any site can include your script with <script src="https://app.example.com/config.js">. The browser sends the visitor's cookies with that request and runs the response. Same-origin policy stops the attacker's page from reading your JSON through fetch, but it does not stop the script from executing and defining global variables, overriding built-in functions or leaking values the attacker's page can then read.

So a response like this is a data leak:

var CURRENT_USER = {"id": 42, "email": "a@b.test", "apiKey": "k_live_..."};

Dynamic scripts that embed per user data are the usual cause: bootstrap config files, window.__STATE__ bundles, localization files that include account names, and JSONP style endpoints, see V3.5.6.

How to implement it

Serve scripts as static, identical-for-everyone files. Deliver per user data from an authenticated JSON endpoint that is not script includable.

// static: /static/app.js has no user data

// data: JSON endpoint, strict type, requires session and a custom header
app.get("/api/me", requireAuth, (req, res) => {
  if (req.get("X-Requested-With") !== "app") return res.status(403).end();
  res.type("application/json").json({ id: req.user.id, email: req.user.email });
});

Add X-Content-Type-Options: nosniff so a JSON response cannot be treated as script, see V3.4.4. For authenticated assets, Cross-Origin-Resource-Policy: same-origin blocks cross-site loading outright.

If you must inline initial state into HTML, do it in the page itself (a document, not a script resource), encode it safely, and send it only to the signed in user.

How to test it

Fetch every script URL with a valid session and without one, and diff:

for u in /static/app.js /config.js /i18n/en.js; do
  curl -s https://app.example.com$u -b cookies.txt | sha256sum
  curl -s https://app.example.com$u | sha256sum
done

Hashes must match, meaning the response does not depend on who asks. Grep script responses for emails, names, tokens and ids from a test account. Then include a script from another origin on a test page and check that no private global appears.

Common mistakes

Bootstrap scripts with user data. Move them to an authenticated JSON call.

API keys in config.js. Treat anything in a script as public.

Array or JSON responses served as script. Use correct JSON content type and nosniff.

Quick check

Is a script that only the logged in user can load safe?

No. The attacker's page makes the logged in visitor's browser load it, using their cookies.

Sources

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.