From f0d57a67104bb7b516bd1a896e0c7fcb73250991 Mon Sep 17 00:00:00 2001 From: yashwagle1 Date: Wed, 26 Aug 2026 11:49:39 -0700 Subject: [PATCH 1/3] fix: request every pii-entity-table row as a PII detection threshold (#1048) Co-authored-by: Claude Opus 5 (1M context) --- pyproject.toml | 2 +- .../agent/tools/internal_tools/pii_masker.py | 12 ++++-- .../tools/internal_tools/test_pii_masker.py | 39 +++++++++++++++++-- uv.lock | 4 +- 4 files changed, 48 insertions(+), 9 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 930923082..951fc52db 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "uipath-langchain" -version = "0.16.7" +version = "0.16.7.post1" description = "Python SDK that enables developers to build and deploy LangGraph agents to the UiPath Cloud Platform" readme = { file = "README.md", content-type = "text/markdown" } requires-python = ">=3.11" diff --git a/src/uipath_langchain/agent/tools/internal_tools/pii_masker.py b/src/uipath_langchain/agent/tools/internal_tools/pii_masker.py index e5cb19b12..cbce4a298 100644 --- a/src/uipath_langchain/agent/tools/internal_tools/pii_masker.py +++ b/src/uipath_langchain/agent/tools/internal_tools/pii_masker.py @@ -153,14 +153,20 @@ def rehydrate(self, text: str) -> str: return rehydrated def _entity_thresholds_from_policy(self) -> list[PiiEntityThreshold]: - """Extract enabled entity thresholds from the policy's ``pii-entity-table``.""" + """Extract entity thresholds from the policy's ``pii-entity-table``. + + Every row in the table is requested. ``pii-entity-is-enabled`` is not + consulted: built-in categories carry it as ``true`` while custom rows + (e.g. ``FINationalID`` at 0.8) omit it entirely, so keying off it dropped + those rows from ``entityThresholds``. The service treats that list as an + allowlist, meaning a dropped row is never detected and its PII reaches + the model unmasked. + """ if not self._policy: return [] table = self._policy.get("data", {}).get("pii-entity-table", []) thresholds: list[PiiEntityThreshold] = [] for entry in table: - if not entry.get("pii-entity-is-enabled", False): - continue category = entry.get("pii-entity-category") confidence = entry.get("pii-entity-confidence-threshold") if category is None or confidence is None: diff --git a/tests/agent/tools/internal_tools/test_pii_masker.py b/tests/agent/tools/internal_tools/test_pii_masker.py index bd3421873..a1050d1c1 100644 --- a/tests/agent/tools/internal_tools/test_pii_masker.py +++ b/tests/agent/tools/internal_tools/test_pii_masker.py @@ -99,7 +99,15 @@ def test_returns_empty_when_table_missing(self): masker = PiiMasker(Mock(), {"data": {}}) assert masker._entity_thresholds_from_policy() == [] - def test_filters_disabled_entries(self): + def test_ignores_the_enabled_flag(self): + """``pii-entity-is-enabled`` is not consulted, even when explicitly false. + + Deliberate: the flag is absent on custom rows, so honouring it dropped + those categories from ``entityThresholds`` and, since the service treats + that list as an allowlist, left their PII unmasked. Presence in + ``pii-entity-table`` is the only signal, so an explicit ``false`` no + longer disables a category — de-selecting one must remove its row. + """ policy = { "data": { "pii-entity-table": [ @@ -111,7 +119,31 @@ def test_filters_disabled_entries(self): ] } } - assert PiiMasker(Mock(), policy)._entity_thresholds_from_policy() == [] + assert PiiMasker(Mock(), policy)._entity_thresholds_from_policy() == [ + PiiEntityThreshold(category="Email", confidence_threshold=0.5), + ] + + def test_includes_entry_without_enabled_flag(self): + """Custom rows omit ``pii-entity-is-enabled`` entirely and must survive. + + Regression: such rows were dropped from ``entityThresholds``, and since + the service treats that list as an allowlist the category was then never + detected. + """ + policy = { + "data": { + "pii-entity-table": [ + { + "identifier": "FINationalID0.8", + "pii-entity-category": "FINationalID", + "pii-entity-confidence-threshold": 0.8, + }, + ] + } + } + assert PiiMasker(Mock(), policy)._entity_thresholds_from_policy() == [ + PiiEntityThreshold(category="FINationalID", confidence_threshold=0.8), + ] def test_filters_entries_with_missing_category_or_confidence(self): policy = { @@ -130,7 +162,7 @@ def test_filters_entries_with_missing_category_or_confidence(self): } assert PiiMasker(Mock(), policy)._entity_thresholds_from_policy() == [] - def test_returns_enabled_entries_as_thresholds(self): + def test_returns_every_table_row_as_a_threshold(self): policy = { "data": { "pii-entity-table": [ @@ -157,6 +189,7 @@ def test_returns_enabled_entries_as_thresholds(self): assert thresholds == [ PiiEntityThreshold(category="Email", confidence_threshold=0.5), + PiiEntityThreshold(category="Phone", confidence_threshold=0.7), PiiEntityThreshold(category="SSN", confidence_threshold=0.9), ] diff --git a/uv.lock b/uv.lock index e248e2817..d6fe1b66d 100644 --- a/uv.lock +++ b/uv.lock @@ -9,7 +9,7 @@ resolution-markers = [ ] [options] -exclude-newer = "2026-08-23T13:22:50.1947794Z" +exclude-newer = "2026-08-24T18:32:21.3675003Z" exclude-newer-span = "P2D" [options.exclude-newer-package] @@ -4546,7 +4546,7 @@ wheels = [ [[package]] name = "uipath-langchain" -version = "0.16.7" +version = "0.16.11" source = { editable = "." } dependencies = [ { name = "a2a-sdk" }, From 148e67c7aeb054f951f11df0a1959533ef192c26 Mon Sep 17 00:00:00 2001 From: Radu Mocanu Date: Tue, 1 Sep 2026 18:18:02 +0300 Subject: [PATCH 2/3] ci: run checks and publish on release branches (#1059) --- .github/workflows/cd.yml | 1 + .github/workflows/ci.yml | 2 ++ 2 files changed, 3 insertions(+) diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 91ab81cff..7cee7e4ec 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -5,6 +5,7 @@ on: push: branches: - main + - 'release/**' paths: - pyproject.toml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6658b4a44..fd5dd8621 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,11 +4,13 @@ on: push: branches: - main + - 'release/**' paths-ignore: - pyproject.toml pull_request: branches: - main + - 'release/**' jobs: commit-lint: From 3b69fd2030ffd077cdf9f310a17e199b333cf65a Mon Sep 17 00:00:00 2001 From: Yash Wagle Date: Thu, 3 Sep 2026 13:13:15 -0700 Subject: [PATCH 3/3] fix: bump version --- uv.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/uv.lock b/uv.lock index d6fe1b66d..d0c25996a 100644 --- a/uv.lock +++ b/uv.lock @@ -9,7 +9,7 @@ resolution-markers = [ ] [options] -exclude-newer = "2026-08-24T18:32:21.3675003Z" +exclude-newer = "2026-09-01T19:52:33.763506Z" exclude-newer-span = "P2D" [options.exclude-newer-package] @@ -4546,7 +4546,7 @@ wheels = [ [[package]] name = "uipath-langchain" -version = "0.16.11" +version = "0.16.7.post1" source = { editable = "." } dependencies = [ { name = "a2a-sdk" },