#CCSP2026A. 沙箱代理审计
沙箱代理审计
题目来自 CCSP2026 T1,评测使用官方数据和自造高质量复刻数据。我们承认原始题面、大样例、官方数据版权均归中国计算机学会(CCF)所有,因此题面与评测服务均免费对外开放。如果您认为我们侵犯了您的权益,可联系我们。
综合数据范围、民间数据、场上选手提交,我们将原本时空限制的 1.0 秒/512 MB 调整为 5.0 秒/2048 MB。
由于官方数据在正确性与时间空间强度均过弱,我们将给出子任务内的数据分布:对于子任务 1 到 3,前 2 个数据为官方数据;对于子任务 4,前 4 个数据为官方数据;子任务内的其余后续数据均为民间数据。当前 3 个子任务评测通过后才会开启子任务 4 的评测。
目前一部分用户的已通过代码仍旧可以被持续 hack,但是综合考虑后我们决定不再新增 hack 数据。
时间限制: 1.0 秒 5.0 秒
空间限制: 512 MB 2048 MB
题目描述
某代码平台允许自动化代理(Agent)读取文件、修改工作区和执行命令,并通过沙箱规则控制权限。请你实现一个审计器,按顺序处理授权和工具调用,判断每次调用能否执行,并维护文件的存在状态。
1. 初始状态
所有代理共用权限规则和文件状态。初始时没有文件,也没有任何权限。授权一旦加入便始终有效。代理编号仅标识来源,不影响审计结果。
2. 路径规范化
文件用相对路径表示。路径只包含小写字母、数字、点号 . 和斜杠 /,不含下划线 _,不以 / 开头或结尾,也不含连续的 /。
路径以 / 分隔为若干段。测试数据可能出现 .、.. 路径段。把路径按 / 切分后,逐段比较该段的全部内容:某段恰好为 . 时,按当前目录处理;某段恰好为 .. 时,按上一级目录处理。只要这一段还含有其他字符,它就是普通名称,不作特殊处理。例如,...、....、.git、a..b 均为普通名称。
处理任何路径前,均须从左到右进行规范化:
- 遇到
.段时,忽略该段; - 遇到
..段时,删除前面最近的一个尚未被删除的普通路径段; - 遇到其他路径段时,保留该段。
输入保证规范化过程中不会越过沙箱根目录,且规范化结果非空。权限规则、目录边界匹配和文件存在性判断均使用规范化后的路径。
例如,./src 规范化后为 src;docs/./guide/../readme 与 docs/readme 表示同一个文件;规则路径 src/lib/.. 规范化后为 src;pkg/.../file 规范化后仍为 pkg/.../file。
3. 权限规则
权限分为读、写和执行三类,分别授权,互不替代。
READ p:允许读取路径p及其所有子路径;WRITE p:允许写入或删除路径p及其所有子路径;EXEC c:允许执行以完整单词序列c为前缀的命令。
路径按目录边界匹配:规则 src 能匹配 src、src/main.c 和 src/lib/a.c,但不能匹配 src2/main.c。
命令按空格分词后匹配:只有调用命令开头的若干个完整单词与某条执行规则完全相同时,才具有执行权限。例如,规则 git status 能匹配 git status 和 git status -s,但不能匹配 git 或 git status2。
4. 工具调用与判定顺序
调用有以下四种操作。文件操作只处理参数指定的那个文件,不递归处理其他路径。
| 操作 | 所需权限 | 成功条件及效果 |
|---|---|---|
read |
读权限 | 文件已存在;不改变文件状态。 |
write |
写权限 | 不要求文件已存在;成功后文件存在。 |
delete |
文件已存在;成功后文件不存在。 | |
exec |
执行权限 | 命令匹配至少一条执行规则;不改变文件状态。 |
对每条调用,严格按以下顺序判断:
- 若缺少所需权限,输出
DENIED,文件状态不变; - 否则,若操作为
read或delete,且文件不存在,输出ERROR,文件状态不变; - 否则,输出
OK,并按上表更新文件状态。
输入格式
从标准输入读入数据。
第一行包含一个整数 ,表示事件数量。接下来 行,每行是一条事件,格式为以下四种之一:
ALLOW_READ p
ALLOW_WRITE p
ALLOW_EXEC c
CALL id op arg
前三种事件分别增加一条读、写或执行规则。p 为路径;c 为命令前缀,可以包含空格,取该行 ALLOW_EXEC 之后的完整内容。
CALL 表示一次工具调用。id 为代理编号,op 为 read、write、delete、exec 之一。参数 arg 不含空格:
- 当
op不是exec时,arg为路径; - 当
op为exec时,arg用下划线_表示命令中的空格。判断前须先将_还原为空格,例如git_status_-s表示git status -s。真实命令单词中不含下划线。
只有 CALL 中的命令参数使用上述下划线编码;输入中的所有路径(包括 op 不是 exec 时的 CALL arg)均不含下划线 _。
输出格式
输出到标准输出。
对每条 CALL 事件输出一行 OK、DENIED 或 ERROR,顺序与调用出现的顺序相同。授权事件不产生输出。
10
CALL 1 read src/main.c
ALLOW_WRITE src
CALL 1 write src/main.c
ALLOW_READ src
CALL 2 read src/main.c
CALL 1 delete src/main.c
CALL 2 read src/main.c
ALLOW_EXEC git status
CALL 1 exec git_status_-s
CALL 1 exec git_commit
DENIED
OK
OK
OK
ERROR
OK
DENIED
样例 1 解释
样例共有 7 条调用,输出 7 行。
- 首次读取未授权,输出
DENIED; - 写入、读取、删除依次成功;
- 再次读取时文件已不存在,输出
ERROR; git status -s匹配规则git status,输出OK;git commit不匹配,输出DENIED。
子任务
对于所有测试数据,;每个路径和命令的长度不超过 ;代理编号不超过 。所有路径均满足前述规范化保证。
本题采用捆绑测试,你只有通过一个子任务中的所有测试点才能得到该子任务的分数。
| 子任务 | 分值 | 特殊限制 |
|---|---|---|
| 1 | 20 | 调用操作只有 read 和 write |
| 2 | 规范化后,仅测试权限规则与调用路径完全相同的匹配,不测试祖先目录匹配 | |
| 3 | 不包含 ALLOW_EXEC 和 exec |
|
| 4 | 40 | 无 |