Version: master @ e7f5f7ef (1.9.44) · zscaler/zpa/policies.py
conditions is popped out of kwargs while the payload dict is being built, and the guard that
decides whether to keep it then tests kwargs — which can no longer contain it:
payload = {
...
"conditions": self._create_conditions_v2(kwargs.pop("conditions", [])), # pops from kwargs
}
...
if "conditions" in payload and "conditions" not in kwargs: # always True after the pop
del payload["conditions"] # so this always runs
for key, value in kwargs.items(): # `conditions` was popped, so this loop
if key == "conditions": # can never match
payload["conditions"] = self._create_conditions_v2(value)
Net effect: conditions is always removed from the request body, and the re-add loop is
unreachable. A caller who passes conditions gets no error and no change to the rule's criteria.
Reproduction
import inspect
from zscaler.zpa.policies import PolicySetControllerAPI as P
src = inspect.getsource(P.update_app_protection_rule_v2)
print(src.index('kwargs.pop("conditions"') < src.index('"conditions" not in kwargs')) # True
The pop precedes the membership test, so the deletion is unconditional.
Suggested direction
The intent of the guard looks like "only send conditions if the caller supplied it", which is a
reasonable thing to want on a partial update. Capturing whether the key was present before
popping it — or reading from a saved copy of kwargs — would make the guard do that. As written
the method silently accepts an argument it cannot act on, so rejecting it would also be an
improvement over the current behaviour.
Happy to open a PR.
Version:
master@e7f5f7ef(1.9.44) ·zscaler/zpa/policies.pyconditionsis popped out ofkwargswhile the payload dict is being built, and the guard thatdecides whether to keep it then tests
kwargs— which can no longer contain it:Net effect:
conditionsis always removed from the request body, and the re-add loop isunreachable. A caller who passes
conditionsgets no error and no change to the rule's criteria.Reproduction
The pop precedes the membership test, so the deletion is unconditional.
Suggested direction
The intent of the guard looks like "only send
conditionsif the caller supplied it", which is areasonable thing to want on a partial update. Capturing whether the key was present before
popping it — or reading from a saved copy of
kwargs— would make the guard do that. As writtenthe method silently accepts an argument it cannot act on, so rejecting it would also be an
improvement over the current behaviour.
Happy to open a PR.