TestEscaping Class — langchain Architecture
Architecture documentation for the TestEscaping class in test_serializable.py from the langchain codebase.
Entity Profile
Dependency Diagram
graph TD a193f10f_1a60_b879_b342_d29b1680b3e6["TestEscaping"] de5a7878_b3fe_95d7_2575_7f534546dc1e["AIMessage"] a193f10f_1a60_b879_b342_d29b1680b3e6 -->|extends| de5a7878_b3fe_95d7_2575_7f534546dc1e d90477e3_b806_4058_daf0_8495f08436d6["test_serializable.py"] a193f10f_1a60_b879_b342_d29b1680b3e6 -->|defined in| d90477e3_b806_4058_daf0_8495f08436d6 1eefacbe_c43e_84e8_dc3c_c9a29bcb1069["test_document_metadata_with_lc_key_escaped()"] a193f10f_1a60_b879_b342_d29b1680b3e6 -->|method| 1eefacbe_c43e_84e8_dc3c_c9a29bcb1069 1a2dadb3_bc1b_7714_b00d_afa1425cccfe["test_document_metadata_with_nested_lc_key_escaped()"] a193f10f_1a60_b879_b342_d29b1680b3e6 -->|method| 1a2dadb3_bc1b_7714_b00d_afa1425cccfe 33676637_7c9e_175a_2a9a_b13128e89d47["test_document_metadata_with_lc_key_in_list_escaped()"] a193f10f_1a60_b879_b342_d29b1680b3e6 -->|method| 33676637_7c9e_175a_2a9a_b13128e89d47 822e55fc_290f_8fbc_606a_e45a85e0a0af["test_malicious_payload_not_instantiated()"] a193f10f_1a60_b879_b342_d29b1680b3e6 -->|method| 822e55fc_290f_8fbc_606a_e45a85e0a0af 4946a8d3_7a23_7518_def8_ca78da82b4e7["test_message_additional_kwargs_with_lc_key_escaped()"] a193f10f_1a60_b879_b342_d29b1680b3e6 -->|method| 4946a8d3_7a23_7518_def8_ca78da82b4e7 2ea9aeeb_6aff_6243_335b_f7c665722dad["test_message_response_metadata_with_lc_key_escaped()"] a193f10f_1a60_b879_b342_d29b1680b3e6 -->|method| 2ea9aeeb_6aff_6243_335b_f7c665722dad 4209f521_1764_26ee_927c_789549188624["test_double_escape_handling()"] a193f10f_1a60_b879_b342_d29b1680b3e6 -->|method| 4209f521_1764_26ee_927c_789549188624
Relationship Graph
Source Code
libs/core/tests/unit_tests/load/test_serializable.py lines 400–527
class TestEscaping:
"""Tests that escape-based serialization prevents injection attacks.
When user data contains an `'lc'` key, it's escaped during serialization
(wrapped in `{"__lc_escaped__": ...}`). During deserialization, escaped
dicts are unwrapped and returned as plain dicts - NOT instantiated as
LC objects.
"""
def test_document_metadata_with_lc_key_escaped(self) -> None:
"""Test that `Document` metadata with `'lc'` key round-trips as plain dict."""
# User data that looks like an LC constructor - should be escaped, not executed
suspicious_metadata = {"lc": 1, "type": "constructor", "id": ["some", "module"]}
doc = Document(page_content="test", metadata=suspicious_metadata)
# Serialize - should escape the metadata
serialized = dumpd(doc)
assert serialized["kwargs"]["metadata"] == {
"__lc_escaped__": suspicious_metadata
}
# Deserialize - should restore original metadata as plain dict
loaded = load(serialized, allowed_objects=[Document])
assert loaded.metadata == suspicious_metadata # Plain dict, not instantiated
def test_document_metadata_with_nested_lc_key_escaped(self) -> None:
"""Test that nested `'lc'` key in `Document` metadata is escaped."""
suspicious_nested = {"lc": 1, "type": "constructor", "id": ["some", "module"]}
doc = Document(page_content="test", metadata={"nested": suspicious_nested})
serialized = dumpd(doc)
# The nested dict with 'lc' key should be escaped
assert serialized["kwargs"]["metadata"]["nested"] == {
"__lc_escaped__": suspicious_nested
}
loaded = load(serialized, allowed_objects=[Document])
assert loaded.metadata == {"nested": suspicious_nested}
def test_document_metadata_with_lc_key_in_list_escaped(self) -> None:
"""Test that `'lc'` key in list items within `Document` metadata is escaped."""
suspicious_item = {"lc": 1, "type": "constructor", "id": ["some", "module"]}
doc = Document(page_content="test", metadata={"items": [suspicious_item]})
serialized = dumpd(doc)
assert serialized["kwargs"]["metadata"]["items"][0] == {
"__lc_escaped__": suspicious_item
}
loaded = load(serialized, allowed_objects=[Document])
assert loaded.metadata == {"items": [suspicious_item]}
def test_malicious_payload_not_instantiated(self) -> None:
"""Test that malicious LC-like structures in user data are NOT instantiated."""
# An attacker might craft a payload with a valid AIMessage structure in metadata
malicious_data = {
"lc": 1,
"type": "constructor",
"id": ["langchain", "schema", "document", "Document"],
"kwargs": {
"page_content": "test",
"metadata": {
# This looks like a valid LC object but is in escaped form
"__lc_escaped__": {
"lc": 1,
"type": "constructor",
"id": ["langchain_core", "messages", "ai", "AIMessage"],
"kwargs": {"content": "injected message"},
}
},
},
}
# Even though AIMessage is allowed, the metadata should remain as dict
loaded = load(malicious_data, allowed_objects=[Document, AIMessage])
assert loaded.page_content == "test"
# The metadata is the original dict (unescaped), NOT an AIMessage instance
assert loaded.metadata == {
"lc": 1,
"type": "constructor",
"id": ["langchain_core", "messages", "ai", "AIMessage"],
Extends
Source
Frequently Asked Questions
What is the TestEscaping class?
TestEscaping is a class in the langchain codebase, defined in libs/core/tests/unit_tests/load/test_serializable.py.
Where is TestEscaping defined?
TestEscaping is defined in libs/core/tests/unit_tests/load/test_serializable.py at line 400.
What does TestEscaping extend?
TestEscaping extends AIMessage.
Analyze Your Own Codebase
Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.
Try Supermodel Free