-
-
Notifications
You must be signed in to change notification settings - Fork 164
/
sandbox.html
106 lines (104 loc) · 5.11 KB
/
sandbox.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sandbox</title>
<meta name="twitter-site-verification" content="loading" />
</head>
<body>
<div id="anims" style="display:none"></div>
<script>
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
let initError = false, solver;
window.addEventListener('message', async function(event) {
if (event.origin !== 'https://twitter.com' && event.origin !== 'https://x.com') {
return;
}
let data = event.data;
if (data.action === 'init') {
try {
let url = `https://abs.twimg.com/responsive-web/client-web/ondemand.s.${data.challengeCode}a.js`
let challengeData;
try {
challengeData = await fetch(url).then(res => res.text());
} catch(e) {
await sleep(500);
try {
challengeData = await fetch(url).then(res => res.text());
} catch(e) {
await sleep(1000);
try {
challengeData = await fetch(url).then(res => res.text());
} catch(e) {
throw new Error('Failed to fetch challenge data: ' + e);
}
}
}
let animsDiv = document.getElementById('anims');
for(let anim of data.anims) {
animsDiv.innerHTML += `\n${anim}`;
}
let verif = document.querySelector('meta[name="twitter-site-verification"]');
verif.content = data.verificationCode;
let headerRegex = /(\d+):(.+)=>.+default:\(\)=>(\w).+,\w\(\d+\)\;/;
let headerMatch = challengeData.match(headerRegex);
if(!headerMatch) {
console.error('Uh oh, header not found!! Report to https://github.com/dimdenGD/OldTwitter/issues');
event.source.postMessage({action: 'initError', error: `Header not found at ${data.challengeCode} (${String(challengeData).slice(0, 500)}...)`}, event.origin);
initError = true;
return;
}
// TO EXTENSION REVIEWERS (mostly Mozilla):
// This script is part of Twitter's security challenge, before mindlessly rejecting extension actually review what code does please! It's in sandbox for a reason.
// It only ever executes code from trusted Twitter domain, abs.twimg.com (specifically their script that generates security headers)
// It's impossible to have it contained in extension itself, since it's generated dynamically
// you can see where script is loaded in scripts/twchallenge.js
// it also can't use any extension APIs, since it's contained in object url iframe
eval(challengeData.replace(headerRegex, '$1:$2=>{window._CHALLENGE=()=>$3;'));
let id = headerMatch[1];
webpackChunk_twitter_responsive_web[0][1][id]();
solver = window._CHALLENGE()();
event.source.postMessage({action: 'ready'}, event.origin);
} catch(e) {
console.error(e);
event.source.postMessage({action: 'initError', error: String(e) }, event.origin);
initError = true;
}
} else if (data.action === 'solve') {
if(initError) {
event.source.postMessage({action: 'error', error: 'Initialization error', id: data.id }, event.origin);
return;
}
if(!solver) {
await sleep(50);
if(!solver) {
await sleep(100);
}
if(!solver) {
await sleep(500);
}
if(!solver) {
await sleep(1000);
}
if(!solver) {
await sleep(2500);
}
if(initError || !solver) {
event.source.postMessage({action: 'error', error: 'Solver timed out', id: data.id }, event.origin);
return;
}
}
try {
let result = await solver(data.path, data.method);
event.source.postMessage({action: 'solved', result, id: data.id}, event.origin);
} catch(e) {
event.source.postMessage({action: 'error', error: `${e.message}\n${e.stack}`, id: data.id}, event.origin);
}
}
});
</script>
</body>
</html>