o
    i8                     @   s   d dl mZ d dlmZ d dlmZ d dlmZ d dlm	Z	 d dlm
Z
 d dlmZ d dlmZ d	d
 Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd  Zd!d" Zd#d$ Zd%d& Zd'd( Zd)d* Z d+S ),    )is_iast_request_enabled)
iast_errortaint_pyobject)get_tainted_ranges)unwrap)wrap)config)get_argument_valuec                 C   sb   t jsd S | dt | dt | dt | dt | dt | dt | dt d S )Nzlangchain.patchzlangchain.unpatchzlangchain.llm.generate.afterzlangchain.llm.agenerate.afterz"langchain.chatmodel.generate.afterz#langchain.chatmodel.agenerate.afterzlangchain.stream.chunk.callback)
asm_config_iast_enabledon_langchain_patch_langchain_unpatch_langchain_llm_generate_after#_langchain_chatmodel_generate_after _langchain_stream_chunk_callback)core r   S/home/ubuntu/.local/lib/python3.10/site-packages/ddtrace/appsec/_iast/_langchain.pylangchain_listen   s   r   c            	      C   s  t jsdS tddt tddt d} d}zddl}d}W n ty8   zddl}d}W n	 ty5   Y nw Y nw |r| D ]C}z4ddl}|	|}|}|
d	D ]}t||}qPt|d
ret||d t t|drrt||d t W q= ttfy~   Y q=w dS dS )z
    Patch langchain for IAST. MUST NOT be called directly, only as a callback
    from ddtrace.contrib.internal.langchain.patch import wrap
    Nlangchain_corez$prompts.prompt.PromptTemplate.formatz%prompts.prompt.PromptTemplate.aformat)z*agents.chat.output_parser.ChatOutputParserz5agents.conversational.output_parser.ConvoOutputParserz:agents.conversational_chat.output_parser.ConvoOutputParserz*agents.mrkl.output_parser.MRKLOutputParserz0agents.output_parsers.json.JSONAgentOutputParserzGagents.output_parsers.openai_functions.OpenAIFunctionsAgentOutputParserzNagents.output_parsers.react_json_single_input.ReActJsonSingleInputOutputParserzEagents.output_parsers.react_single_input.ReActSingleInputOutputParserz2agents.output_parsers.self_ask.SelfAskOutputParserz.agents.output_parsers.xml.XMLAgentOutputParserz,agents.react.output_parser.ReActOutputParserz=agents.self_ask_with_search.output_parser.SelfAskOutputParserz?agents.structured_chat.output_parser.StructuredChatOutputParserr   	langchainlangchain_community.formatz.formataformatz.aformat)r   r   r   _wrapper_prompt_template_format _wrapper_prompt_template_aformatlangchain.agentsImportErrorlangchain_community.agents	importlibimport_modulesplitgetattrhasattr_wrapper_agentoutput_parse_wrapper_agentoutput_aparseAttributeError)	agent_output_parser_classesagents_packager   r   class_r"   module	class_objpartr   r   r   r      sH   


r   c                  C   sP   t jrd S zdd l} W n
 ty   Y d S w t| jjjd t| jjjd d S )Nr   r   r   )r   r   r   r    r   promptspromptPromptTemplate)r   r   r   r   r   S   s   r   c              
   C   s  t jsdS t| ttfsdS t|dsdS zS|j}t|ts!W dS d}| D ]}t|ts-q%t|}|r:|d j	} nq%|s@W dS |D ]#}|D ]}t
|\}}	|rR|	sSqFt|	|j|j|jd}
t|||
 qFqBW dS  ty } ztd| W Y d}~dS d}~ww )z
    Taints the output of an LLM call if its inputs are tainted.

    Range propagation does not make sense in LLMs. So we get the first source in inputs, if any,
    and taint the full output with that source.
    Ngenerationsr   pyobjectsource_namesource_valuesource_originz<propagation::source::langchain _langchain_llm_generate_after)r   r   
isinstancetuplelistr&   r3   strr   source"_get_text_attribute_for_generationr   namevalueoriginsetattr	Exceptionr   )r0   completionsr3   r=   r1   tainted_rangesgensgen	text_attrtextnew_texter   r   r   r   ^   sN   



r   c              
      s(  t jsd S t| ttfsd S t| dkrd S t|dsd S z|j}t|ts)W d S t|dkr2W d S d  | D ]"}t|ts>q6|D ]}t|dsHq@t|j	}|rV|d j
  nq@q6  s^W d S |D ]}|D ]}t|\}}	|r|	rt|	 j j jd}
t|||
 t|dr|j}t|dsqd|j	}t|trt|dt | n't|trt|d fdd|D  nt|trt|d fdd	| D  t|d
r|j}t|trd|v r|d }t|trd|v r|d }t|trt ||d< qdq`W d S  ty } ztd| W Y d }~d S d }~ww )Nr   r3   contentr4   messagec                       g | ]}t  |qS r   _iast_taint_if_str.0cr=   r   r   
<listcomp>       z7_langchain_chatmodel_generate_after.<locals>.<listcomp>c                       i | ]
\}}|t  |qS r   rO   rR   kvrT   r   r   
<dictcomp>       z7_langchain_chatmodel_generate_after.<locals>.<dictcomp>additional_kwargsfunction_call	argumentszBpropagation::source::langchain _langchain_chatmodel_generate_after)r   r   r9   r:   r;   lenr&   r3   r   rL   r=   r>   r   r?   r@   rA   rB   rM   r<   rP   dictitemsr]   rC   r   )messagesrD   r3   msgsmsgrE   rF   rG   rH   rI   rJ   rM   rL   r]   r^   r_   rK   r   rT   r   r      s   












r   c                 C   s2   t ||dddd}|sd S t|}|sd S t|S )Nr   inputT)optional)r
   *_get_tainted_source_from_chat_prompt_value_create_taint_chunk_callback)interface_typeargskwargschat_messagesr=   r   r   r   r      s   r   c                    s    fdd}|S )Nc              
      sB   zt  |  W d S  ty  } ztd| W Y d }~d S d }~ww )Nz:propagation::source::langchain _langchain_iast_taint_chunk)_langchain_iast_taint_chunkrC   r   )chunkrK   rT   r   r   _iast_chunk_taint   s   z7_create_taint_chunk_callback.<locals>._iast_chunk_taintr   )r=   rp   r   rT   r   ri      s   ri   c                 C   sv   t jsd S t| dsd S | j}t|ttfsd S |D ]}t|ds"q|j}t|ts+qt	|}|r8|d j
  S qd S )Nrc   rL   r   )r   r   r&   rc   r9   r:   r;   rL   r<   r   r=   )chat_prompt_valuerc   rM   rL   rE   r   r   r   rh      s$   


rh   c                 C   sH   d }t | dr
d}n
t | drd}ndS t| |}t|ts dS ||fS )N_textrI   )NN)r&   r%   r9   r<   )rG   rH   rI   r   r   r   r>      s   



r>   c                    s  t jsdS  s	dS |}t|dsdS |j}t|tr$t|dt | n't|tr7t|d fdd|D  nt|t	rKt|d fdd|
 D  t|dr{|j}t|t	r}d|v r|d }t|t	rd	|v r|d	 }t|trt ||d	< dS dS dS dS dS dS dS )
z]
    Taints a chunk (type BaseMessageChunk, typically an AIMessageChunk) given a source.
    NrL   c                    rN   r   rO   rQ   rT   r   r   rU     rV   z/_langchain_iast_taint_chunk.<locals>.<listcomp>c                    rW   r   rO   rX   rT   r   r   r[     r\   z/_langchain_iast_taint_chunk.<locals>.<dictcomp>r]   r^   r_   )r   r   r&   rL   r9   r<   rB   rP   r;   ra   rb   r]   )r=   ro   rM   rL   r]   r^   r_   r   rT   r   rn     s4   





rn   c                 C   s0   t |ts|S ddlm} ||| j| j| jdS )Nr   r   r4   )r9   r<   3ddtrace.appsec._iast._taint_tracking._taint_objectsr   r?   r@   rA   )r=   objr   r   r   r   rP   (  s   
rP   c                 C   s   | |i |}t ||S )zR
    Propagate taint in PromptTemplate.format, from any input, to the output.
    !_propagate_prompt_template_formatfuncinstancerk   rl   resultr   r   r   r   5  s   
r   c                    s    | |i |I dH }t ||S )zS
    Propagate taint in PromptTemplate.aformat, from any input, to the output.
    Nru   rw   r   r   r   r   =  s   
r   c              
   C   s   z(t  s|W S |  D ]}t|}|r%|d j}t||j|j|j  W S qW |S  ty@ } zt	d| W Y d }~|S d }~ww )Nr   zDpropagation::source::langchain iast_propagate_prompt_template_format)
r   valuesr   r=   r   r?   r@   rA   rC   r   )rl   rz   r@   rangesr=   rK   r   r   r   rv   E  s    
rv   c                 C   s   | |i |}t |||S N_propagante_agentoutput_parserw   r   r   r   r'   T  s   r'   c                    s"   | |i |I d H }t |||S r}   r~   rw   r   r   r   r(   Y  s   r(   c           	   
   C   s
  zlzddl m} ddl m} W n ty$   ddlm} ddlm} Y nw t| d }|rd|d j}t||rFt|j	|j
|j|j|_	W |S t||rgd|jv rj|j}t|d |j
|j|j|d< W |S W |S W |S W |S  ty } ztd| W Y d }~|S d }~ww )Nr   )AgentAction)AgentFinishoutputz2propagation::source::langchain taint_parser_output)langchain_core.agentsr   r   r    r   r   r=   r9   r   
tool_inputr?   r@   rA   return_valuesrC   r   )	rk   rl   rz   r   r   r|   r=   r{   rK   r   r   r   r   ^  s:   

	r   N)!/ddtrace.appsec._iast._iast_request_context_baser   ddtrace.appsec._iast._logsr   rs   r   8ddtrace.appsec._iast._taint_tracking._taint_objects_baser   $ddtrace.contrib.internal.trace_utilsr   r   ddtrace.internal.settings.asmr	   r   ddtrace.internal.utilsr
   r   r   r   r   r   r   ri   rh   r>   rn   rP   r   r   rv   r'   r(   r   r   r   r   r   <module>   s2    <,D

 