// Synthetic contracts and a loopback-only DOM fixture. Official-looking links // are inspected but never clicked, fetched, or exposed as an origin override. import assert from 'node:assert/strict'; import fs from 'node:fs/promises'; import path from 'node:path'; import {fileURLToPath} from 'node:url'; import {createServer} from 'node:http'; import {ActionInputError} from './action-contract.mjs'; const root=path.resolve(path.dirname(fileURLToPath(import.meta.url)),'../..'); await fs.mkdir(path.join(root,'.tmp'),{recursive:true}); const output=await fs.mkdtemp(path.join(root,'.tmp','navigation-profile-')); process.env.ASSISTANT_LEARNING_HOME=path.join(output,'worker-learning'); process.env.ASSISTANT_BROWSER_HEADLESS='1'; process.env.ASSISTANT_BROWSER_CHANNEL=process.platform==='win32' ? 'msedge' : 'chromium'; let assertions=0; const results=[]; let browserFixture=null; const eq=(actual,expected,message)=>{assert.deepEqual(actual,expected,message);assertions+=1;}; const ok=(value,message)=>{assert.ok(value,message);assertions+=1;}; const throws=(fn,code)=>{assert.throws(fn,error=>error instanceof ActionInputError && error.code===code);assertions+=1;}; const report=async(extra={})=>fs.writeFile(path.join(output,'report.json'),JSON.stringify({ result:'passed',passed:results.length,assertions,results,official_browser_navigation:false, live_platform_requests:0,application_api_calls:0,model_calls:0, browser_fixture:browserFixture || 'not executed',...extra, },null,2)); const group=async(name,run)=>{ const start=assertions; try{const details=await run();results.push({name,assertions:assertions-start,...details});await report();} catch(error){await report({result:'failed',failed_group:name,error:{name:error.name,message:error.message,code:error.code}});throw error;} }; const official='https://www.xiaohongshu.com'; const noteId='a'.repeat(24),otherId='b'.repeat(24),profileId='c'.repeat(24); const note=`${official}/explore/${noteId}?xsec_token=LOCAL_NAVIGATION_FIXTURE`; const profileUrl=`${official}/user/profile/${profileId}?source=LOCAL_FIXTURE`; const profile=await import('./execution-profile.mjs'); const {NATIVE_UI_PROFILE,NATIVE_UI_CONTRACT,NAVIGATION_UI_PROFILE,NAVIGATION_UI_CONTRACT, isNativeUiProfile,resolveExecutionProfile,executionContractMatches,executionMetadata, validNativePage,validNavigationPage,navigationTarget,navigationPopupMatches,navigationComparison,assertNativeUiAction,assertNativeUiResultLocation}=profile; await group('navigation profile is explicit immutable and never silently changes the old profile',()=>{ eq(NATIVE_UI_PROFILE,'playwright-xhs-native-ui-v1'); eq(NATIVE_UI_CONTRACT,{engine:'playwright',action_policy:'xhs-bounded-readonly-v1',network_policy:'xhs-page-native-v1'}); eq(NAVIGATION_UI_PROFILE,'playwright-xhs-navigation-ui-v1'); eq(NAVIGATION_UI_CONTRACT,{engine:'playwright',action_policy:'xhs-observed-navigation-readonly-v1',network_policy:'xhs-page-navigation-v1'}); eq(Object.isFrozen(NATIVE_UI_CONTRACT),true);eq(Object.isFrozen(NAVIGATION_UI_CONTRACT),true); eq(resolveExecutionProfile(undefined),null); eq(resolveExecutionProfile(NATIVE_UI_PROFILE),NATIVE_UI_CONTRACT); eq(resolveExecutionProfile(NAVIGATION_UI_PROFILE),NAVIGATION_UI_CONTRACT); eq(executionContractMatches({...NAVIGATION_UI_CONTRACT},NAVIGATION_UI_PROFILE),true); eq(executionContractMatches({...NATIVE_UI_CONTRACT},NATIVE_UI_PROFILE),true); eq(executionContractMatches({...NATIVE_UI_CONTRACT},NAVIGATION_UI_PROFILE),false); eq(executionContractMatches({...NAVIGATION_UI_CONTRACT},NATIVE_UI_PROFILE),false); for(const value of [null,undefined,[],{},Object.create(NAVIGATION_UI_CONTRACT), {...NAVIGATION_UI_CONTRACT,extra:'fixture'}, {...NAVIGATION_UI_CONTRACT,engine:'browser-use'}, {...NAVIGATION_UI_CONTRACT,network_policy:NATIVE_UI_CONTRACT.network_policy}]){ eq(executionContractMatches(value,NAVIGATION_UI_PROFILE),false); } eq(isNativeUiProfile(NATIVE_UI_PROFILE),true);eq(isNativeUiProfile(NAVIGATION_UI_PROFILE),true); for(const value of [null,undefined,false,0,'',{},'unknown']) eq(isNativeUiProfile(value),false); eq(executionMetadata(undefined),{}); const metadata=executionMetadata(NAVIGATION_UI_PROFILE); eq(metadata,{execution_profile:NAVIGATION_UI_PROFILE,execution_contract:NAVIGATION_UI_CONTRACT}); metadata.execution_contract.engine='LOCAL_MUTATION'; eq(executionMetadata(NAVIGATION_UI_PROFILE).execution_contract.engine,'playwright'); for(const value of [null,false,'',{},NAVIGATION_UI_PROFILE+' ',NAVIGATION_UI_PROFILE.toUpperCase(),'playwright-xhs-navigation-ui-v2']){ throws(()=>resolveExecutionProfile(value),'EXECUTION_PROFILE_INVALID'); } }); await group('destination parser allows only observed official page shapes and keeps the exact href',()=>{ for(const [href,kind,objectId] of [[note,'note',noteId],[profileUrl,'profile',profileId], [`${official}/search_result/${otherId}`,'note',otherId],[official+'/notification','notification',null], [official+'/explore','explore',null],[official+'/search_result?keyword=fixture','search',null], [official+'/search_result_ai?keyword=fixture','search',null]]){ eq(validNavigationPage(href),true,href); eq(navigationTarget(href),{kind,object_id:objectId,href:new URL(href).href}); } for(const href of [null,undefined,{},'', 'not a url','/explore', 'http://www.xiaohongshu.com/explore','https://xiaohongshu.com/explore', 'https://www.xiaohongshu.com:8443/explore','https://u:p@www.xiaohongshu.com/explore', 'https://www.xiaohongshu.com.evil.invalid/explore','https://www.xiaohongshu.com@evil.invalid/explore', 'https://so.xiaohongshu.com/explore',official+'/',official+'/explore/', official+'/message',official+'/messages',official+'/notification/',official+'/notification/send', official+'/user/profile/'+profileId+'/',official+'/user/profile/'+profileId.slice(1), official+'/user/profile/'+'g'.repeat(24),official+'/user/profile/%2f'+profileId, official+'/user/profile/'+profileId+'/follow',official+'/api/sns/web/v2/comment/post', official+'/api/sns/web/v1/follow',official+'/explore/'+noteId+'/delete', 'javascript:void(0)','data:text/html,fixture','file:///fixture']){ eq(validNavigationPage(href),false,String(href));eq(navigationTarget(href),null); } for(const href of [profileUrl,official+'/notification']) eq(validNativePage(href),false,'old v1 page scope remains unchanged'); }); const observed={kind:'click',tag:'a',unique:true,sensitive:false}; const actual=(href,kind)=>({tag:'a',href,sensitive:false,visible:true,in_viewport:true,unobscured:true, native_context:{search_input:false,note_link:kind==='note',profile_link:kind==='profile',navigation_link:['notification','explore','search'].includes(kind),read_root:false}}); const action=(href,kind,pageUrl=note)=>({executionProfile:NAVIGATION_UI_PROFILE,kind:'click',pageUrl, selector:'#fixture',observed:{...observed},actualRoots:[actual(href,kind)],matchCount:1,href}); const reject=(context,code='WRITE_ACTION_BLOCKED')=>{ const before=JSON.stringify(context);throws(()=>assertNativeUiAction(context),code);eq(JSON.stringify(context),before); }; await group('new navigation accepts fixed note profile notification and return links only',()=>{ for(const [href,kind] of [[profileUrl,'profile'],[official+'/notification','notification'], [official+'/explore','explore'],[official+'/search_result?keyword=fixture','search'],[note,'note']]){ const context=action(href,kind); eq(assertNativeUiAction(context),true); eq(assertNativeUiAction({...context,pageUrl:profileUrl}),true); eq(assertNativeUiAction({...context,pageUrl:official+'/notification'}),true); eq(assertNativeUiResultLocation(context,href),true); } const collection=action(profileUrl,'profile'); reject({...collection,observed:{...observed,unique:false}}); eq(assertNativeUiAction({...collection,observed:{...observed,unique:false},targetResolvedUnique:true}),true); reject({...collection,observed:{...observed,unique:false},targetResolvedUnique:true,matchCount:2}); }); await group('click permission requires actual usable unique immutable anchor evidence',()=>{ const context=action(profileUrl,'profile'),root=context.actualRoots[0]; for(const patch of [ {observed:null},{observed:{...observed,kind:'read'}},{observed:{...observed,tag:'button'}}, {observed:{...observed,sensitive:true}},{matchCount:0},{matchCount:2},{actualRoots:[]}, {actualRoots:[root,root]},{actualRoots:[{...root,sensitive:true}]}, {actualRoots:[{...root,visible:false}]},{actualRoots:[{...root,in_viewport:false}]}, {actualRoots:[{...root,unobscured:false}]},{actualRoots:[{...root,tag:'button'}]}, {actualRoots:[{...root,native_context:undefined}]}, {actualRoots:[{...root,native_context:{...root.native_context,profile_link:false}}]}, {actualRoots:[{...root,href:`${official}/user/profile/${otherId}`}]}, {href:`${official}/user/profile/${otherId}`}, ]) reject({...context,...patch}); for(const tag of ['button','input','textarea','select','form']){ reject({...context,observed:{...observed,tag},actualRoots:[{...root,tag}]}); } for(const kind of ['follow','unfollow','send_message','comment','evaluate','fetch','request','goto']){ reject({...context,kind},'SENSITIVE_OUTPUT'); } }); await group('fixed profile cannot be borrowed by a note or arbitrary page link',()=>{ for(const [href,kind] of [[profileUrl,'note'],[note,'profile'],[profileUrl,'notification'], [official+'/notification','profile'],[official+'/message','notification'], [official+'/api/sns/web/v1/follow','profile'],['https://evil.invalid/user/profile/'+profileId,'profile'], ['https://www.xiaohongshu.com:8443/user/profile/'+profileId,'profile'], ['https://u:p@www.xiaohongshu.com/user/profile/'+profileId,'profile']]) reject(action(href,kind)); for(const executionProfile of [undefined,NATIVE_UI_PROFILE]){ const context=action(profileUrl,'profile',official+'/explore'); reject({...context,executionProfile}); reject({...action(official+'/notification','notification',official+'/explore'),executionProfile}); eq(assertNativeUiAction({...action(note,'note',official+'/explore'),executionProfile}),true); } for(const executionProfile of [null,'unknown',false,{},NAVIGATION_UI_PROFILE+' ']){ reject({...action(profileUrl,'profile'),executionProfile},'EXECUTION_PROFILE_INVALID'); } }); await group('navigation result binds complete destination and object rather than a merely allowed page',()=>{ const context=action(profileUrl,'profile'); for(const changed of [note,context.pageUrl,official+'/notification', `${official}/user/profile/${otherId}?source=LOCAL_FIXTURE`, `${official}/user/profile/${profileId}`,profileUrl+'&changed=1',profileUrl+'#changed']){ throws(()=>assertNativeUiResultLocation(context,changed),'NAVIGATION_BINDING_MISMATCH'); } for(const href of [official+'/message','https://evil.invalid/user/profile/'+profileId]){ throws(()=>assertNativeUiResultLocation(context,href),'SOURCE_CHANGED'); } for(const kind of ['read','extract','wait','scroll','fill']){ const context={executionProfile:NAVIGATION_UI_PROFILE,kind,pageUrl:profileUrl}; eq(assertNativeUiResultLocation(context,profileUrl),true); throws(()=>assertNativeUiResultLocation(context,profileUrl+'&changed=1'),'SOURCE_CHANGED'); } }); await group('navigation diagnostics expose only the fixed comparison schema and no original identifiers or values',()=>{ const keys=['expected_kind','actual_kind','same_origin','same_pathname','same_object_id','same_query','same_query_pairs','same_hash','xsec_token','xsec_source','other_query_equal'].sort(); const boolKeys=['same_origin','same_pathname','same_object_id','same_query','same_query_pairs','same_hash','other_query_equal']; const kinds=new Set(['note','profile','notification','explore','search','invalid']); const validate=value=>{ eq(Object.keys(value).sort(),keys); ok(kinds.has(value.expected_kind));ok(kinds.has(value.actual_kind)); for(const key of boolKeys) eq(typeof value[key],'boolean',key); for(const key of ['xsec_token','xsec_source']){ eq(Object.keys(value[key]).sort(),['actual_count','expected_count','values_equal']); for(const name of ['actual_count','expected_count']) ok(Number.isInteger(value[key][name]) && value[key][name]>=0 && value[key][name]<=1000); eq(typeof value[key].values_equal,'boolean'); } }; const token='LOCAL_SENSITIVE_TOKEN_8f31',source='LOCAL_TRACKING_SOURCE_c82f',unknown='LOCAL_UNKNOWN_QUERY_SECRET_4a17'; const left=`${official}/user/profile/${profileId}?xsec_token=${token}&xsec_source=${source}&private_fixture_key=${unknown}#LOCAL_HASH_MARKER`; const right=`${official}/user/profile/${otherId}?xsec_token=DIFFERENT_LOCAL_TOKEN&xsec_source=${source}&private_fixture_key=${unknown}#OTHER_LOCAL_HASH`; const comparison=navigationComparison(left,right);validate(comparison); eq(comparison.expected_kind,'profile');eq(comparison.actual_kind,'profile'); eq(comparison.same_origin,true);eq(comparison.same_pathname,false);eq(comparison.same_object_id,false); eq(comparison.same_query,false);eq(comparison.same_query_pairs,false);eq(comparison.same_hash,false); eq(comparison.xsec_token,{expected_count:1,actual_count:1,values_equal:false}); eq(comparison.xsec_source,{expected_count:1,actual_count:1,values_equal:true});eq(comparison.other_query_equal,true); const serialized=JSON.stringify(comparison); for(const marker of [official,profileId,otherId,token,source,unknown,'private_fixture_key','LOCAL_HASH_MARKER','OTHER_LOCAL_HASH','DIFFERENT_LOCAL_TOKEN']){ eq(serialized.includes(marker),false,'fixed diagnostics cannot disclose '+marker); } const invalid=navigationComparison(null,'not a url');validate(invalid); eq(invalid.expected_kind,'invalid');eq(invalid.actual_kind,'invalid'); for(const key of boolKeys) eq(invalid[key],false); const many=Array.from({length:1001},()=>['xsec_token','LOCAL_COUNT_ONLY']); const repeated=profileUrl+'&'+new URLSearchParams(many).toString(); const bounded=navigationComparison(repeated,repeated);validate(bounded); eq(bounded.xsec_token,{expected_count:1000,actual_count:1000,values_equal:true}); }); await group('encoding tracking order and unknown query differences stay diagnostic and never authorize new navigation',()=>{ const base=`${official}/user/profile/${profileId}`; const encoded=navigationComparison(base+'?q=local+fixture&xsec_token=%2F',base+'?q=local%20fixture&xsec_token=/'); eq(encoded.same_query,false);eq(encoded.same_query_pairs,true);eq(encoded.xsec_token.values_equal,true);eq(encoded.other_query_equal,true); const tracking=navigationComparison(base+'?q=fixture&xsec_token=LEFT&xsec_source=one',base+'?q=fixture&xsec_token=RIGHT&xsec_source=two'); eq(tracking.same_object_id,true);eq(tracking.same_query,false);eq(tracking.other_query_equal,true); eq(tracking.xsec_token.values_equal,false);eq(tracking.xsec_source.values_equal,false); const duplicate=navigationComparison(base+'?xsec_token=one&xsec_token=two',base+'?xsec_token=one'); eq(duplicate.xsec_token,{expected_count:2,actual_count:1,values_equal:false}); const order=navigationComparison(base+'?a=one&b=two',base+'?b=two&a=one'); eq(order.same_query_pairs,false);eq(order.other_query_equal,false); const unknown=navigationComparison(base+'?unknown=one',base+'?unknown=two'); eq(unknown.other_query_equal,false);eq(unknown.xsec_token.values_equal,true);eq(unknown.xsec_source.values_equal,true); const hash=navigationComparison(base+'?q=fixture#one',base+'?q=fixture#two'); eq(hash.same_query,true);eq(hash.same_query_pairs,true);eq(hash.same_hash,false); for(const [left,right] of [[base+'?q=local+fixture',base+'?q=local%20fixture'], [base+'?xsec_token=one',base+'?xsec_token=two'],[base+'?unknown=one',base+'?unknown=two'], [base+'?a=one&b=two',base+'?b=two&a=one'],[base+'#one',base+'#two']]){ const context=action(left,'profile');let error; try{assertNativeUiResultLocation(context,right);}catch(value){error=value;} ok(error instanceof ActionInputError);eq(error.code,'NAVIGATION_BINDING_MISMATCH'); eq(error.navigation_comparison,navigationComparison(left,right)); eq(navigationPopupMatches(left,right),false,'diagnostic equality facts never weaken full profile URL binding'); } }); await group('only new navigation mismatch errors receive comparison fields and old error shapes stay unchanged',()=>{ const expected=`${official}/user/profile/${profileId}?xsec_token=LOCAL_ERROR_SECRET&unknown=LOCAL_UNKNOWN_SECRET`; const context=action(expected,'profile');let mismatch; try{assertNativeUiResultLocation(context,expected+'&changed=1');}catch(error){mismatch=error;} ok(mismatch instanceof ActionInputError);eq(mismatch.code,'NAVIGATION_BINDING_MISMATCH'); eq(mismatch.navigation_comparison.same_object_id,true);eq(mismatch.navigation_comparison.other_query_equal,false); for(const marker of ['LOCAL_ERROR_SECRET','LOCAL_UNKNOWN_SECRET',profileId,official,'unknown']){ eq((JSON.stringify(mismatch)+' '+mismatch.message).includes(marker),false); } const cases=[ [{executionProfile:NATIVE_UI_PROFILE,kind:'click',pageUrl:official+'/explore',href:note},`${official}/explore/${otherId}`,'NOTE_BINDING_MISMATCH'], [{kind:'click',pageUrl:official+'/explore',href:note},`${official}/explore/${otherId}`,'NOTE_BINDING_MISMATCH'], [context,'https://evil.invalid/user/profile/'+profileId,'SOURCE_CHANGED'], [{executionProfile:NAVIGATION_UI_PROFILE,kind:'read',pageUrl:profileUrl},profileUrl+'&changed=1','SOURCE_CHANGED'], ]; for(const [current,href,code] of cases){ let error;try{assertNativeUiResultLocation(current,href);}catch(value){error=value;} ok(error instanceof ActionInputError);eq(error.code,code);eq(Object.hasOwn(error,'navigation_comparison'),false); } }); await group('popup continuation binds complete non-note destinations and the fixed note identity',()=>{ for(const href of [profileUrl,official+'/notification',official+'/explore',official+'/search_result?keyword=fixture']){ eq(navigationPopupMatches(href,href),true); for(const changed of [href+'#changed',href+(href.includes('?') ? '&changed=1' : '?changed=1')]){ eq(navigationPopupMatches(href,changed),false); eq(navigationPopupMatches(changed,href),false); } } for(const expected of [undefined,null,'',{},'about:blank',official+'/message','https://evil.invalid/explore']){ eq(navigationPopupMatches(expected,profileUrl),false); eq(navigationPopupMatches(profileUrl,expected),false); } for(const actualUrl of [`${official}/user/profile/${otherId}?source=LOCAL_FIXTURE`, `${official}/user/profile/${profileId}`,note,official+'/notification', `https://u:p@www.xiaohongshu.com/user/profile/${profileId}?source=LOCAL_FIXTURE`, `https://www.xiaohongshu.com:8443/user/profile/${profileId}?source=LOCAL_FIXTURE`, `https://www.xiaohongshu.com.evil.invalid/user/profile/${profileId}?source=LOCAL_FIXTURE`, `http://www.xiaohongshu.com/user/profile/${profileId}?source=LOCAL_FIXTURE`, official+'/api/sns/web/v1/follow']) eq(navigationPopupMatches(profileUrl,actualUrl),false); }); const {beginNativeUiRequestPolicy,evaluatePlatformRequest,matchPlatformRequest,endPlatformRequestPolicy}=await import('./platform-policy.mjs'); const policies=new Set(); const mint=context=>{const policy=beginNativeUiRequestPolicy(context);ok(policy);policies.add(policy);return policy;}; const request={automating:true,sessionOrigin:official,pageUrl:note,activeMainFrame:true,method:'POST',resourceType:'xhr', url:'https://so.xiaohongshu.com/api/synthetic-native-request',now:10001}; const allow={allowed:true,policy_version:'xhs-page-navigation-v1',policy_rule:'native_page_traffic'}; const denied=(context,reason)=>{ const value=evaluatePlatformRequest(context);eq(value.allowed,false);if(reason) eq(value.reason,reason);eq(matchPlatformRequest(context),null); }; await group('navigation request capabilities bind the original source and complete target',()=>{ const context={...action(profileUrl,'profile'),sessionOrigin:official,now:10000}; const policy=mint(context); eq(policy,{version:'xhs-page-navigation-v1',scope:'native_ui',expiresAt:25000});eq(Object.isFrozen(policy),true); eq(evaluatePlatformRequest({...request,policy}),allow); eq(evaluatePlatformRequest({...request,policy,pageUrl:profileUrl}),allow); for(const pageUrl of [profileUrl+'&changed=1',profileUrl+'#changed',`${official}/user/profile/${otherId}`, official+'/notification',note+'&changed=1',official+'/explore']) denied({...request,policy,pageUrl},'page_changed'); context.pageUrl=official+'/explore';context.href=official+'/notification';context.actualRoots[0].href=context.href; eq(evaluatePlatformRequest({...request,policy,pageUrl:profileUrl}),allow,'issued source facts cannot be mutated by the caller'); for(const href of [official+'/explore',official+'/notification',official+'/search_result?keyword=fixture']){ const kind=navigationTarget(href).kind; const policy=mint({...action(href,kind),sessionOrigin:official,now:10000}); eq(evaluatePlatformRequest({...request,policy,pageUrl:href}),allow); denied({...request,policy,pageUrl:profileUrl},'page_changed'); } }); await group('note results allow only the same fixed identity across standard aliases and tracking changes',()=>{ const context=action(note,'note',official+'/search_result?keyword=fixture'); const policy=mint({...context,sessionOrigin:official,now:10000}); const aliases=[note,`${official}/search_result/${noteId}`,`${official}/explore/${noteId}`, `${official}/explore/${noteId}?xsec_token=OTHER_LOCAL_TRACKING&source=fixture`, `${official}/search_result/${noteId.toUpperCase()}?source=changed#fixture`]; for(const pageUrl of aliases){ eq(assertNativeUiResultLocation(context,pageUrl),true); eq(evaluatePlatformRequest({...request,policy,pageUrl}),allow); eq(navigationPopupMatches(note,pageUrl),true); eq(navigationPopupMatches(pageUrl,note),true); } // Aliases are accepted only after a pinned actual anchor was activated. // The click's precondition still binds the exact href observed on that node. reject({...context,actualRoots:[actual(`${official}/search_result/${noteId}`,'note')]}); reject({...context,href:`${official}/search_result/${noteId}`}); for(const pageUrl of [`${official}/explore/${otherId}`,`${official}/search_result/${otherId}`, `${official}/user/profile/${noteId}`,official+'/explore',official+'/notification', `${official}/explore/${noteId}/delete`,`${official}/search_result_ai/${noteId}`, `https://evil.invalid/explore/${noteId}`,`https://www.xiaohongshu.com:8443/explore/${noteId}`, `https://u:p@www.xiaohongshu.com/explore/${noteId}`]){ const inScope=validNavigationPage(pageUrl); throws(()=>assertNativeUiResultLocation(context,pageUrl),inScope ? 'NAVIGATION_BINDING_MISMATCH' : 'SOURCE_CHANGED'); denied({...request,policy,pageUrl}); eq(navigationPopupMatches(note,pageUrl),false); } return {note_equivalence:'official standard note route and identical note ID only; non-note target hrefs stay exact', pre_click_href_exact:true}; }); await group('profile hydration may only omit the two observed single channel context parameters',async()=>{ const base=`${official}/user/profile/${profileId}`; const fixed='xsec_token=LOCAL_FIXED_TOKEN&xsec_source=LOCAL_FIXED_SOURCE'; const expected=base+'?'+fixed+'&channel_type=LOCAL_CHANNEL&parent_page_channel_type=LOCAL_PARENT&other=LOCAL_OTHER#fixed'; const context=action(expected,'profile',note); const policy=mint({...context,sessionOrigin:official,now:10000}); const allowedUrls=[expected, base+'?'+fixed+'&parent_page_channel_type=LOCAL_PARENT&other=LOCAL_OTHER#fixed', base+'?'+fixed+'&channel_type=LOCAL_CHANNEL&other=LOCAL_OTHER#fixed', base+'?'+fixed+'&other=LOCAL_OTHER#fixed']; for(const pageUrl of allowedUrls){ eq(assertNativeUiResultLocation(context,pageUrl),true); eq(evaluatePlatformRequest({...request,policy,pageUrl}),allow); eq(navigationPopupMatches(expected,pageUrl),true); } // An existing empty value is still a single observed pair, and can only // disappear; no arbitrary new channel pair may be created during hydration. eq(navigationPopupMatches(base+'?channel_type=',base),true); eq(navigationPopupMatches(base+'?parent_page_channel_type=',base),true); const changedUrls=[ base+'?'+fixed+'&channel_type=CHANGED&parent_page_channel_type=LOCAL_PARENT&other=LOCAL_OTHER#fixed', base+'?'+fixed+'&parent_page_channel_type=CHANGED&other=LOCAL_OTHER#fixed', base+'?'+fixed+'&channel_type=LOCAL_CHANNEL&channel_type=LOCAL_CHANNEL&other=LOCAL_OTHER#fixed', base+'?'+fixed+'&parent_page_channel_type=LOCAL_PARENT&parent_page_channel_type=LOCAL_PARENT&other=LOCAL_OTHER#fixed', base+'?xsec_token=CHANGED&xsec_source=LOCAL_FIXED_SOURCE&other=LOCAL_OTHER#fixed', base+'?xsec_token=LOCAL_FIXED_TOKEN&xsec_source=CHANGED&other=LOCAL_OTHER#fixed', base+'?xsec_source=LOCAL_FIXED_SOURCE&other=LOCAL_OTHER#fixed', base+'?'+fixed+'&other=CHANGED#fixed',base+'?'+fixed+'#fixed', base+'?'+fixed+'&other=LOCAL_OTHER&added=NEW#fixed', base+'?other=LOCAL_OTHER&'+fixed+'#fixed', base+'?'+fixed+'&other=LOCAL_OTHER#changed',base+'?'+fixed+'&other=LOCAL_OTHER', `${official}/user/profile/${otherId}?${fixed}&other=LOCAL_OTHER#fixed`, `${official}/explore/${profileId}?${fixed}&other=LOCAL_OTHER#fixed`, `https://evil.invalid/user/profile/${profileId}?${fixed}&other=LOCAL_OTHER#fixed`, `https://www.xiaohongshu.com:8443/user/profile/${profileId}?${fixed}&other=LOCAL_OTHER#fixed`, `https://u:p@www.xiaohongshu.com/user/profile/${profileId}?${fixed}&other=LOCAL_OTHER#fixed`, ]; for(const pageUrl of changedUrls){ eq(navigationPopupMatches(expected,pageUrl),false); throws(()=>assertNativeUiResultLocation(context,pageUrl),validNavigationPage(pageUrl) ? 'NAVIGATION_BINDING_MISMATCH' : 'SOURCE_CHANGED'); denied({...request,policy,pageUrl}); } for(const [left,right] of [ [base+'?'+fixed,base+'?'+fixed+'&channel_type=NEW'], [base+'?'+fixed,base+'?'+fixed+'&parent_page_channel_type=NEW'], [base+'?channel_type=one',base+'?parent_page_channel_type=NEW'], [base+'?parent_page_channel_type=one',base+'?channel_type=NEW'], [base+'?channel_type=one&channel_type=two',base], [base+'?parent_page_channel_type=one&parent_page_channel_type=two',base], [base+'?channel_type=one&channel_type=one',base+'?channel_type=one'], ]) eq(navigationPopupMatches(left,right),false); const duplicateExact=base+'?channel_type=one&channel_type=one'; eq(navigationPopupMatches(duplicateExact,duplicateExact),true,'an unchanged complete href keeps the existing exact-match contract'); // The extra rule applies to profiles only. Notification and search targets // must not inherit profile-specific channel omission behavior. for(const pathname of ['/explore','/notification','/search_result']){ eq(navigationPopupMatches(official+pathname+'?channel_type=one',official+pathname),false); } const {nativePopupRequestContext}=await import('./browser-worker.mjs'); const sourceFrame={},popupFrame={}; const source={url:()=>note,mainFrame:()=>sourceFrame},popup={url:()=>allowedUrls[3],mainFrame:()=>popupFrame}; sourceFrame.page=()=>source;popupFrame.page=()=>popup; const permission={opener:source,sourceUrl:note,expectedUrl:expected,pendingPopup:popup,adopted:false}; const popupContext={executionProfile:NAVIGATION_UI_PROFILE,automating:true,policy,policyPage:source,currentPage:source, permission,requestPage:popup,requestFrame:popupFrame,popupOpener:source,now:10001}; eq(nativePopupRequestContext(popupContext),{activeMainFrame:true,pageUrl:allowedUrls[3]}); eq(nativePopupRequestContext({...popupContext,popupOpener:null}),null); eq(nativePopupRequestContext({...popupContext,now:25000}),null); eq(nativePopupRequestContext({...popupContext,executionProfile:NATIVE_UI_PROFILE}),null); eq(policy.expiresAt,25000); reject({...context,actualRoots:[actual(allowedUrls[3],'profile')]},'WRITE_ACTION_BLOCKED'); return {fixed_omittable_keys:['channel_type','parent_page_channel_type'],other_query_values_and_order_preserved:true, popup_expiry_and_opener_unchanged:true,pre_click_href_exact:true}; }); await group('fifteen second capabilities reject early exact expiry revoked and forged use',()=>{ const policy=mint({...action(profileUrl,'profile'),sessionOrigin:official,now:10000}); eq(evaluatePlatformRequest({...request,policy,now:10000}),allow); eq(evaluatePlatformRequest({...request,policy,now:24999}),allow); denied({...request,policy,now:9999},'policy_not_started'); for(const now of [25000,25001]) denied({...request,policy,now},'policy_expired'); for(const now of [NaN,Infinity,null,'10001']) denied({...request,policy,now},'invalid_time'); denied({...request,policy:{...policy}},'inactive_policy'); endPlatformRequestPolicy(policy);denied({...request,policy},'inactive_policy'); }); await group('request authority remains first party HTTPS xhr fetch and requires a permitted UI action',()=>{ const context={...action(profileUrl,'profile'),sessionOrigin:official,now:10000}; const policy=mint(context); for(const host of ['www.xiaohongshu.com','xiaohongshu.com','so.xiaohongshu.com','as.xiaohongshu.com']){ for(const resourceType of ['xhr','fetch']) eq(evaluatePlatformRequest({...request,policy,resourceType,url:`https://${host}/synthetic-native`}),allow); } for(const patch of [{activeMainFrame:false},{automating:false},{sessionOrigin:'https://evil.invalid'}, {pageUrl:official+'/message'},{pageUrl:'https://evil.invalid/explore'}, {url:'https://www.xiaohongshu.com.evil.invalid/synthetic-native'}, {url:'https://u:p@so.xiaohongshu.com/synthetic-native'}, {url:'https://so.xiaohongshu.com:8443/synthetic-native'}, {url:'http://so.xiaohongshu.com/synthetic-native'}, {url:'http://127.0.0.1/synthetic-native'}, {resourceType:'document'},{resourceType:'websocket'},{method:'GET'},{method:'DELETE'}]) denied({...request,policy,...patch}); for(const patch of [{executionProfile:'unknown'},{executionProfile:null},{sessionOrigin:'https://evil.invalid'}, {kind:'follow'},{kind:'send_message'},{observed:null},{href:official+'/message'}, {actualRoots:[actual(official+'/message','notification')]},{now:NaN}]){ eq(beginNativeUiRequestPolicy({...context,...patch}),null); } }); await group('old v1 cannot receive the navigation page scope via copied or missing profile metadata',()=>{ const readRoot={tag:'section',readonly_root:true,sensitive:false,forbidden:false,native_context:{read_root:true}}; for(const pageUrl of [profileUrl,official+'/notification']){ for(const executionProfile of [undefined,NATIVE_UI_PROFILE]){ reject({executionProfile,kind:'read',pageUrl,actualRoots:[readRoot]},'SCOPE_BLOCKED'); eq(beginNativeUiRequestPolicy({executionProfile,kind:'read',pageUrl,actualRoots:[readRoot],sessionOrigin:official,now:10000}),null); } eq(assertNativeUiAction({executionProfile:NAVIGATION_UI_PROFILE,kind:'read',pageUrl,actualRoots:[readRoot]}),true); } }); await group('popup request handoff needs one fixed opener target and genuine main frame without renewing policy',async()=>{ const {nativePopupRequestContext}=await import('./browser-worker.mjs'); const sourceFrame={},popupFrame={},otherFrame={}; const source={url:()=>note,mainFrame:()=>sourceFrame}; const popup={url:()=>profileUrl,mainFrame:()=>popupFrame}; sourceFrame.page=()=>source;popupFrame.page=()=>popup; const otherPopup={url:()=>profileUrl,mainFrame:()=>({})}; const policy=mint({...action(profileUrl,'profile'),sessionOrigin:official,now:10000}); const permission={opener:source,sourceUrl:note,expectedUrl:profileUrl,adopted:false,pendingPopup:popup}; const context={executionProfile:NAVIGATION_UI_PROFILE,automating:true,policy,policyPage:source,currentPage:source, permission,requestPage:popup,requestFrame:popupFrame,popupOpener:source,now:10001}; const accepted={activeMainFrame:true,pageUrl:profileUrl}; const before=JSON.stringify({permission:{sourceUrl:permission.sourceUrl,expectedUrl:permission.expectedUrl,adopted:permission.adopted},policy}); eq(nativePopupRequestContext(context),accepted); eq(evaluatePlatformRequest({...request,policy,...nativePopupRequestContext(context)}),allow); eq(JSON.stringify({permission:{sourceUrl:permission.sourceUrl,expectedUrl:permission.expectedUrl,adopted:permission.adopted},policy}),before,'request qualification changes neither facts nor policy'); eq(policy.expiresAt,25000); const adopted={...context,policyPage:popup,currentPage:popup,permission:{...permission,adopted:true}}; eq(nativePopupRequestContext(adopted),accepted); eq(adopted.policy,policy,'adoption reuses the original issued capability'); eq(adopted.policy.expiresAt,25000,'adoption cannot start a new fifteen second window'); for(const patch of [ {executionProfile:NATIVE_UI_PROFILE},{executionProfile:undefined},{executionProfile:'unknown'}, {automating:false},{policy:null},{policy:{...policy,scope:'search'}}, {policy:{...policy,version:'xhs-page-native-v1'}},{policy:{...policy,expiresAt:10000}}, {requestPage:source},{requestFrame:sourceFrame},{requestFrame:otherFrame},{requestFrame:null}, {popupOpener:null},{popupOpener:otherPopup},{permission:null}, {permission:{...permission,manual:true}},{permission:{...permission,opener:otherPopup}}, {permission:{...permission,sourceUrl:note+'&changed=1'}}, {permission:{...permission,expectedUrl:profileUrl+'&changed=1'}}, {permission:{...permission,expectedUrl:official+'/message'}}, {permission:{...permission,pendingPopup:otherPopup}}, {permission:{...permission,adopted:true}}, {policyPage:otherPopup},{currentPage:otherPopup}, {requestPage:{url:()=>official+'/message',mainFrame:()=>popupFrame}}, {requestPage:{url:()=>profileUrl+'&changed=1',mainFrame:()=>popupFrame}}, {requestPage:{url:()=>`https://evil.invalid/user/profile/${profileId}`,mainFrame:()=>popupFrame}}, {now:25000},{now:25001},{now:NaN},{now:Infinity},{now:'10001'}, ]) eq(nativePopupRequestContext({...context,...patch}),null); for(const patch of [{policyPage:source},{currentPage:source},{permission:{...permission,adopted:true,pendingPopup:otherPopup}}]){ eq(nativePopupRequestContext({...adopted,...patch}),null); } // Even apparently correct public fields cannot fabricate the private issued // policy. Qualification is followed by the existing capability evaluator. const clone={...policy}; denied({...request,policy:clone,...(nativePopupRequestContext({...context,policy:clone}) || {})},'inactive_policy'); eq(nativePopupRequestContext({...context,now:24999}),accepted); denied({...request,policy,now:25000,...accepted},'policy_expired'); endPlatformRequestPolicy(policy); denied({...request,policy,...accepted},'inactive_policy'); return {pre_adoption_and_post_adoption:true,child_frames_and_unrequested_popups_rejected:true, original_expiry:25000,reissued_policy:false,production_network:false}; }); await group('real loopback Edge popup frame and opener objects exercise the handoff predicate',async()=>{ const {nativePopupRequestContext}=await import('./browser-worker.mjs'); const {chromium}=await import('playwright'); let browser,fixtureRequests=0,unexpectedNetwork=0; const server=createServer((req,res)=>{ fixtureRequests+=1; const html=req.url==='/source' ? 'Open local profile fixture' : req.url==='/destination' ? '
Local child frame
'; res.writeHead(200,{'content-type':'text/html; charset=utf-8'}).end(''+html); }); await new Promise(resolve=>server.listen(0,'127.0.0.1',resolve)); const loopback=`http://127.0.0.1:${server.address().port}`; try{ browser=await chromium.launch({channel:process.platform==='win32' ? 'msedge' : 'chromium',headless:true}); const browserContext=await browser.newContext({viewport:{width:1280,height:840},serviceWorkers:'block'}); let postRequest; browserContext.on('request',req=>{if(req.method()==='POST' && req.url()===loopback+'/local-post') postRequest=req;}); await browserContext.route('**/*',async route=>{ if(new URL(route.request().url()).origin!==loopback){unexpectedNetwork+=1;await route.abort();return;}await route.continue(); }); const actualSource=await browserContext.newPage();await actualSource.goto(loopback+'/source'); const [actualPopup]=await Promise.all([actualSource.waitForEvent('popup'),actualSource.locator('#open').click()]); await actualPopup.waitForLoadState('load'); eq(await actualPopup.opener(),actualSource,'the popup has a real explicit opener'); ok(postRequest,'local popup emitted an actual main-frame POST'); eq(postRequest.frame(),actualPopup.mainFrame());eq(postRequest.frame().page(),actualPopup); const child=actualPopup.frames().find(frame=>frame!==actualPopup.mainFrame());ok(child);eq(child.parentFrame(),actualPopup.mainFrame()); // Only the fixed URL reads are synthetic. Frame and opener identity were // obtained from the actual loopback browser above; no official page is // navigated, intercepted, fetched, or accepted via an origin override. const source=actualSource,popup=actualPopup; const realSourceUrl=source.url.bind(source),realPopupUrl=popup.url.bind(popup); // Project only the two URL accessors after local navigation completed; // retain genuine Page, Frame, frame.page() and opener object identities. source.url=()=>note;popup.url=()=>profileUrl; const policy=mint({...action(profileUrl,'profile'),sessionOrigin:official,now:10000}); const permission={opener:source,sourceUrl:note,expectedUrl:profileUrl,pendingPopup:popup,adopted:false}; const context={executionProfile:NAVIGATION_UI_PROFILE,automating:true,policy,policyPage:source,currentPage:source, permission,requestPage:popup,requestFrame:postRequest.frame(),popupOpener:source,now:10001}; const accepted={activeMainFrame:true,pageUrl:profileUrl}; try{ eq(nativePopupRequestContext(context),accepted); eq(evaluatePlatformRequest({...request,policy,...accepted}),allow); eq(nativePopupRequestContext({...context,requestFrame:child}),null); eq(nativePopupRequestContext({...context,popupOpener:null}),null); eq(nativePopupRequestContext({...context,permission:null}),null); eq(nativePopupRequestContext({...context,executionProfile:NATIVE_UI_PROFILE}),null); const adopted={...context,currentPage:popup,policyPage:popup,permission:{...permission,adopted:true}}; eq(nativePopupRequestContext(adopted),accepted);eq(adopted.policy,policy);eq(policy.expiresAt,25000); eq(nativePopupRequestContext({...adopted,now:25000}),null); }finally{source.url=realSourceUrl;popup.url=realPopupUrl;} eq(nativePopupRequestContext(context),null,'unprojected real loopback URL cannot become an official profile'); eq(unexpectedNetwork,0);endPlatformRequestPolicy(policy); return {browser:process.platform==='win32' ? 'Edge' : 'Chromium',loopback_requests:fixtureRequests,local_main_frame_post:true, real_opener_and_frame_identity:true,official_urls_synthetic_metadata_only:true,unexpected_network_attempts:unexpectedNetwork, production_origin_override:false,worker_navigation_profile_end_to_end:false}; }finally{if(browser) await browser.close();await new Promise(resolve=>server.close(resolve));} }); await group('fixed loopback DOM distinguishes ordinary navigation from editable and write controls',async()=>{ const {inspectElements}=await import('./browser-worker.mjs'); const {chromium}=await import('playwright'); const observations=[]; let browser,fixtureRequests=0,unexpectedNetwork=0; const server=createServer((req,res)=>{fixtureRequests+=1;res.writeHead(200,{'content-type':'text/html; charset=utf-8'}).end('