feat: 新增脚手架/开发模式/权限白名单/system-monitor插件
Some checks failed
CI / test (3.10) (push) Has been cancelled
CI / test (3.11) (push) Has been cancelled
CI / test (3.12) (push) Has been cancelled
CI / test (3.13) (push) Has been cancelled

- nebula create mod/key/list-templates 模组脚手架
- nebula dev 开发模式热重载
- manifest permissions.imports 权限白名单机制
- system-monitor 系统监控仪表盘插件
- 默认端口统一为 10086
- 修复 _init_nbpf 误读 Ed25519 私钥为 RSA 的 bug
- 更新 README.md 文档
This commit is contained in:
starlight-apk
2026-05-16 20:20:43 +08:00
parent bce27db4ac
commit 5fbc5cc335
14 changed files with 1225 additions and 312 deletions

View File

@@ -55,6 +55,7 @@ class NBPFLoader:
self.trusted_ed25519_keys = trusted_ed25519_keys or {}
self.trusted_rsa_keys = trusted_rsa_keys or {}
self.rsa_private_key = rsa_private_key
self._current_allowed_imports: list[str] = []
def load(
self,
@@ -112,7 +113,12 @@ class NBPFLoader:
meta = manifest.get("metadata", {})
name = plugin_name or meta.get("name", nbpf_path.stem)
# 9. 反序列化并执行
# 9. 反序列化并执行(传入 imports 白名单)
perms = manifest.get("permissions", {})
if isinstance(perms, dict):
self._current_allowed_imports = perms.get("imports", [])
else:
self._current_allowed_imports = []
instance, module = self._deserialize_and_exec(nir_data, name)
# 10. 构建插件信息
@@ -326,7 +332,7 @@ class NBPFLoader:
"""反序列化 NIR 并执行,返回 (instance, module)"""
# 构建安全的全局命名空间
safe_globals = self._build_safe_globals(plugin_name)
safe_globals = self._build_safe_globals(plugin_name, self._current_allowed_imports)
# 按依赖顺序执行模块
main_module = None
@@ -365,9 +371,12 @@ class NBPFLoader:
return instance, main_module
def _build_safe_globals(self, plugin_name: str) -> dict:
def _build_safe_globals(self, plugin_name: str, allowed_imports: list[str] = None) -> dict:
"""构建安全的全局命名空间
如果插件在 manifest 中声明了 imports 权限,将 `__import__` 加回内置函数,
并用白名单包装器限制只能导入声明的模块。
注意Python 沙箱无法完全阻止通过 ()__class__.__bases__[0].__subclasses__()
等反射方式逃逸。本沙箱仅用于防止意外访问危险模块,真正的安全隔离
需要 OS 级容器化。
@@ -390,6 +399,19 @@ class NBPFLoader:
'KeyError': KeyError, 'IndexError': IndexError,
'Exception': Exception, 'BaseException': BaseException,
}
# 如果插件声明了 imports 权限,添加白名单 __import__
if allowed_imports:
_allowed_set = set(allowed_imports)
def _safe_import(name, *args, **kwargs):
base = name.split(".")[0]
if base not in _allowed_set:
raise ImportError(
f"模块 '{name}' 不在权限白名单中。"
f"请在 manifest.json 的 permissions.imports 中声明: {sorted(_allowed_set)}"
)
return __import__(name, *args, **kwargs)
safe_builtins['__import__'] = _safe_import
return {
'__builtins__': safe_builtins,
'__name__': f'nbpf.{plugin_name}',