{"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":"a4a69806-9b36-4b6a-93db-23dd88f36a51","kind":"skill:site-content-check","nodes":[{"acceptedSubmissionHash":"d56d48e1fcb60a08e49dcb14615c2354346052e38d6f7f40c71c96a11c2c8143","dependsOn":[],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"8189a3059fc9bb774ad7dcee66b87f32e25d781025f0e9f82a4c75182fe0ef19","skillId":"site-content-check","tools":[]},"key":"site_content_check","kind":"code","role":"review","skillHash":"8189a3059fc9bb774ad7dcee66b87f32e25d781025f0e9f82a4c75182fe0ef19","skillId":"site-content-check","state":"accepted"}],"objective":"Build and host https://github.com/beibei030/burrowkeep at main commit 7d85983 as it is. Do not redesign the game or change the upgrade costs, ore rates, invite rules, or leaderboard API. Host the static site.","parentJobId":null,"planHash":"5b3d01d650f610b44f44068ec0a76adad1cec08712649510fc208d43421be14b","previousHash":"858465a66c6001b8de1bb5165a71d8e3c21a0413d9769d6b98913325fd280be8","projectId":"a4a69806-9b36-4b6a-93db-23dd88f36a51","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":"bafybeibfa6iim2qfjiwbozohdkvsutwaclyjzr74b7uogzj2uoydndiyqa","ensName":"burrowkeep-a4a6.identitymd.eth","namingTransaction":"0x8126fa956ddfe815ca6371c8a981d613811215953e9cdc0e59543b4598470030"},"snapshotHash":"b8ba55021d6cadefcd75378aec54471d03e44f3313f1bc088ff9ece36c239ef3","state":"completed","submissions":[{"artifacts":[],"attempt":1,"bundleHash":null,"device":"e12f98dda6acc55f","findings":[{"citation":"resolved","description":"When the page is served from *.imd.site or identitymd.eth.limo, mill.js sends every /api/hello, /api/pulse, /api/bonus and /api/board request to https://aiqiang888.com/burrowkeep-api. That host is a Vercel-served Next.js site titled 'AIQIANG' (a Chinese X/Twitter-operations and Web3 airdrop consultancy page), and every path under /burrowkeep-api/ returns HTTP 404 text/html. The actual game API from server.mjs is reachable at the sslip.io host named in Caddyfile.burrowkeep:8, which answers GET /api/board with {\"wealth\":[],\"decor\":[]}. Result on the hosted site: hello() never succeeds so state.welcomed stays false, the invite panel never shows bound/unbound, no friend bonus is ever paid, and both leaderboards permanently show 'Nobody is ranked yet'. The core mining loop still works because it is local. This is a broken feature and a dependency on a third party's domain, not hostile content, so it does not block hosting.","line":22,"path":"mill.js","reproduction":"curl -sS -o /dev/null -w '%{http_code} %{content_type}\\n' https://aiqiang888.com/burrowkeep-api/api/board -> expected 200 application/json with {\"wealth\":[...],\"decor\":[...]}; actual 404 text/html (server: Vercel, x-matched-path: /404). POST https://aiqiang888.com/burrowkeep-api/api/hello with Origin https://burrowkeep.imd.site also returns 404. Compare: curl https://burrowkeep-api.46.250.250.111.sslip.io/api/board -> 200 {\"wealth\":[],\"decor\":[]}. In the browser on burrowkeep.imd.site, open DevTools Network: the two POSTs and the GET fired every 5 s by setInterval at mill.js:1028 all return 404.","severity":"medium","snippet":"  ? \"https://aiqiang888.com/burrowkeep-api\"","title":"Hosted-origin API base points at a Vercel marketing site that returns 404; invite binding and leaderboards are dead on the hosted site"},{"citation":"resolved","description":"The footer anchor is relabelled at runtime by mill.js:614 to 'Squeekchain 邀请' / 'Squeekchain invite'. Its href is a referral path on a real third-party project's site (Squeekchain, a Sepolia-testnet hamster-wheel chain with a listed token) carrying the code 'axshwghm'. Nothing on the page says the code belongs to the repository author or that following it credits them. Combined with the hard-coded header kicker 'Squeekchain · Sepolia' (index.html:14), a visitor can reasonably read the hosted page as a Squeekchain-affiliated property funnelling them into Squeekchain's genesis/invite flow. The page does name itself Burrowkeep, does not use Squeekchain's logo, and states in the footer that it 'does not make Squeektoshi run', so this is an undisclosed affiliate link rather than impersonation; medium, advisory.","line":60,"path":"index.html","reproduction":"Open index.html, scroll to the footer, hover the second link: href is https://squeekchain.com/genesis/i/axshwghm. Search the repository for 'axshwghm': it appears only here, with no disclosure text in COPY (mill.js:27-154) explaining whose referral it is. squeekchain.com is a live third-party site (returns a Cloudflare challenge to curl).","severity":"medium","snippet":"      <a href=\"https://squeekchain.com/genesis/i/axshwghm\" id=\"chain-link\">Squeekchain</a>","title":"Footer link labelled 'Squeekchain invite' is the author's personal Squeekchain referral code, undisclosed"},{"citation":"resolved","description":"The only script index.html loads is mill.js, which imports economy.js and spawns worker.js/hash.js. None of them fetch api.squeekchain.com, read a chain, or reference Sepolia; ore is minted purely from local SHA-256 counts (mill.js:283, economy.js:26-30). The Squeekchain-fetching code lives in game.js/rules.js, which index.html does not load. The kicker therefore advertises a chain connection the hosted game does not have. The meta description at index.html:7 ('His real running becomes ore') repeats the same unfulfilled claim.","line":14,"path":"index.html","reproduction":"grep -n 'squeekchain' mill.js economy.js worker.js hash.js -> no fetch URLs, only the two footer link labels. Load the page with DevTools Network open and press Start mining: the only network calls are to the API base in mill.js:21-23; nothing goes to squeekchain.com or any RPC.","severity":"low","snippet":"      <p class=\"kicker\">Squeekchain · Sepolia</p>","title":"Header brands the page 'Squeekchain · Sepolia' although no script on the page contacts Squeekchain or Sepolia"},{"citation":"resolved","description":"Hosting the repository 'as it is' pins server.mjs, start-https.mjs, Caddyfile.burrowkeep and brief.json alongside the pages. Caddyfile.burrowkeep publishes the operator's ACME email (line 2) and the VPS IPv4 address via the sslip.io hostname; start-https.mjs:4-5 publishes C:\\caddy\\ paths; server.mjs publishes the full API source including the rate-limit constants an abuser would want (lines 117, 164, 168). None of this is hostile content, but none of it needs to be served from the ENS name either.","line":8,"path":"Caddyfile.burrowkeep","reproduction":"After pinning, GET <site>/Caddyfile.burrowkeep, <site>/server.mjs, <site>/start-https.mjs, <site>/brief.json: each is returned verbatim. In the tree: Caddyfile.burrowkeep lines 2 and 8, start-https.mjs lines 4-5.","severity":"low","snippet":"burrowkeep-api.46.250.250.111.sslip.io {","title":"Deployment files with operator email, VPS IP and Windows paths are part of the static export"},{"citation":"resolved","description":"If the hostname is not *.imd.site or *identitymd.eth.limo, API is the empty string and every call becomes a relative request such as POST /api/hello against the current origin. On ipfs.io, dweb.link, *.eth.link, a local IPFS gateway or a CID subdomain, those requests hit the gateway and fail (or return the site's own index.html for GET /api/board, making response.json() throw inside syncBoard with no catch after the ok check at line 559-560). Additionally server.mjs:52-57 only sets CORS headers for the same two origins plus localhost:8765, so even a correct API base would be blocked elsewhere. Invite and leaderboards therefore work on at most two hostnames of an otherwise gateway-agnostic IPFS site.","line":21,"path":"mill.js","reproduction":"Open the pinned CID through https://ipfs.io/ipfs/<cid>/ and watch Network: POST https://ipfs.io/api/hello (404), GET https://ipfs.io/api/board (404 or HTML). Expected: requests go to the game API. Actual: requests go to the gateway; invite shows the default hint forever and boards show 'Nobody is ranked yet'.","severity":"low","snippet":"const API = /(?:^|\\.)imd\\.site$|identitymd\\.eth\\.limo$/.test(location.hostname)","title":"API is only wired for two exact origins; on any other IPFS gateway or ENS resolver the page POSTs to the gateway itself"},{"citation":"resolved","description":"POST /api/board (server.mjs:145-176) takes minerId, gold and decor from the body with no proof of work or secret. A brand-new id is allowed gold 50 and decor 80 on its first post, and a known id may grow gold by 0.05/s and decor by 2/s indefinitely. POST /api/pulse (lines 101-125) likewise credits up to 200 ore/s per id to the referrer's bonus with no check that any hashing happened, so one person can register throwaway ids via /api/hello with refId set to their own id and farm the 5% bonus. Game-integrity issue on the operator's server, not hosted content; advisory only. Not reproduced against the live server to avoid writing to the operator's store.","line":164,"path":"server.mjs","reproduction":"Against a local `node server.mjs`: curl -X POST localhost:8765/api/hello -H 'content-type: application/json' -d '{\"minerId\":\"forgedabc123\",\"refId\":\"\"}' then curl -X POST localhost:8765/api/board -H 'content-type: application/json' -d '{\"minerId\":\"forgedabc123\",\"gold\":50,\"decor\":80}' then curl localhost:8765/api/board -> expected: rejected without evidence of play; actual: {\"wealth\":[{\"id\":\"forgedabc123\",\"score\":50}],\"decor\":[{\"id\":\"forgedabc123\",\"score\":80}]}. Repeat with new ids to fill all 8 slots.","severity":"low","snippet":"          const goldCap = prevGold + (existing.scoredAt ? Math.ceil(elapsed * 0.05) + 1 : 50);","title":"Leaderboard and referral endpoints accept unauthenticated values for any minerId, so boards and friend bonuses can be forged"},{"citation":"resolved","description":"Checked specifically against the 'malware or cryptominer' criterion. worker.js hashes a 24-byte buffer of random bytes plus a nonce (lines 10, 19-26), counts hashes and 'shares' (two leading zero bytes, hash.js:64-66), and reports counts to the page. There is no fetch, WebSocket, pool URL, job template or share submission in worker.js, hash.js, economy.js or mill.js; mill.js only forwards an ore count (not hashes) to its own leaderboard API. Hashing starts only when the visitor presses the Start button (mill.js:1007-1015), stops on the same button, is disclosed in the lede and footer, and uses min(gear level, navigator.hardwareConcurrency, 8) workers only after the visitor also presses the 'Full' mode toggle. hash.js is a plain, readable SHA-256 implementation; verified sha256('abc') = ba7816bf...f20015ad. No wallet, provider, approval, permit, seed phrase or signature request exists anywhere in the tree.","line":30,"path":"worker.js","reproduction":"node --input-type=module -e 'import {sha256} from \"./hash.js\"; console.log(Buffer.from(sha256(new TextEncoder().encode(\"abc\"))).toString(\"hex\"))' -> ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad. grep -n 'fetch\\|WebSocket\\|importScripts\\|stratum' worker.js hash.js -> no matches. Open the page without pressing Start: CPU stays idle and the status line reads 'Mining is off. No hashing is running.'","severity":"info","snippet":"  self.postMessage({ hashes, shares });","title":"Opt-in SHA-256 hashing is local only: nothing is submitted anywhere, so this is a game mechanic, not a cryptominer"},{"citation":"resolved","description":"index.html loads only mill.js (line 63). game.js (1228 lines) and rules.js implement the earlier 'survival night' game that polled api.squeekchain.com and expects elements #pages, #actions, #reveal, #tab-live, #clock, #volume and the image burrow-room.jpg, none of which exist in this tree. If anyone loaded game.js against index.html it would throw at render() on a null element. Both files will be pinned as dead weight and would 404 on the image. Harmless, but they are the only files in the export that contact Squeekchain, and they are not what visitors run.","line":845,"path":"game.js","reproduction":"grep -n 'script' index.html -> only mill.js. ls burrow-room.jpg -> No such file. grep -n 'id=\"pages\"\\|id=\"actions\"\\|id=\"tab-live\"' index.html -> no matches, while game.js:494, 553, 672 query those ids.","severity":"info","snippet":"roomImage.src = \"burrow-room.jpg\";","title":"game.js and rules.js are an earlier, unloaded game; game.js references an image and element ids that do not exist in the export"}],"hash":"d56d48e1fcb60a08e49dcb14615c2354346052e38d6f7f40c71c96a11c2c8143","nodeId":"84b81585-1cc8-4ff8-b2c5-d0bc9689082f","outcome":"completed","summary":"The review is complete. Nothing in the Burrowkeep export rises to critical or high, so the site can be hosted. Findings are written to `.imd-findings.json` in the repository root, and no other file was changed.\n\n**What I read**\n\nAll 13 files at commit 7d85983. The hosted entry point `index.html` loads only `mill.js`, which imports `economy.js` and spawns `worker.js` with `hash.js`. The remaining files are an unloaded earlier game, server-side code, and deployment config.\n\n**Why it is not blocked**\n\n- No wallet, provider, seed-phrase, approval, permit, or signature code exists anywhere in the tree.\n- No remote scripts, iframes, redirects, or obfuscation. `hash.js` is a plain SHA-256, verified against the standard \"abc\" test vector.\n- The CPU hashing is opt-in behind a Start button, disclosed in the lede and footer, and submits nothing anywhere. The worker only reports counts back to the page, so it is a game mechanic rather than a cryptominer.\n\n**Findings recorded (2 medium, 4 low, 2 info)**\n\n- **Medium, mill.js:22.** On the hosted origins the API base is aiqiang888.com, a Vercel-hosted Chinese marketing site that returns 404 for every game path. Invite binding and both leaderboards are dead when hosted. The real server answers at the sslip.io host from the Caddyfile.\n- **Medium, index.html:60.** The footer link labelled \"Squeekchain invite\" is the author's personal referral code on a real third-party project, with no disclosure.\n- **Low, index.html:14.** The header says \"Squeekchain · Sepolia\" but no loaded script contacts either.\n- **Low, Caddyfile.burrowkeep:8.** Deployment files with the operator email, VPS IP, and Windows paths ship in the static export.\n- **Low, mill.js:21.** The API only works on two exact hostnames. On any other IPFS gateway the page posts to the gateway itself.\n- **Low, server.mjs:164.** Leaderboard and referral endpoints accept unauthenticated values, so scores and friend bonuses can be forged. Described against a local server rather than exercised on the live one.\n- **Info, worker.js:30 and game.js:845.** The hashing is local-only as noted above, and `game.js` plus `rules.js` are dead code referencing a missing image and missing element ids.\n\nAll eight snippets were checked against the tree and match exactly.\n\nSources: [SqueekChain on blockspot.io](https://blockspot.io/coin/squeekchain-squeek/), [Pickaxe news on hamster-powered Squeekchain](https://pickaxe.io/resources/news/hamster-powered-squeekchain-and-pudgy-penguins-ignite-crypto-buzz), [AICoin user post on Squeekchain](https://www.aicoin.com/en/news-flash/3156020)","treeHash":null,"usage":{"cachedInputTokens":558053,"inputTokens":226,"model":"claude-fable-5-1","outputTokens":17449,"runtime":"claude","turns":22,"wallClockMs":289994}}],"verification":[]}