icemac: It might also fix zopefoundation/RestrictedPython#129 even though the error message there is different.
diff --git a/CHANGES.rst b/CHANGES.rst
index 8dcf866..874cf62 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -6,7 +6,8 @@ For changes before version 3.0, see ``HISTORY.rst``.
 4.1 (unreleased)
 ----------------
 
-- Nothing changed yet.
+- PY3: allow iteration over the result of ``dict.{keys,values,items}``
+  (`#89 <https://github.com/zopefoundation/AccessControl/issues/89>`_).
 
 
 4.0 (2019-05-08)
diff --git a/src/AccessControl/ZopeGuards.py b/src/AccessControl/ZopeGuards.py
index 5cf0e4c..34643af 100644
--- a/src/AccessControl/ZopeGuards.py
+++ b/src/AccessControl/ZopeGuards.py
@@ -34,6 +34,7 @@ from AccessControl.SecurityInfo import secureModule
 from AccessControl.SecurityManagement import getSecurityManager
 from AccessControl.SimpleObjectPolicies import ContainerAssertions
 from AccessControl.SimpleObjectPolicies import Containers
+from AccessControl.SimpleObjectPolicies import allow_type
 
 
 _marker = []  # Create a new marker object.
@@ -196,6 +197,13 @@ def _check_dict_access(name, value):
 ContainerAssertions[type({})] = _check_dict_access
 
 
+if six.PY3:
+    # Allow iteration over the result of `dict.{keys, values, items}`
+    d = {}
+    for attr in ("keys", "values", "items"):
+        allow_type(type(getattr(d, attr)()))
+
+
 _list_white_list = {
     'append': 1,
     'count': 1,

PY3: "ZopeGuards" forgets to allow iteration over the result of "dict.{keys,values,items}"
Under Python 3, the `next`s in the following code all result in an `AccessControl.unauthorized.Unauthorized: You are not allowed to access 'a particular tuple' in this context`:
```
from AccessControl.ZopeGuards import SafeIter, Containers

d={1:1, 2:2}
i=SafeIter(d.items())
next(i)
ik=SafeIter(d.keys())
next(ik)
iv=SafeIter(d.values())
next(iv)
```
This is the cause of https://github.com/zopefoundation/Products.PythonScripts/issues/35.
diff --git a/src/AccessControl/tests/testZopeGuards.py b/src/AccessControl/tests/testZopeGuards.py
index 20bd41f..24c933c 100644
--- a/src/AccessControl/tests/testZopeGuards.py
+++ b/src/AccessControl/tests/testZopeGuards.py
@@ -355,6 +355,14 @@ class TestDictGuards(GuardTestCase):
             self.setSecurityManager(old)
         self.assertTrue(sm.calls)
 
+    def test_kvi_iteration(self):
+        from AccessControl.ZopeGuards import SafeIter
+        d = dict(a=1, b=2)
+        for attr in ("keys", "values", "items"):
+            v = getattr(d, attr)()
+            si = SafeIter(v)
+            self.assertEqual(next(si), next(iter(v)))
+
 
 class TestListGuards(GuardTestCase):
 

pip install -e .
parse_log_pytest
requirements.txt
pytest
apt-get update apt-get install -y gcc
3.7
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
-e git+https://github.com/zopefoundation/AccessControl.git@099c03fb5bcb7e3cf8e9f3f959a1a30508cd5422#egg=AccessControl
Acquisition==5.2
AuthEncoding==5.0
BTrees==5.2
certifi @ file:///croot/certifi_1671487769961/work/certifi
cffi==1.15.1
DateTime==5.5
exceptiongroup==1.2.2
ExtensionClass==5.1
importlib-metadata==6.7.0
iniconfig==2.0.0
multipart==1.1.0
packaging==24.0
Persistence==4.1
persistent==5.2
pluggy==1.2.0
pycparser==2.21
pytest==7.4.4
python-gettext==5.0
pytz==2025.2
RestrictedPython==7.3
six==1.17.0
tomli==2.0.1
transaction==4.0
typing_extensions==4.7.1
zExceptions==5.0
zipp==3.15.0
zope.browser==3.0
zope.component==6.0
zope.configuration==5.0.1
zope.contenttype==5.1
zope.deferredimport==5.0
zope.deprecation==5.0
zope.event==5.0
zope.exceptions==5.1
zope.hookable==6.0
zope.i18n==5.1
zope.i18nmessageid==6.1.0
zope.interface==6.4.post2
zope.location==5.0
zope.proxy==5.3
zope.publisher==7.0
zope.schema==7.0.1
zope.security==6.2
zope.testing==5.0.1

name: AccessControl
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2022.12.7=py37h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=22.3.1=py37h06a4308_0
  - python=3.7.16=h7a1cb2a_0
  - readline=8.2=h5eee18b_0
  - setuptools=65.6.3=py37h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.38.4=py37h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - acquisition==5.2
      - authencoding==5.0
      - btrees==5.2
      - cffi==1.15.1
      - datetime==5.5
      - exceptiongroup==1.2.2
      - extensionclass==5.1
      - importlib-metadata==6.7.0
      - iniconfig==2.0.0
      - multipart==1.1.0
      - packaging==24.0
      - persistence==4.1
      - persistent==5.2
      - pluggy==1.2.0
      - pycparser==2.21
      - pytest==7.4.4
      - python-gettext==5.0
      - pytz==2025.2
      - restrictedpython==7.3
      - six==1.17.0
      - tomli==2.0.1
      - transaction==4.0
      - typing-extensions==4.7.1
      - zexceptions==5.0
      - zipp==3.15.0
      - zope-browser==3.0
      - zope-component==6.0
      - zope-configuration==5.0.1
      - zope-contenttype==5.1
      - zope-deferredimport==5.0
      - zope-deprecation==5.0
      - zope-event==5.0
      - zope-exceptions==5.1
      - zope-hookable==6.0
      - zope-i18n==5.1
      - zope-i18nmessageid==6.1.0
      - zope-interface==6.4.post2
      - zope-location==5.0
      - zope-proxy==5.3
      - zope-publisher==7.0
      - zope-schema==7.0.1
      - zope-security==6.2
      - zope-testing==5.0.1
prefix: /opt/conda/envs/AccessControl

src/AccessControl/tests/testZopeGuards.py::TestDictGuards::test_kvi_iteration
src/AccessControl/tests/testZopeGuards.py::TestGuardedGetattr::test_attr_handler_table src/AccessControl/tests/testZopeGuards.py::TestGuardedGetattr::test_calls_validate_for_unknown_type src/AccessControl/tests/testZopeGuards.py::TestGuardedGetattr::test_miss src/AccessControl/tests/testZopeGuards.py::TestGuardedGetattr::test_simple_object_policies src/AccessControl/tests/testZopeGuards.py::TestGuardedGetattr::test_unauthorized src/AccessControl/tests/testZopeGuards.py::TestGuardedGetattr::test_unhashable_key src/AccessControl/tests/testZopeGuards.py::TestGuardedHasattr::test_hit src/AccessControl/tests/testZopeGuards.py::TestGuardedHasattr::test_miss src/AccessControl/tests/testZopeGuards.py::TestGuardedHasattr::test_unauthorized src/AccessControl/tests/testZopeGuards.py::TestGuardedHasattr::test_unhashable_key src/AccessControl/tests/testZopeGuards.py::TestDictGuards::test_get_default src/AccessControl/tests/testZopeGuards.py::TestDictGuards::test_get_simple src/AccessControl/tests/testZopeGuards.py::TestDictGuards::test_get_validates src/AccessControl/tests/testZopeGuards.py::TestDictGuards::test_keys_empty src/AccessControl/tests/testZopeGuards.py::TestDictGuards::test_keys_validates src/AccessControl/tests/testZopeGuards.py::TestDictGuards::test_pop_default src/AccessControl/tests/testZopeGuards.py::TestDictGuards::test_pop_raises src/AccessControl/tests/testZopeGuards.py::TestDictGuards::test_pop_simple src/AccessControl/tests/testZopeGuards.py::TestDictGuards::test_pop_validates src/AccessControl/tests/testZopeGuards.py::TestDictGuards::test_values_empty src/AccessControl/tests/testZopeGuards.py::TestDictGuards::test_values_validates src/AccessControl/tests/testZopeGuards.py::TestListGuards::test_pop_raises src/AccessControl/tests/testZopeGuards.py::TestListGuards::test_pop_simple src/AccessControl/tests/testZopeGuards.py::TestListGuards::test_pop_validates src/AccessControl/tests/testZopeGuards.py::TestBuiltinFunctionGuards::test_all_fails src/AccessControl/tests/testZopeGuards.py::TestBuiltinFunctionGuards::test_all_succeeds src/AccessControl/tests/testZopeGuards.py::TestBuiltinFunctionGuards::test_any_fails src/AccessControl/tests/testZopeGuards.py::TestBuiltinFunctionGuards::test_any_succeeds src/AccessControl/tests/testZopeGuards.py::TestBuiltinFunctionGuards::test_apply src/AccessControl/tests/testZopeGuards.py::TestBuiltinFunctionGuards::test_enumerate_fails src/AccessControl/tests/testZopeGuards.py::TestBuiltinFunctionGuards::test_enumerate_succeeds src/AccessControl/tests/testZopeGuards.py::TestBuiltinFunctionGuards::test_map_fails src/AccessControl/tests/testZopeGuards.py::TestBuiltinFunctionGuards::test_map_succeeds src/AccessControl/tests/testZopeGuards.py::TestBuiltinFunctionGuards::test_max_fails src/AccessControl/tests/testZopeGuards.py::TestBuiltinFunctionGuards::test_max_succeeds src/AccessControl/tests/testZopeGuards.py::TestBuiltinFunctionGuards::test_min_fails src/AccessControl/tests/testZopeGuards.py::TestBuiltinFunctionGuards::test_min_succeeds src/AccessControl/tests/testZopeGuards.py::TestBuiltinFunctionGuards::test_sum_fails src/AccessControl/tests/testZopeGuards.py::TestBuiltinFunctionGuards::test_sum_succeeds src/AccessControl/tests/testZopeGuards.py::TestBuiltinFunctionGuards::test_zip_fails src/AccessControl/tests/testZopeGuards.py::TestBuiltinFunctionGuards::test_zip_succeeds src/AccessControl/tests/testZopeGuards.py::TestGuardedDictListTypes::testDictCreation src/AccessControl/tests/testZopeGuards.py::TestGuardedDictListTypes::testListCreation src/AccessControl/tests/testZopeGuards.py::TestRestrictedPythonApply::test_apply src/AccessControl/tests/testZopeGuards.py::TestActualPython::testPython src/AccessControl/tests/testZopeGuards.py::TestActualPython::testPythonRealAC src/AccessControl/tests/testZopeGuards.py::TestActualPython::test_derived_class_normal src/AccessControl/tests/testZopeGuards.py::TestActualPython::test_derived_class_sneaky_en_suite src/AccessControl/tests/testZopeGuards.py::TestActualPython::test_derived_sneaky_instance src/AccessControl/tests/testZopeGuards.py::TestActualPython::test_derived_sneaky_post_facto src/AccessControl/tests/testZopeGuards.py::TestActualPython::test_dict_access src/AccessControl/tests/testZopeGuards.py::TestActualPython::test_guarded_next__1 src/AccessControl/tests/testZopeGuards.py::TestActualPython::test_guarded_next__2 src/AccessControl/tests/testZopeGuards.py::TestActualPython::test_guarded_next__3 src/AccessControl/tests/testZopeGuards.py::test_inplacevar src/AccessControl/tests/testZopeGuards.py::test_inplacevar_for_py24 src/AccessControl/tests/testZopeGuards.py::test_suite
src/AccessControl/ZopeGuards.py CHANGES.rst
src/AccessControl/ZopeGuards.py CHANGES.rst