T09 · Insecure Skill Coding Practices
- Location
scripts/semantic_vector_store.py:191- Finding
Unsafe Pickle Deserialization Enables Arbitrary Code Execution
- Content
View full analysis
Vulnerability Details
File Location:
scripts/semantic_vector_store.py, lines 191–192
Vulnerability Type: Unsafe deserialization
Risk Level: HighVulnerable Code
python id_map_file = Path(filepath).with_suffix('.ids.pkl') if id_map_file.exists(): with open(id_map_file, 'rb') as f: self.vector_ids = pickle.load(f)Related unsafe deserialization also occurs at lines 275 and 487:
python vector = pickle.loads(embedding_blob)Technical Analysis
Python's
pickleformat is executable serialization rather than a safe data-interchange format. Duringpickle.load()orpickle.loads(), specially crafted objects can invoke attacker-selected callables through pickle reduction opcodes. Consequently, deserializing a malicious pickle can execute arbitrary Python code before the application validates or uses the resulting value.The implementation automatically loads the
.ids.pklfile adjacent to the configured FAISS index whenVectorStoreinitializes. It also deserializes embedding blobs retrieved from the SQLite database while rebuilding the index and conducting linear searches. None of these operations authenticate the serialized data, restrict the allowed object types, or verify file integrity.Attack Path
- An attacker creates a malicious pickle whose deserialization invokes an attacker-selected command or Python callable.
- The attacker places it at the ID-map path derived from the configured database and FAISS index, or inserts it into an
embeddingfield in the SQLite database. - The victim initializes
VectorStoreusing the affected storage path, rebuilds the FAISS index from the database, or performs a linear search. - The application invokes
pickle.load()orpickle.loads()on the attacker-controlled data. - The malicious reduction operation executes with the privileges of the process running the Skill.
Exploitation requires the attacker to ...[truncated 558 chars]
- Remediation
View remediation
Remediation Suggestions
- Eliminate pickle for persistent data that may cross a trust boundary.
- Store the FAISS ID mapping as JSON containing an array of strings. After loading, verify that every entry is a string and that the number of entries equals the number of vectors in the FAISS index.
- Store embeddings in a non-executable representation, such as fixed-width
float32bytes or a NumPy data format that does not permit object arrays. Validate the byte length, dtype, dimension, shape, and finiteness of every vector before use. - Add a migration utility that converts trusted legacy pickle artifacts into the new format. Do not automatically deserialize legacy files.
- If legacy pickle support is temporarily unavoidable, require explicit administrative opt-in and verify artifacts against a trusted cryptographic signature before loading. File permissions alone should not be treated as sufficient protection.
- Restrict storage files to an application-owned directory with least-privilege permissions, reject symbolic links where appropriate, and avoid accepting vector databases from untrusted sources.
- On malformed or unauthenticated data, fail closed and rebuild the index only from validated records.
