脚本动作安全与授权
本文说明脚本动作能做什么、不能做什么,什么时候会弹出授权确认,以及哪些情况需要提高警惕。内容以当前版本的实际行为为准,不代表脚本动作是绝对安全的。
相关文档:脚本动作入门、脚本动作 API 参考。
1. 一句话概括
- 脚本运行在一个**受限环境(沙箱)**里:不能直接使用文件、网络、进程等 .NET 功能,一切系统能力都必须通过
qk调用。 - 运行前,Quicker 从源码中识别脚本会用到哪些能力;运行时,只放行已识别且已授权的能力。
- 你自己编写的脚本(包括让 AI 帮你写并保存的)运行前不会确认;从外部导入、从动作库安装的脚本,首次运行前会按能力逐项请你确认。
- 沙箱是软件层面的限制,脚本与 Quicker 运行在同一个进程中,不是操作系统级别的隔离。请只运行你信任、并且看得懂的脚本。
2. 沙箱是什么
2.1 脚本能直接做的
- 纯计算:字符串、数字、日期、正则、LINQ、集合、JSON(
JsonNode、只作用于数据的JsonSerializer)、Encoding、Math、Guid、Random、Uri等; Path的纯字符串方法(Path.Combine、GetFileName等,不访问磁盘);- 调用
qk提供的能力。
2.2 脚本不能直接做的
- 读写文件和目录(
File、Directory、文件流); - 访问网络(
HttpClient、WebClient); - 启动或结束进程(
Process); - 创建线程、定时器、并行任务;
- 访问环境变量、控制台、
MessageBox/WPF/WinForms 窗口; - 反射、加载程序集、调用系统 API。
这些能力只有对应的 qk 版本,例如读文件要用 qk.Files.ReadText,访问网络要用 qk.Http.GetText。qk 方法内部会做参数校验、次数与大小限额、权限检查(例如拒绝操作管理员权限的窗口、拒绝读取 Quicker 自身界面、以普通权限启动程序等)。
2.3 沙箱不能保证什么
请准确理解沙箱的边界:
- 与 Quicker 同进程:脚本由 Quicker 内置的解释器在 Quicker 进程内执行。沙箱依靠解释器拦截不允许的类型和成员来工作,不是虚拟机或独立进程。如果解释器存在尚未发现的漏洞,脚本理论上可能获得与 Quicker 相同的权限。
qk能力本身就很强:一个获得了“读取文件”和“访问网络”能力的脚本,完全可以把你的文件上传出去;获得“键盘监听”的脚本可以记录你输入的密码。沙箱只保证脚本“按声明的能力做事”,不判断它做的事是否对你有利。- 能力确认只针对“安装来源”的动作:自己编写的动作运行前没有任何确认(见第 3 节)。
- 每次运行的限额(例如键盘输入 2000 字符、窗口操作次数等)是为了防止失控,不是安全保证。
- 部分外部操作无法撤回:例如启动的程序、发出的网络请求、写入云端的数据、在 Office 中执行的宏,超时或停止脚本后可能仍在继续或已经生效。
3. 能力与授权确认
3.1 按来源决定是否确认
| 动作来源 | 运行前是否确认 |
|---|---|
| 本机自建:你在编辑器中手写,或 AI 助手代写后由你保存;以及它们的副本;同一账号同步到其他设备后的同一动作 | 不确认。作者就是你本人 |
| 从动作库安装或更新 | 首次运行前按能力逐项确认 |
| 在安装来的动作上做了本地修改,或安装来的动作的副本 | 仍按“安装来源”处理(改一个字不会变成“自建”) |
| 从文件导入,或从剪贴板粘贴了他人复制的动作(例如从论坛、聊天中复制) | 按“外部导入”处理,与安装来源相同,逐项确认 |
“安装来源”的脚本动作来自分享平台安装、文件导入和剪贴板粘贴。本机“复制动作”后再粘贴仍视为自建;Quicker 重启后,之前复制在剪贴板里的动作会按外部来源处理(多问一次,不会漏问)。
3.2 确认时会发生什么
对需要确认的动作:
- 运行前,Quicker 列出脚本用到、但尚未授权的能力,请你确认;
- 你确认后,这些能力在本机被记住,下次运行不再询问;
- 你拒绝时,本次运行失败,错误码为
CAPABILITY_DENIED(OperationId 为run),消息为“用户拒绝了 … 权限”;拒绝不会被记住,下次运行会再次询问; - 授权只保存在本机,不随账号同步、不随动作导出。换一台电脑需要重新确认;
- 如果是在编辑器中临时运行一个尚未保存的此类动作,确认只对本次运行有效,不会保存。
以下能力不需要确认(任何来源都直接可用):写日志、等待、读取运行上下文、动作状态(qk.State)、大部分对话框与通知(qk.Ui,带 click 的通知除外)、纯计算的文本工具(哈希、拼音)、显示器信息、音量与播放内置声音/朗读、读取或装饰本动作自身(角标、覆盖图标、附加右键菜单)等。播放本机音频文件或网址、从文件或网址加载图片时,另需“读取文件”或“访问网络”能力。
3.3 能力扩大时再次确认
授权按“动作 + 来源 + 能力”逐项记录,不绑定具体源码:
- 动作更新或你本地修改后,只要用到的能力没有超出已授权的范围,就不再询问;
- 一旦新版本用到了新的能力(例如原来只读剪贴板,新版本增加了“访问网络”),运行前只询问新增的那几项;
- 调用组合动作步骤的
qk.Steps.Run(见 API 参考·qk.Steps)按步骤逐个确认,新增步骤会再次询问。
3.4 确认对话框里的能力说明
| 确认中显示 | 对应的 qk 用法(举例) |
|---|---|
| 桌面鼠标自动化(全屏范围) | qk.Mouse.* |
| 桌面键盘自动化(前台窗口) | qk.Keyboard.Press/Type/Paste/SendKeys、GetIme/SetIme |
| 读取剪贴板内容 / 写入或清空剪贴板内容 | qk.Clipboard.Get* / qk.Clipboard.Set*、Clear |
| 读取桌面窗口与进程信息 | qk.Window.Find/FindAll/Info/...、qk.Process.List、qk.Apps.ListTargets |
| 激活桌面窗口 | qk.Window.Activate/RestoreForeground |
| 移动、缩放、隐藏或改变窗口状态 | qk.Window.SetBounds/SetState/SetTopmost/Close/... |
| 读取资源管理器选中路径 | qk.Selection.GetFiles、qk.Files.GetExplorerPath/SetExplorerPath(后者另需激活窗口) |
| 通过复制读取前台选中文本 | qk.Selection.GetText |
| 捕获屏幕或窗口图像 / 在本机识别图像文字 | qk.Screen.Capture*、qk.Vision.* |
| 打开截图 Pro 并读取用户确认的区域信息 | qk.Screen.PickCapture/CapturePro |
| 读取本机文件和目录 | qk.Files 的读取类方法、qk.Files.Search |
| 读取、创建、修改或删除本机文件(删除默认不经过回收站) | qk.Files 的写入/复制/移动/删除/压缩类方法、qk.Image.Save、qk.Http.Download |
| 访问网络 | qk.Http.*、云端数据、临时分享 |
启动其他程序或打开文件/网址。qk.Process.Start/Run 与指定浏览器程序路径的 qk.Browser.Open 以普通权限(降权)启动;qk.Process.Open、关联文件、网址与通知点击动作遵循 Windows/系统 Shell 的权限行为,Quicker 以管理员运行时不保证降权 | qk.Process.*、qk.Browser.Open、带 click 的 qk.Ui.Notify |
| 调用本机其他动作或子程序,或停止正在运行的动作 | qk.Actions.Call/CallSubprogram/Stop/ShowContextMenu |
| 强制结束程序(可能丢失未保存数据) | qk.Window.Close(w, kill: true)、qk.Process.Kill |
| 让电脑睡眠、休眠、注销、关机或重启(未保存的工作可能丢失) | qk.Sys.Power 的 sleep/hibernate/signOut/shutdown/restart(锁屏 lock、关闭显示器 screenOff 不需确认) |
| 读取和操作浏览器页面 | qk.Browser 的标签页与元素操作 |
| 调用 AI 或翻译服务(发送内容到你配置的 AI 或 Quicker 服务器,消耗 AI 额度/Quicker 点数) | qk.Ai.* |
| 读取其他程序窗口中的界面元素 / 操作其他程序的界面元素 | qk.Uia 的查找类 / 操作类方法 |
| 监听你按下的键:可记录你输入的所有按键(包括密码),并可拦截按键不传给当前程序 | qk.Keyboard.WaitForKey |
| 控制 Quicker 本身(暂停/恢复、停止全部动作、切换动作页、重启 Quicker) | qk.Quicker.Command 的部分命令 |
| 读写你账号下的 Quicker 云端数据(所有动作、所有设备共享) | qk.Quicker.GetCloud/SetCloud/RemoveCloud |
| 上传内容到 Quicker 临时分享(生成他人可访问的网址) | qk.Quicker.ShareTemporary/ShareTemporaryFile |
| 读取可识别本机与你的信息(计算机名、用户名、局域网 IP、Quicker 用户标识、环境变量与注册表,可能含程序保存的密钥/令牌) | qk.Sys.Info、qk.Sys.GetEnv/GetRegistry、qk.Quicker.Info |
| 解密“自用加密”的数据 | qk.Quicker.DecryptLocal |
| 【高风险】在其他程序中执行脚本或命令 | qk.Browser.Eval/Command、qk.Apps.Run/Bridge/RunOfficeCommand |
| 【高风险】向其他程序的窗口发送任意窗口消息 | qk.Window.SendMessage |
| 【高风险】调用组合动作步骤(按步骤列出) | qk.Steps.Run |
少数参数会追加能力:Window.Close 的 kill、Window.ActivateProcess 的 hotkey(键盘)、Clipboard.SetFiles 的 cut(修改文件)、Ui.Notify 的 click(启动程序)写了非 false/null/空串的值时,会追加对应能力。
3.5 高风险提示的含义
确认对话框中标着 【高风险】 并单独成行的能力,意味着授权后脚本可以做到“几乎任何事”:
- 在其他程序中执行脚本或命令:Office 宏可以在该程序中以你的权限执行任意程序;浏览器页面脚本可以读写该页面及其登录状态。
- 向其他程序的窗口发送任意窗口消息:可以触发该程序的菜单命令、改写其中的内容或关闭窗口。
- 调用组合动作步骤:其中可以运行任意程序或命令的步骤会再单独一行警示。
此外,以下能力虽然不标【高风险】,但后果严重,AI 助手完成修改时也会专门提醒:强制结束程序、键盘监听、自用解密、控制 Quicker、电源/会话(睡眠、休眠、注销、关机、重启)。
3.6 源码无法识别时
Quicker 通过源码中的 qk.域.方法(...) 写法识别能力。如果脚本把 qk 或某个域赋给变量、当作参数传递,或写成 qk?.,Quicker 无法判断它会调用什么,会按“需要全部能力”处理:安装来源的动作会因此要求确认一长串能力。
看到一个来路不明的脚本申请了几乎所有能力,应当拒绝,并检查源码中是否有这类写法。编辑器“检查”会逐处提示位置与改写方式(直接写 qk.域.方法(...))。
4. 如何撤销授权
- 删除动作会同时清除它在本机的全部脚本授权;
- 导入并替换一个已有动作时,原动作的脚本授权会被清除,新内容需要重新确认;
- 目前没有单独的授权管理界面;删除动作会同时清除它的授权。如果你想收回某个安装来源动作的授权,可以删除该动作后重新安装或导入,运行时会重新询问。
自己编写的动作没有授权记录可撤销,因为它们本来就不经确认。
5. 什么情况下要警惕
运行来自他人的脚本(文件导入、聊天/论坛里复制的动作)前,请留意确认对话框中的能力组合:
| 能力组合 | 可能的风险 |
|---|---|
| 键盘监听 + 访问网络 | 记录你输入的内容(包括密码)并发送出去 |
| 读取文件 + 访问网络(或临时分享) | 把本机文件上传到外部 |
| 读取剪贴板 / 选中文本 + 访问网络 | 把你复制的内容(可能含账号、验证码)发送出去 |
| 自用解密 + 访问网络 | 解开其他动作用“自用加密”保存的秘密并外发 |
| 读写云端数据 | 云端数据由你账号下的所有动作、所有设备共享,脚本可读取或覆盖其他动作保存的数据 |
| 写入/删除文件 | 删除默认不经过回收站 |
| 强制结束程序 | 可能丢失未保存的工作 |
| 任何【高风险】能力 | 等同于允许脚本在其他程序中执行任意操作 |
| 申请了几乎全部能力 | 多半是源码中有无法识别的 qk 写法(第 3.6 节),或有意隐藏真实意图 |
其他需要注意的点:
- AI 代写的脚本:AI 助手写好并由你保存的脚本按“自建”处理,运行前不会确认。如果你让 AI 参考了网页或文件内容,这些内容可能夹带恶意指令,诱导 AI 写出“读取本机数据并发送到网络”的代码。请在运行前读一遍代码;AI 助手在一轮修改新增高风险能力或出现无法识别的
qk用法时会给出一行提醒,请务必留意。 qk.Ui.React页面:页面完全由脚本绘制,可以仿冒任意界面。不要在脚本弹出的界面里输入其他账号的密码。- “自用加密”不是强加密:
qk.Quicker.EncryptLocal的密钥只由你的 Quicker 账号决定,只适合避免明文落盘或与“加密”步骤互通,不能用来防范攻击者。 - 临时分享的网址任何人都能打开:不要用
qk.Quicker.ShareTemporary上传敏感内容。 - 在编辑器中运行就是真实执行,没有“试运行”或自动回滚。
6. 分享规则
脚本动作(包括内嵌了脚本动作的多操作动作)可以发布到分享平台,按以下规则判定:
- 用到哪些
qk成员都不影响能否分享。成员以后若有调整,旧脚本可能需要按编辑器“检查”的提示改写,这由作者按提示修复; - 源码中有无法识别的
qk用法(qk赋给变量、当参数传递、qk?.、只写了qk.域、写了不存在的成员)的动作不能分享,因为 Quicker 无法确认它会用到哪些能力(对方安装时也就无法准确地逐项确认)。分享被拒时会列出这些位置和改法,改正后即可分享; - 分享时会记录你使用的 Quicker 版本。比这个版本旧的 Quicker 打开该动作会提示“此动作需要 Quicker x.y 或更高版本”,更新后即可使用。
7. API 兼容
qk API 随 Quicker 版本演进;个别成员调整时,编辑器的“检查”会指出旧写法并给出新写法。错误码以英文大写字符串表示,判断失败原因时请用错误码,不要解析错误消息文字。