Skip to content

Commit

Permalink
Merge branch 'stable/v3' into merge_stable_240702
Browse files Browse the repository at this point in the history
  • Loading branch information
dirkkul committed Jul 2, 2024
2 parents 847d6c4 + a3b96a9 commit 38456c5
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 8 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ jobs:
cache: 'pip' # caching pip dependencies
- run: pip install -r requirements-devel.txt
- name: Run mypy
run: mypy --warn-unused-ignores --python-version ${{matrix.version}} ${{ matrix.folder }}
run: mypy --config-file ./pyproject.toml --warn-unused-ignores --python-version ${{matrix.version}} ${{ matrix.folder }}
- uses: jakebailey/pyright-action@v2
with:
version: 1.1.347
Expand Down
11 changes: 6 additions & 5 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
exclude: ^proto/
repos:
- repo: https://github.com/psf/black
rev: 23.9.1
rev: 24.4.2
hooks:
- id: black

- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
rev: v4.6.0
hooks:
- id: no-commit-to-branch
- id: trailing-whitespace

- repo: https://github.com/PyCQA/flake8
rev: 6.1.0
hooks:

- repo: https://github.com/PyCQA/flake8
rev: 7.1.0
hooks:
- id: flake8
name: linting
additional_dependencies: [
Expand Down
13 changes: 13 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,19 @@ This beta version includes:
- No more builder methods or raw dictionaries
- Join the discussion and contribute your feedback `here <https://forum.weaviate.io/t/python-v4-client-feedback-megathread/892>`_

Version 3.26.5
--------------
This patch version includes

- Fixes GraphQL query injection vulnerability caused by incorrect escaping of backslashes in plain text input builder methods
- Many thanks to `@adamleko <https://github.com/adamleko>`_, `@bismuthsalamander <https://github.com/bismuthsalamander>`_, and `@tardigrade-9 <https://github.com/tardigrade-9>`_ for their help in fixing this issue

Version 3.26.4
--------------
This patch version includes

- Fixes batch retry with tenants

Version 3.26.2
--------------
This patch version includes
Expand Down
63 changes: 63 additions & 0 deletions integration/test_injection.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import pytest
import weaviate
import requests
import json


def injection_template(n: int) -> str:
return "Liver" + ("\\" * n) + '"}}){{answer}}}}{payload}#'


@pytest.mark.parametrize("n_backslashes", [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
def test_gql_injection(n_backslashes: int) -> None:
client = weaviate.Client(url="http://localhost:8080")
client.schema.delete_class("Question")
client.schema.delete_class("Hacked")
class_obj = {
"class": "Question",
"vectorizer": "text2vec-contextionary",
"properties": [
{"name": "answer", "dataType": ["string"], "tokenization": "field"},
{"name": "question", "dataType": ["string"]},
{"name": "category", "dataType": ["string"]},
],
}

class_obj2 = {
"class": "Hacked",
"vectorizer": "text2vec-contextionary",
"properties": [
{"name": "answer", "dataType": ["string"]},
{"name": "question", "dataType": ["string"]},
{"name": "category", "dataType": ["string"]},
],
}
client.schema.create_class(class_obj)
client.schema.create_class(class_obj2)

resp = requests.get(
"https://raw.githubusercontent.com/weaviate-tutorials/quickstart/main/data/jeopardy_tiny.json"
)
data = json.loads(resp.text)

client.batch.configure(batch_size=100)
with client.batch as batch:
for _, d in enumerate(data):
properties = {
"answer": d["Answer"],
"question": d["Question"],
"category": d["Category"],
}
batch.add_data_object(data_object=properties, class_name="Question")
batch.add_data_object(data_object=properties, class_name="Hacked")

injection_payload = client.query.get("Hacked", ["answer"]).build()
query = client.query.get("Question", ["question", "answer", "category"]).with_where(
{
"path": ["answer"],
"operator": "NotEqual",
"valueText": injection_template(n_backslashes).format(payload=injection_payload[1:]),
}
)
res = query.do()
assert "Hacked" not in res["data"]["Get"]
4 changes: 3 additions & 1 deletion run-mypy.sh
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#!/usr/bin/env bash

python3 -m venv venv
source venv/bin/activate
pip install -r requirements-devel.txt >/dev/null 2>&1

echo "Static checking ./weaviate:"
mypy --config-file ./pyproject.toml ./weaviate
echo "Static checking ./integration:"
mypy --config-file ./pyproject.toml ./integration
mypy --config-file ./pyproject.toml --warn-unused-ignores ./weaviate
17 changes: 17 additions & 0 deletions test/test_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
is_weaviate_too_old,
is_weaviate_client_too_old,
MINIMUM_NO_WARNING_VERSION,
_sanitize_str,
)

schema_set = {
Expand Down Expand Up @@ -575,3 +576,19 @@ def test_is_weaviate_too_old(version: str, too_old: bool):
)
def test_is_weaviate_client_too_old(current_version: str, latest_version: str, too_old: bool):
assert is_weaviate_client_too_old(current_version, latest_version) is too_old


@pytest.mark.parametrize(
"in_str, out_str",
[
('"', '\\"'),
('"', '\\"'),
('\\"', '\\"'),
('\\"', '\\"'),
('\\\\"', '\\\\\\"'),
('\\\\"', '\\\\\\"'),
('\\\\\\"', '\\\\\\"'),
],
)
def test_sanitize_str(in_str: str, out_str: str) -> None:
assert _sanitize_str(in_str) == f'"{out_str}"'
4 changes: 3 additions & 1 deletion weaviate/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -703,7 +703,9 @@ def _sanitize_str(value: str) -> str:
The sanitized string.
"""
value = strip_newlines(value)
value = re.sub(r'(?<!\\)"', '\\"', value) # only replaces unescaped double quotes
value = re.sub(
r'(?<!\\)((?:\\{2})*)"', r"\1\"", value
) # only replaces unescaped double quotes without permitting query injection
return f'"{value}"'


Expand Down

0 comments on commit 38456c5

Please sign in to comment.