This is an automated email from the ASF dual-hosted git repository.
hsluoyz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/casbin-pycasbin.git
The following commit(s) were added to refs/heads/master by this push:
new 6ab2095 fix: return copies from get_policy and get_filtered_policy
6ab2095 is described below
commit 6ab2095c552725535c2550f151b9b2c91c7790f6
Author: Yang Luo <[email protected]>
AuthorDate: Tue Aug 4 14:08:34 2026 +0800
fix: return copies from get_policy and get_filtered_policy
---
casbin/model/policy.py | 16 ++++++++++++----
tests/model/test_policy.py | 25 +++++++++++++++++++++++++
tests/test_rbac_api.py | 23 +++++++++++++++++++++++
3 files changed, 60 insertions(+), 4 deletions(-)
diff --git a/casbin/model/policy.py b/casbin/model/policy.py
index 77fd3a7..9c57cb3 100644
--- a/casbin/model/policy.py
+++ b/casbin/model/policy.py
@@ -89,14 +89,22 @@ class Policy:
self[sec][key].policy = []
def get_policy(self, sec, ptype):
- """gets all rules in a policy."""
+ """gets all rules in a policy.
- return self[sec][ptype].policy
+ The returned rules are shallow copies, so that mutating them does not
+ corrupt the internal policy storage.
+ """
+
+ return [rule[:] for rule in self[sec][ptype].policy]
def get_filtered_policy(self, sec, ptype, field_index, *field_values):
- """gets rules based on field filters from a policy."""
+ """gets rules based on field filters from a policy.
+
+ The returned rules are shallow copies, so that mutating them does not
+ corrupt the internal policy storage.
+ """
return [
- rule
+ rule[:]
for rule in self[sec][ptype].policy
if all(
(callable(value) and value(rule[field_index + i])) or (value
== "" or rule[field_index + i] == value)
diff --git a/tests/model/test_policy.py b/tests/model/test_policy.py
index 855eb84..b4d1cbf 100644
--- a/tests/model/test_policy.py
+++ b/tests/model/test_policy.py
@@ -29,6 +29,31 @@ class TestPolicy(TestCase):
self.assertTrue(m.get_policy("p", "p") == [rule])
+ def test_get_policy_returns_copies(self):
+ m = Model()
+ m.load_model(get_examples("basic_model.conf"))
+
+ rule = ["admin", "domain1", "data1", "read"]
+ m.add_policy("p", "p", rule)
+
+ returned = m.get_policy("p", "p")
+ returned.append(["hacker", "domain1", "data1", "read"])
+ returned[0][0] = "hacker"
+
+ self.assertEqual(m.get_policy("p", "p"), [["admin", "domain1",
"data1", "read"]])
+
+ def test_get_filtered_policy_returns_copies(self):
+ m = Model()
+ m.load_model(get_examples("basic_model.conf"))
+
+ rule = ["admin", "domain1", "data1", "read"]
+ m.add_policy("p", "p", rule)
+
+ returned = m.get_filtered_policy("p", "p", 0, "admin")
+ returned[0][0] = "hacker"
+
+ self.assertEqual(m.get_policy("p", "p"), [["admin", "domain1",
"data1", "read"]])
+
def test_has_policy(self):
m = Model()
m.load_model(get_examples("basic_model.conf"))
diff --git a/tests/test_rbac_api.py b/tests/test_rbac_api.py
index 6171fed..bd40cd4 100644
--- a/tests/test_rbac_api.py
+++ b/tests/test_rbac_api.py
@@ -206,6 +206,29 @@ class TestRbacApi(TestCaseBase):
sorted([["bob", "data2", "write"]]),
)
+ def test_implicit_permissions_api_does_not_expose_internal_rules(self):
+ e = self.get_enforcer(
+ get_examples("rbac_model.conf"),
+ get_examples("rbac_policy.csv"),
+ )
+
+ permissions = e.get_implicit_permissions_for_user("alice")
+ for permission in permissions:
+ permission[0] = "alice"
+
+ self.assertEqual(
+ sorted(e.get_policy()),
+ sorted(
+ [
+ ["alice", "data1", "read"],
+ ["bob", "data2", "write"],
+ ["data2_admin", "data2", "read"],
+ ["data2_admin", "data2", "write"],
+ ]
+ ),
+ )
+ self.assertTrue(e.enforce("alice", "data2", "read"))
+
def test_enforce_implicit_permissions_api_with_multiple_policy(self):
e = self.get_enforcer(
get_examples("rbac_with_multiple_policy_model.conf"),
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]