
    4j':                       d Z ddlmZ ddlZddlmc mZ ddl	Z	ddl
Z
ddlZddlZddlZddlmZ ddlZ ed      Zedz  dz  Zedz  d	z  Zej(                  j+                  d ee             dd
lmZmZmZmZmZ ddddZd(dZ ej>                         d)d       Z d Z!d Z"d Z#ejH                  jK                  dg d      d        Z&d Z'd Z(d Z)d Z*d Z+g dZ,ejH                  jK                  de,      d        Z-d Z.d  Z/ejH                  jK                  d! e0ejc                                     d"        Z2d*d#Z3d$ Z4d% Z5d& Z6d' Z7y)+u  Regression — task-2617 CLI output-path guard (회장 직접 승인 2026-05-19).

검증 범위 (task-2617 §5):
  * guard 모듈 import-only (argparse/main/CLI/__main__ 부재)
  * policy 허용 경로(memory/events|reports 직하위·task-id prefix)만 write
  * absolute · ../ · ws-escape · symlink-component · hardlink · overwrite
    = fail-closed (write 전 차단·부분파일 미잔존)
  * 3 CLI 호출부(batch_hold_adjudicator/batch_dependency_classifier/
    pre_authorized_evidence_bundle_builder) 가 guard 경유
  * stdout-only 3건(auto_remediation_planner/codex_high_classifier/
    critical7_classifier) byte-0 불변
  * 변경 3파일의 stdout 기본 동작 불변(--out 없을 때)
    )annotationsN)Path/home/jay/workspaceanu_v3zcli_output_path_guard.pyconfigzcli_output_path_policy.yaml)
GuardErrorGuardPolicyatomic_guarded_writeload_policyvalidate_output_path@150e79992dbbfe41a432abf6096a8ade0e897f0eef23c86e585103b1eaa5b364@214af21eac48b184e37d4ed86403417636098c84f4e573cad949454ec3964006@6143a2d25fff1f15201feb461c9ce28e62d3400f5893264fe445d311fe4877f2)z"anu_v3/auto_remediation_planner.pyzanu_v3/codex_high_classifier.pyzanu_v3/critical7_classifier.pyc                d    t        j                  | j                               j                         S N)hashlibsha256
read_bytes	hexdigest)ps    G/home/jay/workspace/tests/regression/test_cli_output_path_guard_2617.py_shar   3   s     >>!,,.)3355    c                      t        t              S r   )r   POLICY r   r   policyr   7   s    vr   c            	        t         j                  d      } t        j                  |       }t        j                  |      D ]  }t        |t        j                  t        j                  f      r|j                  }d}||k7  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }t        j                  d      d	z   d
|iz  }t!        t        j"                  |            d x}x}}t        |t        j$                        r|j&                  D ]  }|j                  }d}||k7  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }t        j                  d      d	z   d
|iz  }t!        t        j"                  |            d x}x}} t        |t        j(                        r|j*                  }d}||k7  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }t        j                  d      d	z   d
|iz  }t!        t        j"                  |            d x}x}}t        |t        j,                        s)t        j.                  |j0                        }	g }d}
|
|	v}|}|sd}||	v}|}|snt        j                  d|fd|
|	f      t        j                  |
      dt        j                         v st        j                  |	      rt        j                  |	      nddz  }dd
|iz  }|j3                  |       |st        j                  dfd|	f      t        j                  |      dt        j                         v st        j                  |	      rt        j                  |	      nddz  }dd|iz  }|j3                  |       t        j4                  |d      i z  }t        j                  d      dz   d|iz  }t!        t        j"                  |            d x}x}x}
x}x}} g }t7        t8              }|}|rt7        t:              }|}|sddt        j                         v st        j                  t6              rt        j                  t6              ndd t        j                         v st        j                  t8              rt        j                  t8              nd t        j                  |      d!z  }|j3                  |       |rd"dt        j                         v st        j                  t6              rt        j                  t6              ndd#t        j                         v st        j                  t:              rt        j                  t:              nd#t        j                        d$z  }|j3                  |       t        j4                  |d%      i z  }d&d'|iz  }t!        t        j"                  |            d x}x}x}}y )(Nutf-8encodingmain!=)z,%(py2)s
{%(py2)s = %(py0)s.name
} != %(py5)snodepy0py2py5u   guard 에 main() 금지
>assert %(py7)spy7argparseau   guard 에 argparse 금지)z.%(py2)s
{%(py2)s = %(py0)s.module
} != %(py5)s__name____main__not in)z%(py3)s not in %(py5)scond)py3r)   z%(py7)s)z%(py10)s not in %(py12)s)py10py12z%(py14)spy14   u,   guard 에 __main__ 엔트리포인트 금지z
>assert %(py17)spy17z%%(py5)s
{%(py5)s = %(py2)s(%(py3)s)
}callabler   )r(   r3   r)   z'%(py10)s
{%(py10)s = %(py7)s(%(py8)s)
}r
   )r+   py8r4   r   zassert %(py13)spy13)	GUARD_MOD	read_textastparsewalk
isinstanceFunctionDefAsyncFunctionDefname
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_saferepr_format_assertmsgAssertionError_format_explanationImportnames
ImportFrommoduleIfdumptestappend_format_boolopr9   r   r
   )srctreer%   @py_assert1@py_assert4@py_assert3@py_format6@py_format8r-   r2   @py_assert2@py_assert0@py_assert9@py_assert11@py_format13@py_format15@py_format16@py_format18@py_format11@py_format12@py_format14s                        r   'test_guard_module_is_import_only_no_cliri   =   s^   


w

/C99S>D dS__c.B.BCD99AA9&AAA9AAAAAA4AAA4AAA9AAAAAA(AAAAAAAAdCJJ'ZZ IvvHHv+HHHvHHHHHHqHHHqHHHvHHHHHH-HHHHHHHHIdCNN+;;I*I;*,III;*IIIIII4III4III;III*III.IIIIIIIIdCFF#88DII&D: :T) Z Zt-C   :T  I   v   &*  I &*   v Zt  I .8  v   @D  I @D   v    ?      M8()L)L)h7K.LL.LLLLLLL8LLL8LLLLLL(LLL(LLL)LLLL)LLLLLhLLLhLLLLLL7KLLL7KLLL.LLLLLLLLLLLLLLr   c                   t        dd |       }d}t        |z  }||k(  }|st        j                  d|fd||f      dt	        j
                         v st        j                  |      rt        j                  |      nddt	        j
                         v st        j                  t              rt        j                  t              ndt        j                  |      dz  }dd	|iz  }t        t        j                  |            d x}x}}y )
Nz!memory/events/task-2617.unit.jsontask_idr   ==z%(py0)s == (%(py2)s / %(py4)s)r   WSr'   r(   py4assert %(py7)sr+   
r   rp   rE   rF   rG   rH   rI   rJ   rL   rM   r   r   r[   @py_assert5rY   r\   r]   s          r   test_allowed_event_path_passrw   T   s    +T&	A 98888188888188888881888188888888888888888888r   c                   t        dd|       }d}t        |z  }||k(  }|st        j                  d|fd||f      dt	        j
                         v st        j                  |      rt        j                  |      nddt	        j
                         v st        j                  t              rt        j                  t              ndt        j                  |      dz  }d	d
|iz  }t        t        j                  |            d x}x}}y )Nz memory/reports/task-2617.unit.md	task-2617rk   rm   ro   r   rp   rq   rs   r+   rt   ru   s          r   test_allowed_report_path_passrz   [   s    *K	A 87777177777177777771777177777777777777777777r   bad)z/etc/passwdz2/home/jay/workspace/memory/events/task-2617.x.jsonz+memory/events/../../../etc/task-2617.x.jsonz)memory/events/../reports/task-2617.x.jsonzanu_v3/task-2617.evil.pyzconfig/task-2617.evil.yamlz memory/fixtures/task-2617.x.jsonz!memory/events/no_task_prefix.jsonzmemory/events/2617.jsonz"memory/events/sub/task-2617.x.json .zmemory/events/c                |    t        j                  t              5  t        |d |        d d d        y # 1 sw Y   y xY wNrk   pytestraisesr   r   )r   r{   s     r   test_reject_paths_fail_closedr   c   s1    & 
z	" ?S$v>? ? ?   2;c                |    t        j                  t              5  t        dd|        d d d        y # 1 sw Y   y xY w)Nzmemory/events/task-2610.x.jsonry   rk   r   r   s    r   test_taskid_mismatch_rejectedr   z   s4    	z	" 
,	

 
 
r   c                |    t        j                  t              5  t        d d |        d d d        y # 1 sw Y   y xY wr   r   r   s    r   test_none_rejectedr      s3    	z	" @T4?@ @ @r   c                   d}t         |z  }|j                         r|j                          	 t        |dd |       }g }||k(  }|}|r|j                  } |       }d}	||	k(  }
|
}|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      nddt        j                         v st        j                  |      rt        j                  |      nddz  }d	d
|iz  }|j                  |       |rt        j                  d
fd	f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                        t        j                  |      t        j                  |	      dz  }dd|iz  }|j                  |       t        j                  |d      i z  }dd|iz  }t        t        j                  |            d x}x}x}x}x}x}
}	t        |      }t!        j"                  t$              5  t        |dd |        d d d        t        |      }||k(  }|s9t        j                  d|fd||f      dt        j                         v st        j                  t              rt        j                  t              nddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }t        j&                  d      dz   d|iz  }t        t        j                  |            d x}}|j                         r|j                          y y # 1 sw Y   |xY w# |j                         r|j                          w w xY w)Nz(memory/events/task-2617._regr_probe.json	{"ok":1}
rk   rm   z%(py2)s == %(py4)sretfullr(   rr   %(py6)spy6zM%(py12)s
{%(py12)s = %(py10)s
{%(py10)s = %(py8)s.read_text
}()
} == %(py15)sr:   r4   r5   py15%(py17)sr8   r   assert %(py20)spy20TAMPER)z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py5)sr   before)r'   py1r3   r)   u0   overwrite 차단 후 원본 byte 불변이어야r*   r+   )rp   existsunlinkr
   r=   rE   rF   rG   rH   rI   rJ   rU   rV   rL   rM   r   r   r   r   rK   )r   relr   r   rY   r[   r_   r`   ra   @py_assert14@py_assert13@py_format5@py_format7rd   re   @py_format19@py_format21r   r^   rZ   r\   r]   s                         r   /test_atomic_write_allowed_and_overwrite_blockedr      sH   
4C8D{{}
"3d6R?sd{?t~~?~/?<?/<?????sd??????s???s??????d???d???????/<??????t???t???~???/???<??????????????d]]:& 	M hVL	MDzWzV#WWWzVWWWWWWtWWWtWWWWWWDWWWDWWWzWWWWWWVWWWVWWWW%WWWWWWW;;=KKM 		M 	M ;;=KKM s%   HO OEO OO #O?c           
     b   d}t        j                  t              5  t        |dd |        d d d        t        |z  }|j
                  } |       }| }|st        j                  d      dz   dt        j                         v st        j                  t              rt        j                  t              nddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }t        t        j                  |            d x}x}x}}d	}t        |z  }|j                  }d
} ||      }t        |      }	|	 }
|
sddt        j                         v st        j                  t              rt        j                  t              nddt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      t        j                  |      t        j                  |      t        j                  |	      dz  }t        t        j                  |            d x}x}x}x}x}x}	}
y # 1 sw Y   zxY w)Nz$anu_v3/task-2617.should_not_exist.pyPARTIALrk   u0   거부 시 어떤 파일도 생성되면 안 됨zS
>assert not %(py6)s
{%(py6)s = %(py4)s
{%(py4)s = (%(py0)s / %(py1)s).exists
}()
}rp   r   )r'   r   rr   r   r   z.*task-2617.tmp*xassert not %(py12)s
{%(py12)s = %(py0)s(%(py10)s
{%(py10)s = %(py6)s
{%(py6)s = (%(py1)s / %(py3)s).glob
}(%(py8)s)
})
}listr'   r   r3   r   r:   r4   r5   )r   r   r   r
   rp   r   rE   rK   rG   rH   rI   rJ   rL   rM   globr   )r   r   r^   r[   rv   @py_assert7r]   rZ   r`   ra   r   rh   s               r   *test_rejected_write_leaves_no_partial_filer      s   
0C	z	" JS)T&IJSV  V "V""V"VV$VVVVVVVVVVVVVVVVSVVVSVVV VVV"VVVVVV"=R(]=]((=);=();<=t<===========t===t======R===R===(===(===);===<===========	J Js   J$$J.c                j   | dz  }|j                          t        dz  }|j                         s|j                         r|j	                          t        j                  ||       	 t        j                  t              5  t        ddd|       ddd       d}||z  }|j                  } |       }| }|sdd	t        j                         v st        j                  |      rt        j                  |      nd	t        j                  |      t        j                  |      t        j                  |      d
z  }	t!        t        j"                  |	            dx}x}x}x}}|j                         r|j	                          yy# 1 sw Y   xY w# |j                         r|j	                          w w xY w)u  memory/events 하위에 symlink 디렉터리를 만들어 통과 시도 → 거부.

    single-segment 정책상 events 직하위 파일만 허용되므로, symlink
    component 경유 경로는 문법(중첩) 또는 O_NOFOLLOW 단계에서 거부된다.
    outsidez"memory/events/task-2617-symlinkdirz3memory/events/task-2617-symlinkdir/task-2617.x.jsonXNrk   ztask-2617.x.jsonQassert not %(py7)s
{%(py7)s = %(py5)s
{%(py5)s = (%(py0)s / %(py2)s).exists
}()
}victimr'   r(   r)   r+   )mkdirrp   
is_symlinkr   r   ossymlinkr   r   r   r
   rG   rH   rE   rI   rJ   rL   rM   )
tmp_pathr   r   linkrY   r[   rZ   @py_assert6@py_assert8@py_format9s
             r   "test_symlink_component_fail_closedr      sA    	!F
LLN44DDKKMJJvt]]:& 	 E		 09F//9/779799999999999F999F999/999799999999999??KKM 	 	 ??KKM s%   &F ?FCF FF #F2)z anu_v3/batch_hold_adjudicator.pyz%anu_v3/batch_dependency_classifier.pyz0anu_v3/pre_authorized_evidence_bundle_builder.pyr   c                ^   t         | z  j                  d      }d}||v }|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd	|iz  }t        t        j                  |            d x}}d
}||v }|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd	|iz  }t        t        j                  |            d x}}d}||v}|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd	|iz  }t        t        j                  |            d x}}d}||v}|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd	|iz  }t        t        j                  |            d x}}y )Nr   r    z=from anu_v3.cli_output_path_guard import atomic_guarded_writeinz%(py1)s in %(py3)srW   r   r3   assert %(py5)sr)   zatomic_guarded_write(zPath(a.output).write_textr0   )z%(py1)s not in %(py3)szPath(args.out).write_text)
rp   r=   rE   rF   rJ   rG   rH   rI   rL   rM   )r   rW   r_   r^   @py_format4r\   s         r   "test_cli_sinks_route_through_guardr      s   8



0CJQJcQQQQJcQQQJQQQQQQcQQQcQQQQQQQ")"c))))"c)))"))))))c)))c)))))))&1&c1111&c111&111111c111c1111111&1&c1111&c111&111111c111c1111111r   c           	        | dz  }|j                  dd       t        j                  t        j                  dddt        |      gt        t              dd	      }|j                  }d
}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }t        j                  |j                        dz   d|iz  }t!        t        j"                  |            dx}x}}|j$                  }|j&                  } |       }|st        j                  d      dz   dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      dz  }	t!        t        j"                  |	            dx}x}}d}t        |z  }|j(                  } |       }
|
 }|sddt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      t        j                  |
      dz  }t!        t        j"                  |            dx}x}x}x}
}y)u=   --output 없으면 stdout 으로 그대로 — 동작 불변.p.json{}r   r    -manu_v3.batch_hold_adjudicator--inputTcwdcapture_outputtextr   rm   )z2%(py2)s
{%(py2)s = %(py0)s.returncode
} == %(py5)srr&   r*   r+   Nu)   stdout 출력이 있어야(동작 불변)z^
>assert %(py6)s
{%(py6)s = %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.stdout
}.strip
}()
})r'   r(   rr   r   r   rp   r   )
write_text
subprocessrunsys
executablestrrp   
returncoderE   rF   rG   rH   rI   rJ   rK   stderrrL   rM   stdoutstripr   )r   payloadr   rY   rZ   r[   r\   r]   rv   r   r   r   r   s                r   4test_batch_hold_adjudicator_stdout_default_unchangedr      s   !Gtg.	>	CL	"GDt	A
 <<&1&<1&&&<1&&&&&&1&&&1&&&<&&&1&&&ahh&&&&&&&88H8>>H>HHHHHHHHHH1HHH1HHH8HHH>HHHHHHHHH'X'%%'%'''''''''''''''''X'''%'''''''''''r   c                z   | dz  }|j                  dd       | dz  }t        j                  t        j                  dddt        |      d	t        |      gt        t              d
d
      }|j                  }d}||k7  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }t        j                  d      dz   d|iz  }t        t        j                   |            dx}x}}|j"                  } |       }| }	|	st        j                  d      dz   dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }t        t        j                   |            dx}x}}	d}
|j$                  }|j&                  }||z   }|
|v }|st        j                  d|fd|
|f      t        j                  |
      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }dd|iz  }t        t        j                   |            dx}
x}x}x}}y)uQ   --output 이 비허용 경로면 fail-closed(비정상 종료·파일 미생성).r   r   r   r    zevil_out.jsonr   r   r   z--outputTr   r   r#   )z2%(py2)s
{%(py2)s = %(py0)s.returncode
} != %(py5)sr   r&   u'   비허용 경로 write 는 실패해야r*   r+   Nu   fail-closed: 파일 미생성zG
>assert not %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.exists
}()
}evilrq   zfail-closedr   )zV%(py1)s in (%(py5)s
{%(py5)s = %(py3)s.stderr
} + %(py8)s
{%(py8)s = %(py6)s.stdout
}))r   r3   r)   r   r:   zassert %(py11)spy11)r   r   r   r   r   r   rp   r   rE   rF   rG   rH   rI   rJ   rK   rL   rM   r   r   r   )r   r   r   r   rY   rZ   r[   r\   r]   rv   r_   r   r`   r^   @py_format10rg   s                   r   +test_cli_out_to_disallowed_path_fail_closedr      s   !Gtg.o%D	>	CL*c$i	9GDt	A
 <<G1G<1GGG<1GGGGGG1GGG1GGG<GGG1GGGGGGGGGGG{{={}=}==========t===t==={===}======1QXX11X01=01111=0111=111111Q111Q111X11111111111111111111r   zrel,shac                R   t         | z  }t        |      }||k(  }|st        j                  d|fd||f      dt	        j
                         v st        j                  t              rt        j                  t              nddt	        j
                         v st        j                  t               rt        j                  t               nddt	        j
                         v st        j                  |       rt        j                  |       ndt        j                  |      dt	        j
                         v st        j                  |      rt        j                  |      nddz  }t        j                  |  d      d	z   d
|iz  }t        t        j                  |            d x}x}}y )Nrm   )z<%(py5)s
{%(py5)s = %(py0)s((%(py1)s / %(py2)s))
} == %(py7)sr   rp   r   sha)r'   r   r(   r)   r+   u+    는 본 remediation 으로 불변이어야z
>assert %(py9)spy9)rp   r   rE   rF   rG   rH   rI   rJ   rK   rL   rM   )r   r   r[   rZ   r   r]   r   s          r   (test_stdout_only_modules_byte0_unchangedr      s    SU4>U>S UUU>SUUUUUU4UUU4UUUUUUUUUUUUUUUSUUUSUUU>UUUUUUSUUUSUUUUSE)T"UUUUUUUUr   c                @    | dz  }|dz  dz  j                  d       |S )NwsmemoryeventsT)parents)r   )r   r   s     r   _mk_sandbox_wsr      s*    	DB(]X$$T$2Ir   c           	     2	   ddl m} t        |       }|dz  dz  | dz  t        |      }t        j
                  dddfd
}|j                  |j                  d	|       t        j                  t              5 }t        d
dd|       ddd       d}j                  }t        |      }	||	v }
|
s
t        j                  d|
fd||	f      t        j                  |      dt!        j"                         v st        j$                  t              rt        j                  t              nddt!        j"                         v st        j$                  |      rt        j                  |      ndt        j                  |      t        j                  |	      dz  }dd|iz  }t'        t        j(                  |            dx}x}
x}}	d}|z  }|j*                  } |       }| }|sddt!        j"                         v st        j$                        rt        j                        ndt        j                  |      t        j                  |      t        j                  |      dz  }t'        t        j(                  |            dx}x}x}x}}d
}||z  }|j*                  } |       }| }|sddt!        j"                         v st        j$                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      dz  }t'        t        j(                  |            dx}x}x}x}}j,                  }
d} |
|      }t/        |      }| }|sddt!        j"                         v st        j$                  t.              rt        j                  t.              nddt!        j"                         v st        j$                        rt        j                        ndt        j                  |
      t        j                  |      t        j                  |      t        j                  |      dz  }t'        t        j(                  |            dx}
x}x}x}}y# 1 sw Y   xY w)u   containment 체크 ~ os.link 사이 부모 dir 가 ws 밖으로 rename 되면
    post-link final-inode bound 재검증이 이를 탐지해 final 을 즉시 unlink
    하고 fail-closed(SystemExit). (잔여 HIGH 재현·차단)r   Nr   r   
evil_movedcanonical_ws_root
src_dir_fd
dst_dir_fdc                   j                         r(t        j                  t              t                      | |||      S )Nr   )r   r   renamer   )rW   dstr   r   r   r   	real_links       r   toctou_linkz?test_dir_rename_after_check_toctou_blocked.<locals>.toctou_link  s8    ==?IIc&k3w<0

 	
r   r   z#memory/events/task-2617.toctou.json{"x":1}
rk   "   post-link final-inode bound 이탈r   )zK%(py1)s in %(py8)s
{%(py8)s = %(py3)s(%(py6)s
{%(py6)s = %(py4)s.value
})
}r   ei)r   r3   rr   r   r:   assert %(py10)sr4   ztask-2617.toctou.jsonr   r   r   r   .*tmp*hassert not %(py9)s
{%(py9)s = %(py0)s(%(py7)s
{%(py7)s = %(py3)s
{%(py3)s = %(py1)s.glob
}(%(py5)s)
})
}r   r'   r   r3   r)   r+   r   )anu_v3.cli_output_path_guardcli_output_path_guardr   r	   r   r   setattrr   r   
SystemExitr
   valuer   rE   rF   rJ   rG   rH   rI   rL   rM   r   r   r   )r   monkeypatchgr   polr   r   r_   rv   r   r^   r   rf   rY   r[   rZ   r   r   @py_assert10r   r   r   s                      @@@r   *test_dir_rename_after_check_toctou_blockedr     s    -		!B(]X%F%G

+CI,0T 
 
 fk2	z	" 
b1		

 0@rxx@3x=@/=@@@@/=@@@/@@@@@@3@@@3@@@@@@r@@@r@@@x@@@=@@@@@@@1;11;199;9;;;;;;;;;;;;;;;;;1;;;9;;;;;;;;;;;:D::D:BBDBDDDDDDDDDDDDDDDDD:DDDBDDDDDDDDDDDLL++L*+t*+++++++++++t+++t++++++G+++G+++L++++++*+++++++++++
 
s   ?RRc           
        t        |       }t        |      }t        ddd|      }|dz  }g }||k(  }|}|r|j                  } |       }	d}
|	|
k(  }|}|st	        j
                  d|fd||f      dt        j                         v st	        j                  |      rt	        j                  |      ndd	t        j                         v st	        j                  |      rt	        j                  |      nd	d
z  }dd|iz  }|j                  |       |rt	        j
                  dfd	
f      d	t        j                         v st	        j                  |      rt	        j                  |      nd	t	        j                        t	        j                  |	      t	        j                  |
      dz  }dd|iz  }|j                  |       t	        j                  |d      i z  }dd|iz  }t        t	        j                  |            dx}x}x}x}x}	x}}
d}||z  }|j                  }d} ||      }t        |      }	|	 }|sddt        j                         v st	        j                  t              rt	        j                  t              nddt        j                         v st	        j                  |      rt	        j                  |      ndt	        j                  |      t	        j                  |      t	        j                  |      t	        j                  |      t	        j                  |	      dz  }t        t	        j                  |            dx}x}x}x}x}x}	}y)u   rename 주입 없을 때(정상 경로): 변경 후에도 write 성공·final 이
    ws 안에 안착 — 기존 task-2617 통과 경로 동작 불변 입증.r   zmemory/events/task-2617.ok.jsonr   Nrk   rm   r   r   finalr   r   r   r   r   r   r8   r   r   r   memory/eventsr   r   r   r   r   )r   r	   r
   r=   rE   rF   rG   rH   rI   rJ   rU   rV   rL   rM   r   r   )r   r   r  r   r	  rY   r[   r_   r`   ra   r   r   r   r   rd   re   r   r   r^   rZ   rv   r   rh   s                          r   0test_post_link_check_passes_for_legitimate_writer  !  s    
	!B

+C
)	C 22E=3%<=EOO=O-==-=====3%======3===3======%===%=======-======E===E===O===-=================):R/):)//::/9:t9:::::::::::t:::t::::::R:::R:::/:::/::::::9:::::::::::r   c           	     	   ddl m} t        |       }|dz  dz  }t        |      }t        j
                  dddfd
}|j                  |j                  d|       t        j                  t              5 }t        d	d
d|       ddd       t        j                        }d}	|	|v }
|
st        j                  d|
fd|	|f      t        j                  |	      dt!        j"                         v st        j$                  |      rt        j                  |      nddz  }dd|iz  }t'        t        j(                  |            dx}	}
d}	|	|v }
|
st        j                  d|
fd|	|f      t        j                  |	      dt!        j"                         v st        j$                  |      rt        j                  |      nddz  }t        j*                  |      dz   d|iz  }t'        t        j(                  |            dx}	}
d}	|	|v }
|
st        j                  d|
fd|	|f      t        j                  |	      dt!        j"                         v st        j$                  |      rt        j                  |      nddz  }t        j*                  |      dz   d|iz  }t'        t        j(                  |            dx}	}
d}||z  }|j,                  } |       }| }|sddt!        j"                         v st        j$                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      dz  }t'        t        j(                  |            dx}x}x}x}}|j.                  }
d} |
|      }t1        |      }| }|sddt!        j"                         v st        j$                  t0              rt        j                  t0              nddt!        j"                         v st        j$                  |      rt        j                  |      ndt        j                  |
      t        j                  |      t        j                  |      t        j                  |      dz  }t'        t        j(                  |            dx}
x}x}x}}y# 1 sw Y   3xY w)u  잔여 HIGH 재현: ``os.link()`` 직후·재오픈 직전 fname 이 *다른
    in-ws inode* 로 치환되는 reopen-by-name substitution race.

    치환된 파일은 ws 안(events 직하위)이라 realpath containment 만으로는
    통과한다 — 그러나 post-link 재검증이 inode-bound(link 가 만든 temp
    inode 의 st_dev/st_ino 와 동치) 이므로 inode 불일치를 탐지해 final
    을 즉시 unlink 하고 fail-closed(SystemExit). containment=True 인데도
    inode_bound=False 로 차단됨을 입증한다.r   Nr   r   r   r   c                   | |||      }t        j                  ||       t         j                  t         j                  z  t         j                  z  }t        t         d      r|t         j                  z  }t        j                  ||d|      }t        j                  |d       t        j                  |       |S )Nr   )dir_fd
O_NOFOLLOWi  s   DECOY-DIFFERENT-INODE
)
r   r   O_WRONLYO_CREATO_EXCLhasattrr  openwriteclose)rW   r   r   r   rvdflagsdecoy_fdr   s          r   substituting_linkzHtest_reopen_by_name_substitution_race_blocked.<locals>.substituting_linkC  s    
 

 			#j)rzz)BII52|$bmm#F773jA
56
	r   r   z"memory/events/task-2617.subst.jsonr   rk   r   r   r   msgr   r   r)   zinode_bound=Falsez
>assert %(py5)szcontainment=Trueztask-2617.subst.jsonr   r   r   r   r   r   )r   r   r   r	   r   r   r   r   r   r  r
   r   r  rE   rF   rJ   rG   rH   rI   rL   rM   rK   r   r   r   )r   r  r  r   r   r  r  r   r  r_   r^   r   r\   rY   r[   rZ   r   r   r   r  rf   r   s                        @r   -test_reopen_by_name_substitution_race_blockedr  2  s    -		!B(]X%F

+CI264 " f&78	z	" 
b0		

 bhh-C/6/36666/3666/666666366636666666*#%***#*********#***#****s******)$)))))))))))))))))))c))))))/9//9/779799999999999999999/999799999999999KK**K)*t)***********t***t******F***F***K******)***********
 
s   6R77Sc                    t        t              } | j                  }t        |      }d}||k(  }|s
t	        j
                  d|fd||f      dt        j                         v st	        j                  t              rt	        j                  t              nddt        j                         v st	        j                  |       rt	        j                  |       ndt	        j                  |      t	        j                  |      t	        j                  |      dz  }dd|iz  }t        t	        j                  |            d x}x}x}}| j                  }t        |      }d	d
h}||k(  }|s
t	        j
                  d|fd||f      dt        j                         v st	        j                  t              rt	        j                  t              nddt        j                         v st	        j                  |       rt	        j                  |       ndt	        j                  |      t	        j                  |      t	        j                  |      dz  }dd|iz  }t        t	        j                  |            d x}x}x}}| j                  }d}||u }|st	        j
                  d|fd||f      dt        j                         v st	        j                  |       rt	        j                  |       ndt	        j                  |      t	        j                  |      dz  }	dd|	iz  }
t        t	        j                  |
            d x}x}}| j                  }d}||u }|st	        j
                  d|fd||f      dt        j                         v st	        j                  |       rt	        j                  |       ndt	        j                  |      t	        j                  |      dz  }	dd|	iz  }
t        t	        j                  |
            d x}x}}y )Nr   rm   )zW%(py5)s
{%(py5)s = %(py0)s(%(py3)s
{%(py3)s = %(py1)s.canonical_ws_root
})
} == %(py8)sr   r  )r'   r   r3   r)   r:   r   r4   r
  zmemory/reports)zS%(py5)s
{%(py5)s = %(py0)s(%(py3)s
{%(py3)s = %(py1)s.allowed_roots
})
} == %(py8)ssetT)is)z?%(py2)s
{%(py2)s = %(py0)s.task_id_prefix_required
} is %(py5)sr&   rs   r+   )zI%(py2)s
{%(py2)s = %(py0)s.single_segment_under_allowed_root
} is %(py5)s)r   r   r   r   rE   rF   rG   rH   rI   rJ   rL   rM   allowed_rootsr  task_id_prefix_required!single_segment_under_allowed_root)r  r^   rZ   r   r   r   rf   rY   r[   r\   r]   s              r   (test_guard_policy_file_present_and_validr#  h  sM   
f
C$$>3$%>)>>%)>>>>>%)>>>>>>>3>>>3>>>>>>s>>>s>>>$>>>%>>>)>>>>>>>>  H3 !Ho7G%HH!%HHHHH!%HHHHHHH3HHH3HHHHHHsHHHsHHH HHH!HHH%HHHHHHHH&&.$.&$....&$......3...3...&...$.......008D80D88880D888888388838880888D8888888r   )r   r   returnr   )r$  r	   )r$  r   )8__doc__
__future__r   builtinsrG   _pytest.assertion.rewrite	assertionrewriterE   r>   r   r   r   r   pathlibr   r   rp   r<   r   pathinsertr   r   r   r	   r
   r   r   STDOUT_ONLY_BASELINEr   fixturer   ri   rw   rz   markparametrizer   r   r   r   r   r   TARGET_SINKSr   r   r   r   itemsr   r   r  r  r  r#  r   r   r   <module>r4     s   #   
  	  
  	
 M66		h6	6 3r7   	KJJ 6  
M.98 	$?%$?

@$>6 -2 .2(2  D)=)C)C)E$FGV HV
#,L;"3+l9r   