
    it                    >   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mZmZ ddlmZ ddlZ ee      j%                         j&                  d   Zedz  Z ee      ej.                  vr"ej.                  j1                  d ee             ddlZddlZej:                  d9d       Zej:                  d9d	       Zej:                  d
        Z  ee      jB                  jB                  dz  dz  dz  Z"ejF                  jI                  dg d      	 	 	 	 d:d       Z%d;dZ&ejF                  jI                  dg d      	 	 	 	 d<d       Z'ejF                  jI                  dg d      	 	 	 	 	 	 d=d       Z(ejF                  jI                  dg d      	 	 	 	 	 	 	 	 d>d       Z)ejF                  jI                  ddddidfd d!d"idfd#ddid$fd%ddid&fd'ddd(dfg      	 	 	 	 	 	 	 	 d?d)       Z*d* Z+d@d+Z,d@d,Z-d- Z.d. Z/d/ Z0d0 Z1d1 Z2d2 Z3d3 Z4d4 Z5d5 Z6d6 Z7d7 Z8d8 Z9y)AuX  
test_lifecycle_penetration.py — task-2469 Phase D Penetration Tests

회장 명시: "기능 추가가 아니라 우회 불가능성 증명. 자동화된 방어 검증 체계를 남겨라."

각 시나리오는:
  - 공격 의도 (docstring)
  - 공격 input 박제 (fixture)
  - Guard 호출
  - assert r.ok is False (또는 high>=1)
  - memory/orchestration-audit/penetration-test-2469.jsonl append

모든 6+ 시나리오 통과 = 우회 시도 0건 성공 = task-2468 Guard 우회 불가능.

Phase 2 (mandatory A-F): 토르 작성 (task-2469)
Phase 3 (optional G-M): 헤임달 작성 (기존)
    )annotationsN)datetimetimezone)Path   scriptsc                0    | dz  }|j                          |S )Neventsmkdirtmp_pathds     ?/home/jay/workspace/tests/taskctl/test_lifecycle_penetration.py
tmp_eventsr   +   s    8AGGIH    c                0    | dz  }|j                          |S )Nevidencer   r   s     r   tmp_evidencer   2   s    :AGGIHr   c              #  L   K   g 	 	 	 	 	 	 	 	 	 	 	 	 d fd}| t         dz  dz  dz  }|j                  j                  dd       |j                  dd	      5 }D ]+  }|j	                  t        j                  |d
      dz          - 	 ddd       y# 1 sw Y   yxY ww)u  audit jsonl emit. 테스트 종료 시 penetration-test-2469.jsonl에 append.

    사용법: audit_emit(scenario, task_id, attack_intent, guard_called, attack_blocked, blocking_reasons)

    attack_blocked: 공격이 차단되었는가? (True = 차단 성공 = 정상)
      - Guard r.ok 기반 호출: `r.ok is False` 전달 (r.ok=False면 차단됨)
      - 직접 boolean: True = 차단됨, False = 우회 성공 (테스트 FAIL 조건)

    production admin-override.jsonl 변조 금지 — 전용 audit 파일에만 append.
    c                    j                  | |||t        |      |rt        |      ng t        j                  t
        j                        j                         j                  j                  d       y )N)scenariotask_idattack_intentguard_calledblockedblocking_reasonsts	test_name)
appendboollistr   nowr   utc	isoformatnodename)r   r   r   r   attack_blockedr   entriesrequests         r   _emitzaudit_emit.<locals>._emitG   s^     	$"!. ,/>ND)9$:TVll8<<0::<$\\..		
r   memoryzorchestration-auditzpenetration-test-2469.jsonlT)parentsexist_okautf-8encodingF)ensure_ascii
N)r   strr   r5   r   r5   r   r5   r(   r!   returnNone)
_REPO_ROOTparentr   openwritejsondumps)r*   r+   
audit_pathfentryr)   s   `    @r   
audit_emitrA   9   s      G


 
 	

 
 

* K h&)>>A^^JD48	w	/ B1 	BEGGDJJu59D@A	BB B Bs   AB$1B	B$B!B$fixtures	task-2469gemini_reviewsmarker_name)zg3-failz	g3-failedg3_fail	g3_failedc                   d| }| | d| z  j                  t        j                  |dgd      d       t        j                  ||       }|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  }t        j                  d| d|j                                dz   d|iz  }	t        t        j                  |	            dx}x}}|j                   }
t#        |
      }d}||kD  }|s1t        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  }t        j                  d|j                                dz   d|iz  }t        t        j                  |            dx}
x}x}} |d| |d| dd|j
                  du |j                          y)u6  공격 의도: G3 verifier가 fail marker를 박제했음에도 .done을 강제 발행하려 시도.
    공격 방법: marker 이름을 4가지 변형으로 위장 (g3-fail / g3-failed / g3_fail / g3_failed).
    기대 차단: lifecycle_guards.check_g3_fail_blocks_done — 4가지 변형 모두 인식.
    ztask-pentest-A-.pentest_attackr   fail_reasonsr0   r1   
events_dirFisz*%(py2)s
{%(py2)s = %(py0)s.ok
} is %(py5)srpy0py2py5u   공격 우회 성공! marker=u4    — Guard가 fail marker를 인식하지 못함. r=
>assert %(py7)spy7Nr   )>)zM%(py5)s
{%(py5)s = %(py0)s(%(py3)s
{%(py3)s = %(py1)s.blocking
})
} > %(py8)slen)rT   py1py3rV   py8u!   blocking 리스트 비어있음: z
>assert %(py10)spy10zA-u&   g3-fail marker 위장 시도 (variant=)check_g3_fail_blocks_done)
write_textr<   r=   lgr`   ok
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_saferepr_format_assertmsgas_dictAssertionError_format_explanationblockingrZ   )r   rE   rA   r   rR   @py_assert1@py_assert4@py_assert3@py_format6@py_format8@py_assert2@py_assert7@py_assert6@py_format9@py_format11s                  r   6test_A_done_gfail_concurrent_block_all_marker_variantsry   p   s     }-GWIQ{m,,88

w9I8JKL 9  	$$WDA44 5 45=  45                      (} 5YY[M	     zzQ3z?QQQ?QQQQ?QQQQQQQ3QQQ3QQQQQQqQQQqQQQzQQQ?QQQQQQQ"CAIIK= QQQQQQQQ
[M
0Q?#		

r   c                X   d}| | dz  j                  t        j                  |dd      d       | | dz  j                  t        j                  |dgd	      d       t        j                  || 
      }|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  }t        j                  d|j                                dz   d|iz  }t        t        j                  |            dx}x}}g }d}	|j                   }
|
j"                  } |       }|	|v }|}|sd}|j                   }||v }|}|st        j                  d|fd|	|f      t        j                  |	      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%                  |       |st        j                  dfdf      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }dd|iz  }|j%                  |       t        j&                  |d      i z  }t        j                  d |j                          d!z   d"|iz  }t        t        j                  |            dx}x}x}	x}x}
x}x}x}x}} |d#|d$d%|j
                  du |j(                         y)&u   공격 의도: .done 파일을 직접 작성한 뒤 .g3-fail이 동시 존재.
    공격 방법: 두 파일을 동시에 배치하여 conflict 상태 강제.
    기대 차단: check_done_fail_conflict — done+fail 동시 = CONFLICT → ok=False.
    ztask-pentest-A2z.donez
2026-05-06)r   r   r0   r1   z.g3-failforced_by_attackerrK   rM   FrO   rQ   rR   rS   uO   공격 우회 성공! .done + .g3-fail 동시 존재가 차단되지 않음. r=rW   rX   Nconflictu   동시)in)zb%(py3)s in %(py11)s
{%(py11)s = %(py9)s
{%(py9)s = %(py7)s
{%(py7)s = %(py5)s.reason
}.lower
}()
})r\   rV   rX   py9py11z%(py13)spy13)z2%(py16)s in %(py20)s
{%(py20)s = %(py18)s.reason
})py16py18py20z%(py22)spy22   u,   reason에 conflict/동시 키워드 없음: z
>assert %(py25)spy25A2u5   .done 직접 쓰기 + .g3-fail 동시 존재 conflictcheck_done_fail_conflict)ra   r<   r=   rb   r   rc   rd   re   rf   rg   rh   ri   rj   rk   rl   rm   reasonlowerr    _format_booloprn   )r   rA   r   rR   ro   rp   rq   rr   rs   rt   rv   @py_assert8@py_assert10@py_assert0@py_assert15@py_assert19@py_assert17@py_format12@py_format14@py_format21@py_format23@py_format24@py_format26s                          r   #test_A2_done_force_write_with_gfailr      sQ   
  GWIU##//

wl;<w 0  WIX&&22

w9M8NOP 3  	##G
CA44 5 45=  45                      ZZ[ZcZcZeYfg    :   ) :)) X  X-A   :)                  "    (    *     X    .6      :;    :;    :B        7qxxjA       ?"		

r   zfixture_name,min_high))zhigh_heading_variants.md   )zhigh_inline_labels.md   )zhigh_emoji_variants.mdr   )zhigh_severity_priority.mdr   )zhigh_keywords.mdr   c                   t         | z  }|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}}|j                  d      }t        j                  |      }|d   }	|	|k\  }
|
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|  d|d    d| d|j                  dg              dz   d|iz  }t        t        j                  |            dx}	}
 |d| d|  d|d   |k\  d|d    d| g       y)uY  공격 의도: Gemini High/Critical severity를 5가지 패턴 계열로 위장.
    공격 방법: heading 변형 / inline label / emoji / severity-priority / keyword.
    기대 차단: count_severities — 모든 변형에서 high>=min_high 검출.
    각 fixture file에 해당 패턴이 충분히(min_high 이상) 포함되어야 함.
    u   Fixture 파일 없음: C
>assert %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.exists
}()
}fixture_pathrT   rU   py4Nr0   r1   high>=)z%(py1)s >= %(py3)smin_high)r[   r\   u   공격 우회 성공! u
    → high=z < u1    (Guard가 패턴을 인식하지 못함). hits: 	high_hitsz
>assert %(py5)srV   Bz5pattern group high hiding: count_severitieshigh=zmin_required=)_FIXTURES_DIRexistsrd   rj   rf   rg   rh   ri   rl   rm   	read_textgspr   re   get)fixture_namer   rA   r   ro   rq   @py_format5bodysvr   rt   @py_format4rr   s                r   )test_B_gemini_high_hidden_5pattern_groupsr      s   $ !</LJ J JJ$;L>"JJJJJJJ<JJJ<JJJJJJ JJJJJJ!!7!3D			d	#Bf: :!  :          "    "    !jFCz R;;=66+r;R:S	U     
&|n5
6
hF	xj9:r   zfake_approver,expected_block))z
random-botT)attackerT)ztaskctl-gate-fakeT)zanu-verifier-2T)JonghyukJeonTc                   |}	 | dz  }|j                  t        j                  ddddddgdgd      d	       t        j                  ||
      }|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  }
t        j                  d|d|j                                dz   d|
iz  }t        t        j                  |            d x}x}	} |ddd| d|j
                  du |j                          y )Nzallowed_approvers.jsontaskctl-gatesystem)logintypezanu-verifierr   	approversmanual_loginsr0   r1   allowlist_pathFrO   rQ   rR   rS   uE   공격 우회 성공! approver spoofing 차단 실패: fake_approver=. r=rW   rX   Czapprover-testzapprover spoofing: check_approver_identity)ra   r<   r=   rb   r   rc   rd   re   rf   rg   rh   ri   rj   rk   rl   rm   rn   )r   fake_approverexpected_blockrA   _cfgrR   ro   rp   rq   rr   rs   s               r   test_C_approver_spoofingr      sv    	A
 -
-CNN

 -h?,h? #1!1	
    	""=EA44 5 45=  45                      PP]O` aYY[M	     
m_-!		

r   z9scenario,fake_sha,fake_base,origin_returns,expected_block))	empty_sha mainabc123T)null_shaNr   r   T)sha_mismatchr   r   DIFFERENT_SHAT)non_main_base_mismatchr   develop	WRONG_SHATc                   |}fd}fd}	| j                  t        d|       | j                  t        d|	       t        j                  dd      }
|
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  }t	        j                  d| ddd|
j                                dz   d|iz  }t        t	        j                  |            dx}x}} |d|d| dddd|
j                  du |
j                         y)uR  공격 의도: 실제 머지된 commit과 다른 SHA로 done 발행하여 SHA 검증 우회.
    공격 방법: empty SHA / null SHA / mismatch SHA / non-main base mismatch.
    기대 차단: check_merge_commit_sha — 4가지 케이스 모두 ok=False.
    monkeypatch로 외부 API 호출 mock — production gh api 호출 금지.
    c                     di dS )NT)merge_commit_shabase_refrc   raw )_args_kwargs	fake_basefake_shas     r   _mock_fetch_prz8test_D_merge_sha_mismatch_attack.<locals>._mock_fetch_pr"  s     (!	
 	
r   c                    | k(  rS dS )NBAD_SHAr   )baser   r   origin_returnss     r   _mock_fetch_originz<test_D_merge_sha_mismatch_attack.<locals>._mock_fetch_origin*  s    !%!2~A	Ar   fetch_pr_merge_shafetch_origin_head_sha!   z
dummy/repo)repoFrO   rQ   rR   rS   u9   공격 우회 성공! SHA 공격 차단 실패: scenario=z. fake_sha=z	, origin=r   rW   rX   NDzmerge SHA attack: z (sha=r_   check_merge_commit_sha)setattrrb   r   rc   rd   re   rf   rg   rh   ri   rj   rk   rl   rm   rn   )monkeypatchr   r   r   r   r   rA   r   r   r   rR   ro   rp   rq   rr   rs   s     ```           r    test_D_merge_sha_mismatch_attackr   
  sm   . 	A
B 0.A35GH
!!"<8A44 5 45=  45                      DH: N<y(:$qyy{m	M     
XJfXL	.ASSTU 		

r   zscenario,env,audit_setupbypass_no_auditTASKCTL_BYPASS1emptyoverride_no_auditTASKCTL_PR_AUTHOR_OVERRIDEzfake-botbypass_audit_missing_task
other_taskbypass_audit_deleteddeleteproduction_bypass)r   
PRODUCTIONc                L   | dz  }|dk(  r|j                          n:|dk(  r/|j                  t        j                  ddddd      d	z   d
       n|dk(  r	 d| }|j	                  d      dk(  }t        j                  ||||      }|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  }t        j                  d| d|d|d|j                                dz   d|iz  }t!        t        j"                  |            dx}	x}}
 |d|d| d|j                  du |j$                         y) u_  공격 의도: TASKCTL_BYPASS=1 또는 TASKCTL_PR_AUTHOR_OVERRIDE를 사용하면서 audit 누락.
    공격 방법: audit 빈 파일 / 다른 task entry / 파일 자체 삭제 / production 환경.
    기대 차단: check_bypass_audit — 5가지 케이스 모두 ok=False.
    production admin-override.jsonl 변조 금지 — tmp_path 사용.
    admin-override.jsonlr   r   ztask-other-unrelatedz legitimate bypass for other taskz2026-05-01T00:00:00+00:00admin)r   r   r   actorr4   r0   r1   r   ztask-pentest-E-r   r   )envr>   
productionFrO   rQ   rR   rS   uB   공격 우회 성공! audit 누락 bypass 차단 실패: scenario=z. env=z, audit_setup=r   rW   rX   NEzadmin override no audit: check_bypass_audit)touchra   r<   r=   r   rb   r   rc   rd   re   rf   rg   rh   ri   rj   rk   rl   rm   rn   )r   r   r   audit_setuprA   r>   r   r   rR   ro   rp   rq   rr   rs   s                 r   test_E_admin_override_no_auditr   A  s   $ 22Jg		$JJ5@5$	   	 	
 
	 z*G&#-J
		A 44 5 45=  45                      MXJ Wg^K?$qyy{m	E     
#H:.		

r   c           
        t        t              j                  j                  dz  dz  dz  dz  }|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}}|j                  d
      }t        j                  |      }|d   }d}||k\  }|st	        j                  d|fd||f      t	        j                  |      t	        j                  |      dz  }t	        j
                  d|       dz   d|iz  }	t        t	        j                  |	            d	x}x}} | dddd|d   dk\  d|d    dg       y	)ux  공격 의도: 보고서 메타/summary에 'PASS'/'high=0'이라 적었지만 본문에 High 키워드 산재.
    공격 방법: tampered_report_pass_with_high.md — 메타는 PASS이나 본문에 High 패턴 다수.
    기대 차단: count_severities 본문 재검증 → high>=1 검출.
    이것이 task-2467+3 'silent corruption' 사고의 정확한 재현이다.
    rB   rC   rD   z!tampered_report_pass_with_high.mdu   F1 fixture 없음: r   fixturer   Nr0   r1   r   r   r   )z%(py1)s >= %(py4)s)r[   r   uX   공격 우회 성공! 본문 high 키워드 위장이 count_severities를 통과함. sv=z
>assert %(py6)spy6F1zreport-body-tamperz@report metadata says PASS/high=0 but body contains High keywordsr   r   body_high_detected)r   __file__r9   r   rd   rj   rf   rg   rh   ri   rl   rm   r   r   r   re   )
rA   r  ro   rq   r   r   r   r   rt   @py_format7s
             r   )test_F1_report_body_pass_but_high_in_bodyr    s    	X$$
	
	 	 .		.  >><><<<27)<<<<<<<7<<<7<<<><<<<<<<<<g.D			d	#Bf:  :?  :            ccebfg     J
6
aF	34r   c           	        | dz  }|j                          d}||z  }|j                          |dz  j                  t        j                  ddddd      d	
       t	        j
                  |dd|      }|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  }	t        j                  d|j                                dz   d|	iz  }
t        t        j                   |
            dx}x}} |d|dd|j                  du |j"                         y)u  공격 의도: 다른 task의 g3-pass.json을 현재 task에 재사용 (stale task_id).
    공격 방법: evidence에 task_id="task-2467+3" (다른 task)를 심어 PASS 위장.
    기대 차단: check_done_g3_pass_evidence — task_id 불일치 검출 → ok=False.
    r   ztask-pentest-F2g3-pass.jsonztask-2467+3PASSr   (abc123def456abc123def456abc123def456abc1r   result	pr_numbershar0   r1   c   r  head_shaevidence_dirFrO   rQ   rR   rS   uQ   공격 우회 성공! stale task_id evidence 재사용이 차단되지 않음. r=rW   rX   NF2u>   stale task_id evidence reuse (task-2467+3 → task-pentest-F2)check_done_g3_pass_evidencer   ra   r<   r=   rb   r  rc   rd   re   rf   rg   rh   ri   rj   rk   rl   rm   rn   r   rA   ev_dirr   task_dirrR   ro   rp   rq   rr   rs   s              r   test_F2_stale_task_id_evidencer    sz   
 
"F
LLNGHNN**

( A		
  + 
 	&&;		A 44 5 45=  45                      \\]\e\e\g[hi     H%		

r   c           	        | dz  }|j                          d}||z  }|j                          |dz  j                  t        j                  |dddd      d	       t	        j
                  |dd
|      }|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  }	t        j                  d|j                                dz   d|	iz  }
t        t        j                   |
            dx}x}} |d|dd|j                  du |j"                         y)u
  공격 의도: force-push 이후 이전 SHA의 PASS evidence를 재사용 (stale SHA).
    공격 방법: evidence의 sha="DEADBEEF..." (old SHA)이나 실제 HEAD는 NEW_SHA.
    기대 차단: check_done_g3_pass_evidence — sha 불일치 검출 → ok=False.
    r   ztask-pentest-F3r
  r  r  (DEADBEEF00000000000000000000000000000000r  r0   r1   )NEW_SHA_AFTER_FORCE_PUSH_0000000000000000r  FrO   rQ   rR   rS   uM   공격 우회 성공! stale SHA evidence 재사용이 차단되지 않음. r=rW   rX   NF3uD   stale SHA evidence reuse (force-push scenario: DEADBEEF → NEW_SHA)r  r  r  s              r   test_F3_stale_sha_evidencer     sz   
 
"F
LLNGHNN**

" A		
  + 
 	&&<		A 44 5 45=  45                      XXYXaXaXcWde     N%		

r   c                f   | dz  }|j                  t        j                  dgdgd      d       t        j                  d|      }|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}} |dddd|j
                  d	u |j                         y)uZ  공격 의도: allowed_bot_accounts.json에 비허용 attacker-bot 추가.
    공격 방법: fixture 임시 변조본을 만들어 allowlist_path로 주입.
    기대 차단: check_bot_author_allowlist — production allowlist만 신뢰. 변조본도 attacker-bot이 추가되었지만, _match_bot_author 함수는 패턴 정확히 매칭.
    zallowed_bot_accounts.jsonzjeon-jonghyuk-taskctl-bot[bot]z[bot]exactwildcard_suffixr0   r1   zattacker-humanr   FrO   rQ   rR   rS   assert %(py7)srX   NGzbot-allowlist-testu   비허용 author 차단 검증check_bot_author_allowlist)ra   r<   r=   rb   r'  rc   rd   re   rf   rg   rh   ri   rl   rm   rn   	r   rA   r   rR   ro   rp   rq   rr   rs   s	            r   "test_G_allowed_bot_accounts_tamperr)    s     0
0CNN4::23#9    
 	%%&6sKA44545=451145s(*J+QTTU]AJJHr   c                   | dz  }|j                  t        j                  g g d      d       t        j                  d|      }|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  }t        j                  d      dz   d|iz  }t        t        j                  |            dx}x}} |dddd|j
                  du |j                         y)u   공격 의도: allowlist 파일을 빈 list로 변조하여 fail-open 유발 시도.
    기대 차단: 빈 allowlist → fail-closed (모든 author 차단).
    zempty_allowlist.jsonr"  r0   r1   zany-bot[bot]r   FrO   rQ   rR   rS   u7   빈 allowlist 시 fail-closed 안 됨 → 우회 성공rW   rX   NG2zempty-allowlistu    빈 allowlist fail-closed 검증r'  )ra   r<   r=   rb   r'  rc   rd   re   rf   rg   rh   ri   rj   rl   rm   rn   r(  s	            r   'test_G2_bot_allowlist_empty_fail_closedr,    s     +
+CNN4::rBCgNV
%%nSIA44S5S45=SSS45SSSSSS1SSS1SSS4SSS5SSSSSSSSSSSt&(J+QTTU]AJJHr   c                b   | dz  }|j                  t        j                  g g d      d       t        j                  d|      }|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}} |dddd|j
                  du |j                         y)u   공격 의도: allowed_approvers.json을 빈 list로 변조.
    기대 차단: 빈 list → fail-closed (모든 approver 차단).
    zempty_approvers.jsonr   r0   r1   zany-botr   FrO   rQ   rR   rS   r%  rX   NHzempty-approversu    빈 approvers fail-closed 검증r   )ra   r<   r=   rb   r   rc   rd   re   rf   rg   rh   ri   rl   rm   rn   r(  s	            r   *test_H_allowed_approvers_empty_fail_closedr/    s     +
+CNN4::BDEPWNX
""9SAA44545=451145s%'I(!$$%-Er   c                   | dz  }t        j                  d|      }|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}} |dddd|j                  du |j                         y)ur   공격 의도: allowed_approvers.json 파일 자체 삭제.
    기대 차단: 파일 부재 → fail-closed.
    znonexistent.jsonr   r   FrO   rQ   rR   rS   r%  rX   NH2zmissing-approversu#   approvers 파일 부재 fail-closedr   )rb   r   rc   rd   re   rf   rg   rh   ri   rl   rm   rn   r(  s	            r   &test_H2_allowed_approvers_missing_filer2    s     '
'C
"">#FA44545=451145t(*O(!$$%-Er   c                   | dz  }t        j                  dd|       |j                  dd       t        j                  ddd	i|
      }|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  }t        j                  d      dz   d|iz  }t        t        j                  |            dx}x}} |dddd|j                  du |j                         y)u  공격 의도: admin-override.jsonl을 truncate하여 과거 audit 흔적 제거.
    공격 방법:
      1. 정상 audit 기록
      2. 파일 truncate
      3. 새 audit 기록
      4. check_bypass_audit 호출 → 과거 task_id의 audit이 사라졌는지 검증.
    기대 차단: check_bypass_audit는 현재 task_id 기준으로 검증. truncate 후 task_id entry 부재 → fail.
    r   ztask-pentest-I-historyztest reason)r>   r   r0   r1   r   r   )r   r>   FrO   rQ   rR   rS   u'   truncate 후 audit 검증 우회 성공rW   rX   NIu#   audit truncate (append-only 위반)r   )rb   append_admin_override_auditra   r   rc   rd   re   rf   rg   rh   ri   rj   rl   rm   rn   )	r   rA   r>   rR   ro   rp   rq   rr   rs   s	            r   &test_I_admin_override_overwrite_attackr6  -  s     22J""#;]Wab"w/
6$4c#:*4	6A 44C5C45=CCC45CCCCCC1CCC1CCC4CCC5CCCCCCCCCCCs,.S#QTTU]AJJ@r   c                   | dz  }|j                          |dz  }|j                          | dz  dz  }|j                  j                          |j                  t        j                  dddd      d	       	 |d
z  j                  |       d}|rt        j                  ddd|      }|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  }
t        j                   d      dz   d|
iz  }t#        t        j$                  |            dx}x}	} |dddd|j                  du |j&                         yt)        j*                  d       y# t        $ r d}Y Aw xY w)uV  공격 의도: events/ 외부에 evidence를 만들고 symlink로 우회.
    공격 방법: g3-pass.json을 evidence_dir 외부 경로로 symlink → 경로 검증 우회 시도.
    기대 차단: check_done_g3_pass_evidence는 evidence_dir/<task_id>/ 안에서만 lookup. 외부 파일은 무시 → 결국 evidence 없음으로 fail.
    r   ztask-pentest-Joutsidezfake_pass.jsonr  abcr   r  r  r0   r1   r
  TFr  r   r  rO   rQ   rR   rS   u4   symlink + sha mismatch 차단 못함 = 우회 성공rW   rX   NJz"symlink evidence with sha mismatchr  u   symlink 권한 없음)r   r9   ra   r<   r=   
symlink_toOSErrorrb   r  rc   rd   re   rf   rg   rh   ri   rj   rl   rm   rn   pytestskip)r   rA   r  r  r8  
symlink_okrR   ro   rp   rq   rr   rs   s               r   test_J_symlink_evidence_outsiderA  F  sy   
 
"F
LLN((HNN"%55GNNtzz.>&Y^"_` '  )	N	"..w7
  **+;r5D9?A ttTuTtu}TTTtuTTTTTTqTTTqTTTtTTTuTTTTTTTTTTT3(*N0!$$%-	M 	+,  
s   8G GGc                   | dz  }|j                          | dz  }|j                          |dz  j                  t        j                  dddd      d	       t	        j
                  dd
d|      }|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  }t        j                  d|j                         dz   d|iz  }	t        t        j                   |	            d
x}x}} |dddd|j                  du |j"                         y
)u}  공격 의도: task_id에 '../'를 포함시켜 path traversal + sha 위조 시도.
    시나리오: 외부 danger/ 디렉토리에 g3-pass.json을 만들어 evidence_dir/../danger/로 접근.
    task_id를 "../danger"로 설정해 경로 탈출을 시도하더라도, head_sha를 다르게 지정하면 sha mismatch로 차단.
    기대 차단: sha 불일치 → ok=False.
    r   dangerr
  z	../dangerr  danger_sha_999r:  r0   r1   NEXPECTED_SHAr  FrO   rQ   rR   rS   uI   path traversal + sha mismatch 시 차단 실패 — guard returned PASS: rW   rX   J2z%task_id path traversal + sha mismatchr  )r   ra   r<   r=   rb   r  rc   rd   re   rf   rg   rh   ri   rj   r   rl   rm   rn   )
r   rA   r  
danger_dirrR   ro   rp   rq   rr   rs   s
             r   test_J2_path_traversal_task_idrH  h  se    
"F
LLNH$J. ,,TZZ&9I9 . - 
 	&&{d^5;	=A 44 5 45=  45                     	  !z	+     t["IKhttu}ajj*r   c                T   | dz  }|j                          | dz  dz  }|j                  d       |dz  j                  dd	       t        j                  d
|      }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                  |      dz  }t        j                  d      dz   d|iz  }	t        t        j                  |	            dx}x}} |dd
ddddg       |dz  j                  dd	       t        j                  d
|      }
|
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}} |d!d
d"d#|
j                  du |
j                          y)$u  공격 의도: .g3-fail 마커를 events/ 외부 (.git/, _temp/, dot-prefix dir)에 숨김.
    기대 차단: find_g3_fail_markers는 events_dir만 스캔. 외부 박제는 무시되지만, 동시에 events_dir에 마커가 있을 때 그 마커를 차단함을 검증.
    r
   z.gitfake_eventsT)r-   ztask-pentest-K.g3-failz{}r0   r1   ztask-pentest-KrM   r   ==z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py6)srZ   markersrT   r[   r\   r  uD   hidden path 마커가 events_dir 검색에 포함됨 = 격리 실패
>assert %(py8)sr]   NKzhidden path g3-fail isolationfind_g3_fail_markersisolation_okFrO   rQ   rR   rS   r%  rX   K2u   events_dir 정상 마커 차단r`   )r   ra   rb   rR  rZ   rd   re   rf   rg   rh   ri   rj   rl   rm   r`   rc   rn   )r   rA   real_eventshiddenrN  rt   @py_assert5rp   r  rw   rR   ro   rq   rr   rs   s                  r   )test_K_hidden_path_g3_fail_outside_eventsrX    s    X%K.F
LLL&&224'2J%%&6;OGw<d1d<1ddd<1dddddd3ddd3ddddddwdddwddd<ddd1ddddddddddds$&E%tn-=? ++77w7O
$$%5+NA44545=451145t%'H*ADDEM1::Gr   c                 (   t        t              } | j                  d      }|j                         }|D cg c]'  }|j	                         j                  d      rd|v r|) }}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                  |      d
z  }t        j                  d|       dz   d|iz  }	t        t        j                  |	            dx}x}}yc c}w )uR  메타 테스트: 만약 신규 pentest를 xfail로 마스킹하면 회귀 감지.

    이 테스트는 본인이 PASS 함으로써 xfail 마커가 silent 차단의 우회로 쓰이지 않음을 확인.

    실제 의도: 본 파일 안에 @pytest.mark.xfail 데코레이터가 (주석 외) 사용되지 않았는지 정적 검사.
    r0   r1   @xfailr   rK  rM  rZ   decorator_linesrO  u]   test_lifecycle_penetration.py에서 @xfail 데코레이터 발견 — pentest 우회 시도: rP  r]   N)r   r  r   
splitlinesstrip
startswithrZ   rd   re   rf   rg   rh   ri   rj   rl   rm   )
	test_filer   lineslnr\  rt   rW  rp   r  rw   s
             r   !test_L_xfail_abuse_detection_metarc    sn    XI0DOOE$) Hb((*//4B  HO H 1 1$   1                             $%    h
	     Hs   ,Fc                    t        t              } | j                  d      }t        j                  d|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                  |      d	z  }t        j                  d
t        |       d      dz   d|iz  }t        t        j                  |            dx}x}}y)u   메타: 본 파일에 정의된 test_ 함수가 13개 이상 (mandatory 6 + optional 7).
    pentest를 누락/삭제하면 회귀 감지.
    r0   r1   z^def (test_\w+)   r   )z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} >= %(py6)srZ   
test_funcsrO  u   pentest 함수 수 = u    < 13 (시나리오 누락)rP  r]   N)r   r  r   refindall	MULTILINErZ   rd   re   rf   rg   rh   ri   rj   rl   rm   )r`  r   rf  rt   rW  rp   r  rw   s           r   test_L2_pentest_count_metarj    s     XI0D.bllCJz?fbf?b fff?bffffff3fff3ffffffzfffzfff?fffbfff$9#j/9JJe"ffffffffr   c                   | dz  }|j                          |dz  }|j                          |dz  j                  t        j                  ddd      d       t	        j
                  ddd|	      }|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}} |dddd|j                  d
u |j                         y)u   공격 의도: g3-pass.json 파일은 있지만 result="FAIL".
    기대 차단: check_done_g3_pass_evidence — result≠"PASS" 검출.
    r   ztask-pentest-Mr
  FAIL)r   r  r0   r1   Nr  FrO   rQ   rR   rS   r%  rX   Mzg3-pass.json with result=FAILr  )r   ra   r<   r=   rb   r  rc   rd   re   rf   rg   rh   ri   rl   rm   rn   
r   rA   r  r  rR   ro   rp   rq   rr   rs   s
             r   &test_M_report_pass_but_result_not_passro    s	    
"F
LLN((HNN**4::#v7 , +  	&&'74RV5;	=A44545=451145s$&E,addemQZZIr   c                   | dz  }|j                          |dz  }|j                          |dz  j                  dd       t        j                  ddd|      }|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}} |dddd|j                  d	u |j                         y)u   공격 의도: g3-pass.json을 잘못된 JSON으로 작성하여 파싱 실패 우회 시도.
    기대 차단: 파싱 실패 → fail-closed.
    r   ztask-pentest-M2r
  z{not valid json}r0   r1   Nr  FrO   rQ   rR   rS   r%  rX   M2zcorrupt JSON g3-pass.jsonr  )r   ra   rb   r  rc   rd   re   rf   rg   rh   ri   rl   rm   rn   rn  s
             r    test_M2_report_pass_corrupt_jsonrr    s     
"F
LLN))HNN**+=*P
&&'8DSW5;	=A44545=451145t&(C,addemQZZIr   )r   r   r6   r   )r   r   rE   r5   )r   r   )r   r5   r   int)r   r   r   r5   r   r!   )r   r5   r   r5   r   r5   r   r!   )r   r   r   r5   r   dictr   r5   )r   r   ):__doc__
__future__r   builtinsrf   _pytest.assertion.rewrite	assertionrewriterd   r<   rg  sysr   r   pathlibr   r>  r  resolver-   r8   _SCRIPTS_DIRr5   pathinsertlifecycle_guardsrb   gemini_severity_parserr   r  r   r   rA   r9   r   markparametrizery   r   r   r   r   r   r  r  r   r)  r,  r/  r2  r6  rA  rH  rX  rc  rj  ro  rr  r   r   r   <module>r     s  " #    	 
 '   (^##%--a0
I%|CHH$HHOOAs<()  $     )B )B` X%%,,z9KGJZZ 4#&	8B 	!$	: "	""#&"8<"	"P ?(( 	(
 ( ((\ 	-s3W=	;ZH'R	$'7&=|L	"2C!8(C	CH'R	..!.(,.;>.	.h:%P%^H$	H	E	E@2-D*:G6(gI$Ir   