diff --git a/README.md b/README.md index 25ad005..a95ee45 100644 --- a/README.md +++ b/README.md @@ -115,7 +115,7 @@ Some packages have import-time side effects that raise sensitive audit events. F mypkg = "mypkg" ``` -The entries are module prefixes, so `mypkg` also covers `mypkg.submodule`. `fastaudit` does not import these modules when reading metadata. During an audit context, if the stack contains a frame for an allowed module whose `__spec__` is currently initializing, audit events from that import are allowed. Hosts can also pass `allow_imports=('mypkg',)` to `mk_audit()` or call `audit_perms.add_imports('mypkg')` outside the sandbox. +The entries are module prefixes, so `mypkg` also covers `mypkg.submodule`. `fastaudit` does not import these modules when reading metadata. During an audit context, if the stack contains a frame for an allowed module whose `__spec__` is currently initializing, audit events from that import are allowed. Hosts can also pass `allow_imports=('mypkg',)` to `mk_audit()` or call `audit_perms.add_imports('mypkg')` outside the sandbox. A host that passes `data=` with an `import_approved` list gets every event the allowance let through appended to it as `(event, args)`, so it can reconcile what a trusted import did. ### get/set attr hooks diff --git a/fastaudit/core.py b/fastaudit/core.py index b9d6e67..51d5133 100644 --- a/fastaudit/core.py +++ b/fastaudit/core.py @@ -223,7 +223,9 @@ def chk(cfg, event, args): if event in audit_allow or event.startswith(audit_allow_prefix): return if event in ('_thread.start_new_thread','_thread.start_joinable_thread') and asyncio_executor_thread(args): return if event.startswith('audit_perms.'): return deny(cfg, event, args, err_msg(event, args)) - if importing_allowed_module(cfg.import_allow): return + if importing_allowed_module(cfg.import_allow): + if (rec := (cfg.data or {}).get('import_approved')) is not None: rec.append((event, args)) + return if event in ('os.putenv','os.unsetenv'): if env_denied(args[0]): return deny(cfg, event, args, err_msg(event, args)) return diff --git a/tests/test_core.py b/tests/test_core.py index 3bd1692..cef7cb8 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -194,6 +194,12 @@ def import_mod(nm): with expect_fail(PermissionError): audit_perms.add_imports('blocked_import') audit_perms.add_imports('blocked_import') with audit_perms(): assert import_mod('blocked_import').f() is None + + # Passing `data` with an `import_approved` list records the events the allowance let through. + rec = [] + with mk_audit([tmp_path], allow_imports=('runtime_import_ok',), monitor_calls=False, data=dict(import_approved=rec))(): + import_mod('runtime_import_ok') + assert any(ev=='object.__setattr__' for ev,_ in rec) finally: sys.path.remove(str(tmp_path))