T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/milvus_manager.py:276
- Finding
- Milvus Filter Expression Injection Through Unescaped CLI Arguments## Vulnerability Details **File Location**: `scripts/milvus_manager.py:276-287`, `scripts/milvus_manager.py:335`, `scripts/milvus_manager.py:393`, and `scripts/milvus_manager.py:442` **Vulnerability Type**: Milvus filter-expression injection **Risk Level**: High ### Vulnerable Code ```python # Build filter expression filters = [] if category: filters.append(f'category == "{category}"') if role: filters.append(f'role == "{role}"') if project: filters.append(f'project == "{project}"') if event: filters.append(f'event == "{event}"') if status: filters.append(f'status == "{status}"') if priority: filters.append(f'priority == "{priority}"') filter_expr = " and ".join(filters) if filters else None ``` The same unsafe construction is used when retrieving a record: ```python results = self.client.query( collection_name=self.collection_name, filter=f'memory_id == "{memory_id}"', output_fields=["*"] ) ``` It is also used in the update path: ```python self.client.delete( collection_name=self.collection_name, filter=f'memory_id == "{memory_id}"' ) ``` And in the deletion path: ```python self.client.delete( collection_name=self.collection_name, filter=f'memory_id == "{memory_id}"' ) ``` ### Technical Analysis Values received from the command-line options `--category`, `--role`, `--project`, `--event`, `--status`, `--priority`, and `--memory-id` are interpolated directly into Milvus filter expressions. The implementation neither escapes string-literal metacharacters nor validates these values against strict formats or allowlists. If an attacker can influence an argument, a value containing a closing quotation mark and valid Milvus expression syntax can alter the predicate rather than being treated as literal data. The exact payload syntax depends on the expression grammar supported by the deployed Milvus version, but the v ...[truncated 1690 chars]
- Remediation
- ## Remediation Suggestions 1. Validate `memory_id` as a UUID before constructing any query: ```python def validate_memory_id(value: str) -> str: parsed = uuid.UUID(value, version=4) if str(parsed) != value.lower(): raise ValueError("Invalid memory ID") return str(parsed) ``` 2. Restrict enum-like fields such as `category`, `status`, and `priority` to explicit allowlists. 3. Apply strict length and character policies to free-form dimensions such as `role`, `project`, and `event`. If these fields must accept broad Unicode text, use a dedicated Milvus string-literal escaping function rather than a restrictive character allowlist. 4. Prefer a parameterized or structured filter API if supported by the deployed `pymilvus` version. Do not concatenate untrusted values into expression-language strings. 5. If raw filter construction is unavoidable, implement and test escaping for quotation marks, backslashes, control characters, and all other Milvus string-literal metacharacters. 6. Use a minimally privileged Milvus account restricted to the required database and collection. 7. Add tests that submit quotation marks and expression operators through every filter argument and verify that they are handled only as literal values.
