{"assessments":[],"deployments":[],"fuzz":[],"identity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"interpretation":"Records acceptance and evidence. Neither completion nor an AI assessment establishes correctness, safety, or independent review.","jobId":"03b0ebc5-1e9d-416e-924d-97cdbc78f485","kind":"skill:site-content-check","nodes":[{"acceptedSubmissionHash":"cd51563aa8536e3cf0d61f8d3d2c4e9faea5c006dba9bfc1561f0da0352987b9","dependsOn":[],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"9724d22ee4afab47bcc23d9bcd121784b0de277f78f82806d4dc4e8aa62609bf","skillId":"site-content-check","tools":[]},"key":"site_content_check","kind":"code","role":"review","skillHash":"9724d22ee4afab47bcc23d9bcd121784b0de277f78f82806d4dc4e8aa62609bf","skillId":"site-content-check","state":"accepted"}],"objective":"Wheelcast: free OBS stream overlays driven by Squeekchain's live API (run alerts, wheel telemetry, block banners, Twitch chat predictions, stats ticker). Deploy the repository as-is.","parentJobId":null,"planHash":"8d157c07d86b7890a7833866611b73f59559bca617e2f0080d565320d876949c","previousHash":"a07067c0002a7e0b5778425ac32b8e9385f940fcbd799d42bb5d8d561ea4a4c7","projectId":"03b0ebc5-1e9d-416e-924d-97cdbc78f485","publication":{"commit":null,"deliveredAt":null,"repoUrl":null},"receiptIdentity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"registry":"0xb6d0a187b050fa5bb0b87033a203f37becf4a775","research":[],"schema":"identitymd-work-v1","signals":[],"site":{"cid":"bafybeifbi5s7k6eo4zojvcasu5hyvc4etm5zr4edtanxmmy3frercygm5a","ensName":"wheelcast-broadcast-graphics-for.identitymd.eth","namingTransaction":"0xef8eb496bb8e7abf6b99cb181fd2e3af4b99fb6c249ba5bc4b3a8dd360d95bba"},"snapshotHash":"fe1e45ccae5f3061dac3be2c607f13437ee1fb7995b4c09f02c0b6d28d230e1a","state":"completed","submissions":[{"artifacts":[],"attempt":1,"bundleHash":null,"device":"dc176559ff153c37","findings":[{"citation":"resolved","description":"The message listener at overlay.html:525-533 does not check e.origin or e.source. Any page that embeds the hosted overlay.html in an iframe, or opens it, can post {wheelcast:'test', ev:'start'|'stop'|'block'|'vote'|'resolve'|'show'}. That fires run, nap and block alerts, adds fake chat votes, settles the poll at random, and writes those random results into the localStorage streak board (resolvePoll -> saveBoard). The page's claim that results come from the chain 'so nobody can fake a result' (index.html:188) does not hold for these hooks. In OBS the source is top-level, so only a framing page can reach it. Advisory: no harm to visitors, so this does not block hosting.","line":526,"path":"overlay.html","reproduction":"On any other origin, create <iframe id=f src=\"https://<host>/overlay.html?w=all\"> and after it loads run f.contentWindow.postMessage({wheelcast:'test',ev:'resolve'},'*'). Expected: the message is ignored because it is not from the Wheelcast page's own origin. Actual: the poll stamps 'He ran' or 'He napped' for round 512 and the streaks saved under localStorage 'wheelcast:board:local' change.","severity":"low","snippet":"  const d = e.data || {}; if (d.wheelcast !== \"test\") return;","title":"Overlay accepts test-event postMessages from any origin, so any page that frames it can fire fake alerts"},{"citation":"resolved","description":"renderTicker builds HTML from the api.squeekchain.com /settlements response and assigns it to tkInner.innerHTML (overlay.html:447). settledThroughRound is inserted raw. The same thing happens in the block banner: d.round = x.settledThroughRound (line 357) goes into bkMeta.innerHTML (line 391). Every other API field is passed through Number/fmt first, and chat names go through esc(). If that third-party API, or anything in its path, returns markup, the markup runs inside the streamer's OBS browser source. Advisory: hardening only, nothing malicious is present.","line":443,"path":"overlay.html","reproduction":"Serve a /settlements response whose recentSettlements[0].settledThroughRound is '<img src=x onerror=alert(1)>' (for example by overriding the fetch response in devtools), then open overlay.html?w=ticker. Expected: the round is shown as text. Actual: the img element is created and its onerror handler runs.","severity":"low","snippet":"    if (x) it.push(`Round ${x.settledThroughRound} settled with <b>${fmt(x.workAdded)}</b> work`);","title":"API string field settledThroughRound is put into innerHTML without escaping"},{"citation":"resolved","description":"index.html:12 and overlay.html:11 fetch CSS and fonts from fonts.googleapis.com and fonts.gstatic.com on every load, so the visitor's or streamer's IP address goes to Google. The 'What Wheelcast keeps' section (index.html:189) only says nothing is kept on a server. Disclosure is the only gap. These are stylesheets and fonts, not scripts. The only other network calls are fetches to api.squeekchain.com and an anonymous read-only Twitch IRC websocket, and both are disclosed.","line":12,"path":"index.html","reproduction":"Open index.html or overlay.html with the devtools Network tab open. Requests go to fonts.googleapis.com and fonts.gstatic.com, and the page's privacy text does not mention them.","severity":"low","snippet":"<link href=\"https://fonts.googleapis.com/css2?family=Barlow+Condensed:ital,wght@0,600;0,700;0,800;1,800;1,900&family=Barlow:ital,wght@0,400;0,500;0,600;1,400&display=swap\" rel=\"stylesheet\">","title":"Pages load Google Fonts from a third party, which the privacy note does not mention"},{"citation":"resolved","description":"overlay.html:288 only recognises the themes 'daylight' and 'copper' (default 'broadcast'), so theme=light or theme=mint from the README does nothing. The README also lists the gauge as 360 × 290, the poll as 380 × 330 and the ticker as 1920 × 56. index.html:204-215 says 400×230, 400×330 and 1920×60. Documentation only.","line":33,"path":"README.md","reproduction":"Open overlay.html?theme=light. Expected per the README: a light theme. Actual: the default dark broadcast theme. overlay.html?theme=daylight gives the light look.","severity":"info","snippet":"| `theme` | `night`, `light`, `mint` | `night` |","title":"README documents theme values and overlay sizes that the code does not use"}],"hash":"cd51563aa8536e3cf0d61f8d3d2c4e9faea5c006dba9bfc1561f0da0352987b9","nodeId":"0ccb45a3-bd36-4da7-a9dd-ee43afb8e66a","outcome":"completed","summary":"Nothing in Wheelcast needs to stop it from being hosted: I found no critical or high issues, only three low and one info finding. The only file I wrote is `.imd-findings.json`, and it holds valid JSON. I checked each quoted line against the files.\n\n**What I read:** all six files in the repository: `index.html`, `overlay.html` (including all of its inline script), `README.md`, `LICENSE`, and the two images `assets/hero.webp` and `assets/wheel.webp`. Both images are ordinary WebP files with nothing hidden after the image data. The repository has a single commit and no `stand-ins.txt`.\n\n**Checked against the must-not-host list:**\n- **Wallets:** nothing asks for a seed phrase, key or password. There is no wallet code and no request for an approval or signature.\n- **Impersonation:** none. The page calls itself \"a free community tool built on Squeekchain's public API\" and credits its author, @serkankels.\n- **Hidden or downloaded code:** none of it is obfuscated and nothing downloads and runs code from elsewhere. The one iframe is the visible preview monitor, which shows the site's own `overlay.html`. There are no redirects.\n- **Network traffic:** the only calls go to `api.squeekchain.com` and to Twitch chat, which is read through Twitch's anonymous read-only login. Both are disclosed on the page.\n- **Financial claims:** there are no promises of returns, giveaways or false urgency.\n\n**Findings:**\n1. **Low – `overlay.html:526`:** the overlay accepts test messages from any website. A site that embeds it can fire fake run, nap and block alerts. It can also settle the prediction round at random, which changes the saved streak leaderboard. That contradicts the page's claim that \"nobody can fake a result\" (`index.html:188`).\n2. **Low – `overlay.html:443` and `:391`:** one field from the Squeekchain API (the round number) is inserted into the page as markup without escaping. Every other API field is converted to a number first. If that API ever returned markup, it would run inside the streamer's OBS source.\n3. **Low – `index.html:12` and `overlay.html:11`:** both pages load fonts from Google, so visitors' IP addresses go to Google. The privacy note on the page doesn't mention this.\n4. **Info – `README.md:33`:** the README lists themes the code doesn't support. `light` and `mint` do nothing; the real values are `broadcast`, `copper` and `daylight`. Three overlay sizes in the README also differ from what `index.html` shows.\n\nEach finding has a step-by-step reproduction in the JSON file. None of them carries a Foundry test, because there's no Solidity in this repository.","treeHash":null,"usage":{"cachedInputTokens":213238,"cost":{"source":"runtime","usdMicros":428029},"inputTokens":14,"model":"claude-opus-5-5","outputTokens":4637,"runtime":"claude","turns":8,"wallClockMs":55941}}],"verification":[]}