{
  "scope": "只读静态源码对照；线上配置与漏洞未运行核验；无安全总分",
  "items": [
    {
      "title": "认证头由谁管理",
      "pwa": "已有共享拦截器，按配置添加Authorization。",
      "stake": "统一添加登录凭证与语言信息。",
      "recommendation": "两边都有共同请求入口。保留现有底座，核验公开请求与需登录请求的区分。",
      "pwa_sources": [
        {
          "path": "PwaSlotCash/src/Fwk/Http/Interceptors/AuthInterceptor.ts",
          "line": 14,
          "end_line": 17,
          "snippet": "[项目代码保留在本地；线上版仅提供定位]"
        }
      ],
      "stake_sources": [
        {
          "file": "outputs/stake-us-source/chunks/Cu3B9wdT.mjs",
          "offset_unit": "unicode-character",
          "character_offset_0based": 23291,
          "end_character_offset_0based_exclusive": 23601,
          "line": 30,
          "snippet": "function be({request:e,session:t}){let n={};t?.session&&(n[`x-access-token`]=t.session),t&&(n[`x-language`]=G(t.locale));let r=J(e,n);return{...e,headers:r}}var X=async({request:e,doc:t})=>{let n=t?.definitions?.[0],r=J(e,{\"x-operation-name\":(`name`in n?n.name?.value:void 0)||`unknown`,\"x-operation-type\":`que",
          "sha256": "50e62d1ac243b5f4a439288e29da91ab48a89ab79b661ead825c4b3130a11de6"
        },
        {
          "file": "outputs/stake-us-source/chunks/DYosYWTC.mjs",
          "offset_unit": "unicode-character",
          "character_offset_0based": 3365,
          "end_character_offset_0based_exclusive": 3575,
          "line": 1,
          "snippet": "Z=e=>{let t={\"Content-Type\":`application/json`};return e&&(t[`x-access-token`]=e),Object.assign(t,X),t},Q=()=>a(_),ne=e=>r(_,e),$=new WeakMap,re=e=>$.get(e.xstate)??null,ie=n=>{let r=o({...n,isWidget:t(f,()=>p(",
          "sha256": "8552d3871852551f5b3015c881e9f8497036938202309e7f7f82b96c62e7d314"
        }
      ]
    },
    {
      "title": "没登录时是否发请求",
      "pwa": "这条拦截路径读取凭证并写入头部，未见同位置缺凭证就中止。",
      "stake": "显式要求认证的查询，缺凭证会提前停止。",
      "recommendation": "Pwa可在确实需要登录的请求入口补早期检查；不能把游客或公开请求一律拦掉。服务器仍须验证权限。",
      "pwa_sources": [
        {
          "path": "PwaSlotCash/src/Fwk/Http/Interceptors/AuthInterceptor.ts",
          "line": 14,
          "end_line": 17,
          "snippet": "[项目代码保留在本地；线上版仅提供定位]"
        },
        {
          "path": "PwaSlotCash/src/Fwk/Http/comRequest.ts",
          "line": 170,
          "end_line": 180,
          "snippet": "[项目代码保留在本地；线上版仅提供定位]"
        }
      ],
      "stake_sources": [
        {
          "file": "outputs/stake-us-source/chunks/Cu3B9wdT.mjs",
          "offset_unit": "unicode-character",
          "character_offset_0based": 32639,
          "end_character_offset_0based_exclusive": 33049,
          "line": 30,
          "snippet": "function Ae(e){let t=async({request:e,controller:t})=>(new Headers(e.headers).has(`x-access-token`)===!1&&t.abort(`Request aborted: missing authentication token for authenticated query.`),e);return Q().query({...e,requestInterceptors:[...Q().getRequestInterceptors(),t]})}function je(e){return Q().fetchGraphQL(e)}function Me(e,t,n){return Q().mutation(e,t,n)}function Ne(e,t,n){return Q().mutate(e,t,n)}functi",
          "sha256": "50e62d1ac243b5f4a439288e29da91ab48a89ab79b661ead825c4b3130a11de6"
        },
        {
          "file": "outputs/stake-us-source/chunks/Cu3B9wdT.mjs",
          "offset_unit": "unicode-character",
          "character_offset_0based": 25931,
          "end_character_offset_0based_exclusive": 26116,
          "line": 30,
          "snippet": "if(m.aborted)return h();let u=r?r.name+JSON.stringify(n):null;if(u&&this.cacheMap.has(u))return{data:this.cacheMap.get(u),errors:void 0,context:c};let p=await l.fetch(_.url,{..._});if(p",
          "sha256": "50e62d1ac243b5f4a439288e29da91ab48a89ab79b661ead825c4b3130a11de6"
        }
      ]
    },
    {
      "title": "日志是否保留输入内容",
      "pwa": "开启调试日志时，把加密前的完整请求配置交给日志工具；响应日志也接收完整结果。",
      "stake": "已见的GraphQL错误日志会隐藏变量值。",
      "recommendation": "优先统一脱敏认证头、密码和验证码。Pwa的日志开关不等于脱敏；目前只确认代码路径，未确认线上开关是否开启。",
      "pwa_sources": [
        {
          "path": "PwaSlotCash/src/Fwk/Http/Interceptors/AuthInterceptor.ts",
          "line": 29,
          "end_line": 32,
          "snippet": "[项目代码保留在本地；线上版仅提供定位]"
        },
        {
          "path": "PwaSlotCash/src/Fwk/Http/Interceptors/LogResDataInterceptor.ts",
          "line": 26,
          "end_line": 34,
          "snippet": "[项目代码保留在本地；线上版仅提供定位]"
        }
      ],
      "stake_sources": [
        {
          "file": "outputs/stake-us-source/chunks/Cu3B9wdT.mjs",
          "offset_unit": "unicode-character",
          "character_offset_0based": 26479,
          "end_character_offset_0based_exclusive": 26699,
          "line": 30,
          "snippet": "variables:Object.fromEntries(Object.keys(n??{}).map(e=>[e,`[REDACTED]`]))};i.error(JSON.stringify(e))}for(let e of o||[])typeof e==`function`&&(r=e({errors:r,doc:t,variables:n,load:l,context:c}))}else u&&this.cacheMap.se",
          "sha256": "50e62d1ac243b5f4a439288e29da91ab48a89ab79b661ead825c4b3130a11de6"
        }
      ]
    },
    {
      "title": "动态加载与内容安全策略",
      "pwa": "在本次检查的src和Next配置中未找到nonce/CSP配置，部署层策略尚未知。",
      "stake": "资源预载会继承页面已有nonce标记。",
      "recommendation": "Stake多出可见的nonce兼容机制，但双方线上CSP头都未核验。先检查真实响应，再决定如何接入；未知不计为缺失。",
      "pwa_sources": [
        {
          "path": "PwaSlotCash/next.config.ts",
          "line": 40,
          "end_line": 50,
          "snippet": "[项目代码保留在本地；线上版仅提供定位]"
        }
      ],
      "stake_sources": [
        {
          "file": "outputs/stake-us-source/chunks/uBIymjUX.mjs",
          "offset_unit": "unicode-character",
          "character_offset_0based": 155,
          "end_character_offset_0based_exclusive": 325,
          "line": 1,
          "snippet": "o=document.querySelector(`meta[property=csp-nonce]`),s=o?.nonce||o?.getAttribute(`nonce`);function c(e){return Promise.all(e.map(e=>Promise.resolve(e).then(e=>({status:`f",
          "sha256": "e1a22f3f73566f21ff932e058d32243e4a118f3491b91e96893aa5ab7eb49a00"
        },
        {
          "file": "outputs/stake-us-source/chunks/uBIymjUX.mjs",
          "offset_unit": "unicode-character",
          "character_offset_0based": 689,
          "end_character_offset_0based_exclusive": 919,
          "line": 1,
          "snippet": "o.rel=a?`stylesheet`:`modulepreload`,a||(o.as=`script`),o.crossOrigin=``,o.href=r,s&&o.setAttribute(`nonce`,s),document.head.appendChild(o),a)return new Promise((e,t)=>{o.addEventListener(`load`,e),o.addEventListener(`error`,()=>t",
          "sha256": "e1a22f3f73566f21ff932e058d32243e4a118f3491b91e96893aa5ab7eb49a00"
        },
        {
          "file": "outputs/stake-us-source/chunks/Dh3-ySZv.mjs",
          "offset_unit": "unicode-character",
          "character_offset_0based": 42094,
          "end_character_offset_0based_exclusive": 42204,
          "line": 2,
          "snippet": "import{t as M}from\"./uBIymjUX.mjs\";import{I as N,u as ie,v as ae}from\"./D4G09-Ja.mjs\";import{d as P}from\"./B3x",
          "sha256": "59f75489b9cdb83705d8a34220d637522281bba92d3f1a7d7c9f265e2ae2de50"
        }
      ]
    },
    {
      "title": "第三方登录如何绑定本次授权",
      "pwa": "Apple登录生成随机state，保存在当前标签会话；返回时比较并删除。",
      "stake": "Google跳转分支生成随机校验值和SHA-256挑战，保存临时校验值。",
      "recommendation": "两边各有可见保护，但state与PKCE式挑战解决的问题不同，不能互相替代。Pwa是否需要PKCE，应按具体提供商和后端兑换合同核验。",
      "pwa_sources": [
        {
          "path": "PwaSlotCash/src/app/hooks/useSocialLogin.ts",
          "line": 204,
          "end_line": 214,
          "snippet": "[项目代码保留在本地；线上版仅提供定位]"
        },
        {
          "path": "PwaSlotCash/src/app/hooks/useSocialLogin.ts",
          "line": 620,
          "end_line": 625,
          "snippet": "[项目代码保留在本地；线上版仅提供定位]"
        }
      ],
      "stake_sources": [
        {
          "file": "outputs/stake-us-source/chunks/CHukuwd3.mjs",
          "offset_unit": "unicode-character",
          "character_offset_0based": 160,
          "end_character_offset_0based_exclusive": 520,
          "line": 1,
          "snippet": "n=()=>{let e=new Uint8Array(32);return crypto.getRandomValues(e),t(e)},r=async e=>{let n=await crypto.subtle.digest(`SHA-256`,new TextEncoder().encode(e));return t(new Uint8Array(n))},i=t=>{window.sessionStorage.setItem(e,t)},a=()=>window.sessionStorage.getItem(e),o=()=>window.sessionStorage.removeItem(e),s=e=>window.location.assign(e);export{s as a,a as i,r",
          "sha256": "f2aeb7abcc68b043f93a2a641c823be16d1d58f93b7e357d2f797e6aa97b7fcb"
        },
        {
          "file": "outputs/stake-us-source/chunks/DT98r2cN.mjs",
          "offset_unit": "unicode-character",
          "character_offset_0based": 17128,
          "end_character_offset_0based_exclusive": 17533,
          "line": 31,
          "snippet": "Xe=async e=>{J=!0,p(q,!0);try{let t=Ee(),n=await we(t);Te(t);let r=await le(Oe,{provider:e,returnTo:`${window.location.pathname}${window.location.search}${window.location.hash}`,codeChallenge:n}),i=r.data?.startOauthRedirect.url;if(r.errors||!i)throw r.errors??Error(`OAuth redirect unavailable`);return Ce(i),!0}catch{return De(),p(q,!1),Ue(),!1}},Ze=()=>{try{return fe.getBooleanFlagSync(`platformReleas",
          "sha256": "297518c032e4a61fe875ebc74399e095271b662a59bbf8fdda409bf68cf15a80"
        }
      ]
    },
    {
      "title": "退出授权时怎样清理",
      "pwa": "预加载定时器、页面恢复监听与一组返回检查定时器有卸载清理。",
      "stake": "弹窗关闭或组件销毁时，清理窗口检查、订阅和加载状态。",
      "recommendation": "两边都有清理路径。Pwa还应逐条核验延迟回调和晚到授权结果；不能据局部清理推断整个登录流程都已覆盖。",
      "pwa_sources": [
        {
          "path": "PwaSlotCash/src/app/hooks/useSocialLogin.ts",
          "line": 220,
          "end_line": 226,
          "snippet": "[项目代码保留在本地；线上版仅提供定位]"
        },
        {
          "path": "PwaSlotCash/src/app/hooks/useSocialLogin.ts",
          "line": 262,
          "end_line": 273,
          "snippet": "[项目代码保留在本地；线上版仅提供定位]"
        }
      ],
      "stake_sources": [
        {
          "file": "outputs/stake-us-source/chunks/DT98r2cN.mjs",
          "offset_unit": "unicode-character",
          "character_offset_0based": 15642,
          "end_character_offset_0based_exclusive": 15942,
          "line": 31,
          "snippet": "X=({closePopup:e=!1}={})=>{clearInterval(Y),Y=void 0,e&&W?.close();let t=K;K?.(),K=void 0,D()?.type===`oauth`&&D().unsubscribe===t&&A.set(null),p(q,!1),Ue()},We=m(()=>R()?[x(Ve)]:x(U)),Ge=m(()=>x(U).length>1),Z=t(null),Ke=!0;i(()=>{let e=R();if(Ke){Ke=!1;return}let t=x(Z)?.parentElement;for(;t&&t!==",
          "sha256": "297518c032e4a61fe875ebc74399e095271b662a59bbf8fdda409bf68cf15a80"
        },
        {
          "file": "outputs/stake-us-source/chunks/DT98r2cN.mjs",
          "offset_unit": "unicode-character",
          "character_offset_0based": 16116,
          "end_character_offset_0based_exclusive": 16401,
          "line": 31,
          "snippet": "Je=e=>{clearInterval(Y),Y=setInterval(()=>{G&&!e?.closed&&e?.close(),e?.closed&&(clearInterval(Y),G||X())},100)};te(()=>{Y&&clearInterval(Y),W&&W.close(),X()});let Ye=async e=>{if(J)return;J=!0,p(q,!0);let t={provider:e,sessionName:pe(),...me(),offerDisabled:!!se.affiliate.offerDisabl",
          "sha256": "297518c032e4a61fe875ebc74399e095271b662a59bbf8fdda409bf68cf15a80"
        },
        {
          "file": "outputs/stake-us-source/chunks/DT98r2cN.mjs",
          "offset_unit": "unicode-character",
          "character_offset_0based": 16941,
          "end_character_offset_0based_exclusive": 17311,
          "line": 31,
          "snippet": "if(K=ue(N,t,{next:({data:e,errors:t})=>n({data:e??void 0,errors:t}),error:e=>{let t=ce(e);n({errors:[t]})},complete:()=>{p(q,!1)}}),!J){K(),K=void 0;return}A.openSubscription(`oauth`,K)},Xe=async e=>{J=!0,p(q,!0);try{let t=Ee(),n=await we(t);Te(t);let r=await le(Oe,{provider:e,returnTo:`${window.location.pathname}${window.location.search}${window.location.hash}`,codeC",
          "sha256": "297518c032e4a61fe875ebc74399e095271b662a59bbf8fdda409bf68cf15a80"
        },
        {
          "file": "outputs/stake-us-source/chunks/C07WLNJL.mjs",
          "offset_unit": "unicode-character",
          "character_offset_0based": 0,
          "end_character_offset_0based_exclusive": 205,
          "line": 1,
          "snippet": "var e=({windowName:e=`Connect With OAuth`,url:t})=>{let n=screen.width/2-300,r=`location=0, status=0, width=600, height=600, top=${screen.height/2-300}, left=${n}`;return window.open(t,e,r)};export{e as t}",
          "sha256": "60cf89057acb332853ece968220daac62fbb61671d4848aceec5f9599da5147f"
        }
      ]
    },
    {
      "title": "结构化数据是否转义",
      "pwa": "JSON-LD共享组件将小于号转义后写入脚本。",
      "stake": "JSON-LD输出同样转义小于号。",
      "recommendation": "这一点双方已有对应处理，Pwa无需重做。保护范围限于JSON-LD；其他HTML输出应另查。",
      "pwa_sources": [
        {
          "path": "PwaSlotCash/src/app/_components/JsonLd.tsx",
          "line": 11,
          "end_line": 20,
          "snippet": "[项目代码保留在本地；线上版仅提供定位]"
        }
      ],
      "stake_sources": [
        {
          "file": "outputs/stake-us-source/chunks/ysfTt0iE.mjs",
          "offset_unit": "unicode-character",
          "character_offset_0based": 362,
          "end_character_offset_0based_exclusive": 507,
          "line": 1,
          "snippet": "if(r?.jsonLd){let n;try{n=t(r.jsonLd),r.sanitizedJsonLd=a(e(n))}catch(e){console.error(e)}}return r}var i=()=>typeof window<`u`&&!!n(`session`);f",
          "sha256": "b5e00052e92e07104ffd4cb213f1dadc8fab6785552efe73c58807bde7e27eb9"
        },
        {
          "file": "outputs/stake-us-source/chunks/ysfTt0iE.mjs",
          "offset_unit": "unicode-character",
          "character_offset_0based": 506,
          "end_character_offset_0based_exclusive": 639,
          "line": 1,
          "snippet": "function a(e){return`<script type=\"application/ld+json\">${String(e).replace(/</g,`\\\\u003c`)}<\\/script>`}export{r as n,a as r,i as t};",
          "sha256": "b5e00052e92e07104ffd4cb213f1dadc8fab6785552efe73c58807bde7e27eb9"
        },
        {
          "file": "outputs/stake-us-source/chunks/1dM5wbsU.mjs",
          "offset_unit": "unicode-character",
          "character_offset_0based": 2081,
          "end_character_offset_0based_exclusive": 2226,
          "line": 1,
          "snippet": "W=f(g,`sanitizedJsonLd`,3,void 0),G=f(g,`generatedJsonLd`,3,void 0),Ae=f(g,`robots`,3,void 0),K=f(g,`canonical`,3,void 0),je=u(()=>j(x().params.l",
          "sha256": "bcab497cc6f1ace74cffdaee77d7b58e1b72b3cf4b1202e89c21e021e9f1dfcd"
        }
      ]
    },
    {
      "title": "富文本是否真正经过清洗",
      "pwa": "有清洗函数，但当前调用被注释，渲染直接使用content；公告、公共弹窗和站内信调用此组件。",
      "stake": "已确认JSON-LD转义，未确认等价的富文本清洗路径。",
      "recommendation": "Pwa优先追踪这些内容的信任来源和服务端清洗；按需要恢复受控清洗。Stake这一项留未知，不当作领先证据。",
      "pwa_sources": [
        {
          "path": "PwaSlotCash/src/app/_components/RichText/RichText.tsx",
          "line": 199,
          "end_line": 210,
          "snippet": "[项目代码保留在本地；线上版仅提供定位]"
        },
        {
          "path": "PwaSlotCash/src/app/_dialogs/GameAnnouncementDialog/GameAnnouncementDialog.tsx",
          "line": 182,
          "end_line": 188,
          "snippet": "[项目代码保留在本地；线上版仅提供定位]"
        },
        {
          "path": "PwaSlotCash/src/app/(pages)/components/InBoxPopup/Inbox/InfoDetailBox.tsx",
          "line": 148,
          "end_line": 154,
          "snippet": "[项目代码保留在本地；线上版仅提供定位]"
        }
      ],
      "stake_sources": [
        {
          "file": "outputs/stake-us-source/chunks/ysfTt0iE.mjs",
          "offset_unit": "unicode-character",
          "character_offset_0based": 362,
          "end_character_offset_0based_exclusive": 507,
          "line": 1,
          "snippet": "if(r?.jsonLd){let n;try{n=t(r.jsonLd),r.sanitizedJsonLd=a(e(n))}catch(e){console.error(e)}}return r}var i=()=>typeof window<`u`&&!!n(`session`);f",
          "sha256": "b5e00052e92e07104ffd4cb213f1dadc8fab6785552efe73c58807bde7e27eb9"
        },
        {
          "file": "outputs/stake-us-source/chunks/ysfTt0iE.mjs",
          "offset_unit": "unicode-character",
          "character_offset_0based": 506,
          "end_character_offset_0based_exclusive": 639,
          "line": 1,
          "snippet": "function a(e){return`<script type=\"application/ld+json\">${String(e).replace(/</g,`\\\\u003c`)}<\\/script>`}export{r as n,a as r,i as t};",
          "sha256": "b5e00052e92e07104ffd4cb213f1dadc8fab6785552efe73c58807bde7e27eb9"
        },
        {
          "file": "outputs/stake-us-source/chunks/1dM5wbsU.mjs",
          "offset_unit": "unicode-character",
          "character_offset_0based": 2081,
          "end_character_offset_0based_exclusive": 2226,
          "line": 1,
          "snippet": "W=f(g,`sanitizedJsonLd`,3,void 0),G=f(g,`generatedJsonLd`,3,void 0),Ae=f(g,`robots`,3,void 0),K=f(g,`canonical`,3,void 0),je=u(()=>j(x().params.l",
          "sha256": "bcab497cc6f1ace74cffdaee77d7b58e1b72b3cf4b1202e89c21e021e9f1dfcd"
        }
      ]
    },
    {
      "title": "跨窗口消息如何筛选",
      "pwa": "游戏消息先检查来源origin，再按game_类型分发；退出时移除监听。",
      "stake": "已见OAuth结果通过服务端订阅接收，不能拿它证明postMessage来源校验。",
      "recommendation": "Pwa已有来源检查。可继续核验event.source是否绑定当前游戏窗口，以及每类消息的数据结构；两条通道不同，不评谁更安全。",
      "pwa_sources": [
        {
          "path": "PwaSlotCash/src/app/hooks/useGameMessage.tsx",
          "line": 20,
          "end_line": 39,
          "snippet": "[项目代码保留在本地；线上版仅提供定位]"
        }
      ],
      "stake_sources": [
        {
          "file": "outputs/stake-us-source/chunks/DT98r2cN.mjs",
          "offset_unit": "unicode-character",
          "character_offset_0based": 15642,
          "end_character_offset_0based_exclusive": 15942,
          "line": 31,
          "snippet": "X=({closePopup:e=!1}={})=>{clearInterval(Y),Y=void 0,e&&W?.close();let t=K;K?.(),K=void 0,D()?.type===`oauth`&&D().unsubscribe===t&&A.set(null),p(q,!1),Ue()},We=m(()=>R()?[x(Ve)]:x(U)),Ge=m(()=>x(U).length>1),Z=t(null),Ke=!0;i(()=>{let e=R();if(Ke){Ke=!1;return}let t=x(Z)?.parentElement;for(;t&&t!==",
          "sha256": "297518c032e4a61fe875ebc74399e095271b662a59bbf8fdda409bf68cf15a80"
        },
        {
          "file": "outputs/stake-us-source/chunks/DT98r2cN.mjs",
          "offset_unit": "unicode-character",
          "character_offset_0based": 16116,
          "end_character_offset_0based_exclusive": 16401,
          "line": 31,
          "snippet": "Je=e=>{clearInterval(Y),Y=setInterval(()=>{G&&!e?.closed&&e?.close(),e?.closed&&(clearInterval(Y),G||X())},100)};te(()=>{Y&&clearInterval(Y),W&&W.close(),X()});let Ye=async e=>{if(J)return;J=!0,p(q,!0);let t={provider:e,sessionName:pe(),...me(),offerDisabled:!!se.affiliate.offerDisabl",
          "sha256": "297518c032e4a61fe875ebc74399e095271b662a59bbf8fdda409bf68cf15a80"
        },
        {
          "file": "outputs/stake-us-source/chunks/DT98r2cN.mjs",
          "offset_unit": "unicode-character",
          "character_offset_0based": 16941,
          "end_character_offset_0based_exclusive": 17311,
          "line": 31,
          "snippet": "if(K=ue(N,t,{next:({data:e,errors:t})=>n({data:e??void 0,errors:t}),error:e=>{let t=ce(e);n({errors:[t]})},complete:()=>{p(q,!1)}}),!J){K(),K=void 0;return}A.openSubscription(`oauth`,K)},Xe=async e=>{J=!0,p(q,!0);try{let t=Ee(),n=await we(t);Te(t);let r=await le(Oe,{provider:e,returnTo:`${window.location.pathname}${window.location.search}${window.location.hash}`,codeC",
          "sha256": "297518c032e4a61fe875ebc74399e095271b662a59bbf8fdda409bf68cf15a80"
        },
        {
          "file": "outputs/stake-us-source/chunks/C07WLNJL.mjs",
          "offset_unit": "unicode-character",
          "character_offset_0based": 0,
          "end_character_offset_0based_exclusive": 205,
          "line": 1,
          "snippet": "var e=({windowName:e=`Connect With OAuth`,url:t})=>{let n=screen.width/2-300,r=`location=0, status=0, width=600, height=600, top=${screen.height/2-300}, left=${n}`;return window.open(t,e,r)};export{e as t}",
          "sha256": "60cf89057acb332853ece968220daac62fbb61671d4848aceec5f9599da5147f"
        }
      ]
    }
  ]
}