ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
shell_invocation_selftest_cases.py
Go to the documentation of this file.
1# SPDX-License-Identifier: MIT
2# Copyright (c) 2026 Brighton Sikarskie
3"""Inert case data for the structural shell-caller policy selftest."""
4
5from __future__ import annotations
6
7from shell_entrypoint_policy import (
8 ShellDialect,
9 ShellPolicy,
10 ShellSecurity,
11 ShellUsage,
12)
13
14INSTALL = "scripts/ci/install_unicorn.sh"
15INFRA = "infra/network/ap_openwrt.sh"
16EXTENSIONLESS = "scripts/git/pre-commit"
17SOURCED = "scripts/hil/lib/bench_lock.sh"
18DUAL = "scripts/ci/lib/tool_env.sh"
19RELEASE_LOADER_REL = "scripts/dev/provision_dev_box_toolchain.sh"
20RELEASE_LOADER_CALL = (
21 'source_release_selftest_helper_from "$main" "$helper" '
22 '"$expected_dir" "$expected_digest" || return 1'
23)
24RELEASE_FIXTURE_REL = "scripts/dev/provision_dev_box_toolchain_selftest.bash"
25RELEASE_FIXTURE_CALL = (
26 'source_release_selftest_helper_from "$main" "$helper" "$directory" "$digest" || status=$?'
27)
28
29
30def _policy(
31 security: ShellSecurity,
32 usage: ShellUsage,
33 *,
34 executable: bool,
35 privileged_parent: bool = False,
36) -> ShellPolicy:
37 """Build one compact inert typed-policy fixture."""
38 return ShellPolicy(
39 security,
40 usage,
41 ShellDialect.BASH,
42 executable=executable,
43 source_requires_privileged_parent=privileged_parent,
44 )
45
46
47POLICIES = {
48 INSTALL: _policy(ShellSecurity.PRIVILEGED, ShellUsage.ENTRY, executable=True),
49 INFRA: _policy(ShellSecurity.PRIVILEGED, ShellUsage.ENTRY, executable=True),
50 EXTENSIONLESS: _policy(ShellSecurity.PRIVILEGED, ShellUsage.ENTRY, executable=True),
51 SOURCED: _policy(
52 ShellSecurity.PRIVILEGED,
53 ShellUsage.SOURCED_ONLY,
54 executable=False,
55 privileged_parent=True,
56 ),
57 DUAL: _policy(ShellSecurity.PORTABLE, ShellUsage.DUAL_USE, executable=False),
58}
59PRIVILEGED_CALLER = _policy(
60 ShellSecurity.PRIVILEGED,
61 ShellUsage.ENTRY,
62 executable=True,
63)
64PORTABLE_CALLER = _policy(ShellSecurity.PORTABLE, ShellUsage.ENTRY, executable=True)
65SOURCED_CALLER = _policy(
66 ShellSecurity.PRIVILEGED,
67 ShellUsage.SOURCED_ONLY,
68 executable=False,
69 privileged_parent=True,
70)
71UNBOUND_SOURCED_CALLER = _policy(
72 ShellSecurity.PRIVILEGED,
73 ShellUsage.SOURCED_ONLY,
74 executable=False,
75)
76NONEXECUTABLE_CALLER = _policy(
77 ShellSecurity.PRIVILEGED,
78 ShellUsage.ENTRY,
79 executable=False,
80)
81SH_CALLER = ShellPolicy(
82 ShellSecurity.PRIVILEGED,
83 ShellUsage.ENTRY,
84 ShellDialect.POSIX_SH,
85 executable=True,
86 source_requires_privileged_parent=False,
87)
88
89RELEASE_LOADER_CASES = (
90 (RELEASE_LOADER_REL, PRIVILEGED_CALLER, RELEASE_LOADER_CALL, False, "exact loader rejected"),
91 (
92 RELEASE_FIXTURE_REL,
93 SOURCED_CALLER,
94 RELEASE_FIXTURE_CALL,
95 False,
96 "exact fixture loader rejected",
97 ),
98 (
99 RELEASE_LOADER_REL,
100 PRIVILEGED_CALLER,
101 f"source_release_selftest_helper_from() {{\n :\n}}\n{RELEASE_LOADER_CALL}",
102 False,
103 "loader definition treated as a call",
104 ),
105 (
106 "scripts/dev/other.sh", # PATHREF-OK: synthetic wrong-loader fixture
107 PRIVILEGED_CALLER,
108 RELEASE_LOADER_CALL,
109 True,
110 "wrong file accepted",
111 ),
112 (RELEASE_LOADER_REL, None, RELEASE_LOADER_CALL, True, "wrong caller accepted"),
113 (
114 RELEASE_LOADER_REL,
115 PORTABLE_CALLER,
116 RELEASE_LOADER_CALL,
117 True,
118 "portable caller accepted",
119 ),
120 (
121 RELEASE_LOADER_REL,
122 SOURCED_CALLER,
123 RELEASE_LOADER_CALL,
124 True,
125 "sourced-only caller accepted",
126 ),
127 (
128 RELEASE_LOADER_REL,
129 NONEXECUTABLE_CALLER,
130 RELEASE_LOADER_CALL,
131 True,
132 "non-executable caller accepted",
133 ),
134 (RELEASE_LOADER_REL, SH_CALLER, RELEASE_LOADER_CALL, True, "non-Bash caller accepted"),
135 (
136 RELEASE_FIXTURE_REL,
137 PRIVILEGED_CALLER,
138 RELEASE_FIXTURE_CALL,
139 True,
140 "fixture entry caller accepted",
141 ),
142 (
143 RELEASE_FIXTURE_REL,
144 UNBOUND_SOURCED_CALLER,
145 RELEASE_FIXTURE_CALL,
146 True,
147 "fixture unbound source parent accepted",
148 ),
149 (
150 "scripts/dev/other_selftest.bash", # PATHREF-OK: synthetic wrong-selftest fixture
151 SOURCED_CALLER,
152 RELEASE_FIXTURE_CALL,
153 True,
154 "fixture wrong file accepted",
155 ),
156 (
157 RELEASE_FIXTURE_REL,
158 SOURCED_CALLER,
159 RELEASE_FIXTURE_CALL.replace("source_release_selftest_helper_from", "source"),
160 True,
161 "fixture wrong function accepted",
162 ),
163 (RELEASE_FIXTURE_REL, SOURCED_CALLER, "", True, "missing fixture loader call accepted"),
164 (
165 RELEASE_FIXTURE_REL,
166 SOURCED_CALLER,
167 f"{RELEASE_FIXTURE_CALL} extra",
168 True,
169 "extra fixture loader argument accepted",
170 ),
171 (
172 RELEASE_FIXTURE_REL,
173 SOURCED_CALLER,
174 RELEASE_FIXTURE_CALL.replace('"$main" "$helper"', '"$helper" "$main"'),
175 True,
176 "reordered fixture loader arguments accepted",
177 ),
178 (
179 RELEASE_FIXTURE_REL,
180 SOURCED_CALLER,
181 RELEASE_FIXTURE_CALL.replace('"$digest"', '"$helper"'),
182 True,
183 "substituted fixture loader argument accepted",
184 ),
185 (
186 RELEASE_FIXTURE_REL,
187 SOURCED_CALLER,
188 RELEASE_FIXTURE_CALL.replace(' "$main"', ' \\\n "$main"'),
189 True,
190 "continued fixture loader argv accepted",
191 ),
192 (
193 RELEASE_FIXTURE_REL,
194 SOURCED_CALLER,
195 RELEASE_FIXTURE_CALL.replace("source_release_selftest_helper_from ", "$loader "),
196 True,
197 "indirect fixture loader command accepted",
198 ),
199 (
200 RELEASE_LOADER_REL,
201 PRIVILEGED_CALLER,
202 RELEASE_LOADER_CALL.replace("source_release_selftest_helper_from", "source"),
203 True,
204 "wrong loader function accepted",
205 ),
206 (RELEASE_LOADER_REL, PRIVILEGED_CALLER, "", True, "missing loader call accepted"),
207 (
208 RELEASE_LOADER_REL,
209 PRIVILEGED_CALLER,
210 f"{RELEASE_LOADER_CALL} extra",
211 True,
212 "extra loader argument accepted",
213 ),
214 (
215 RELEASE_LOADER_REL,
216 PRIVILEGED_CALLER,
217 RELEASE_LOADER_CALL.replace('"$main" "$helper"', '"$helper" "$main"'),
218 True,
219 "reordered loader arguments accepted",
220 ),
221 (
222 RELEASE_LOADER_REL,
223 PRIVILEGED_CALLER,
224 RELEASE_LOADER_CALL.replace('"$expected_digest"', '"$helper"'),
225 True,
226 "substituted loader argument accepted",
227 ),
228 (
229 RELEASE_LOADER_REL,
230 PRIVILEGED_CALLER,
231 f"{RELEASE_LOADER_CALL}\n{RELEASE_LOADER_CALL}",
232 True,
233 "duplicate loader call accepted",
234 ),
235 (
236 RELEASE_FIXTURE_REL,
237 SOURCED_CALLER,
238 f"{RELEASE_FIXTURE_CALL}\n{RELEASE_FIXTURE_CALL}",
239 True,
240 "duplicate fixture loader call accepted",
241 ),
242 (
243 RELEASE_LOADER_REL,
244 PRIVILEGED_CALLER,
245 RELEASE_LOADER_CALL.replace(' "$main"', ' \\\n "$main"'),
246 True,
247 "continued loader argv accepted",
248 ),
249 (
250 RELEASE_LOADER_REL,
251 PRIVILEGED_CALLER,
252 RELEASE_LOADER_CALL.replace("source_release_selftest_helper_from ", "$loader "),
253 True,
254 "indirect loader command accepted",
255 ),
256)
257
258SHELL_CASES = (
259 (f"/bin/bash -p {INSTALL}\n", 0, "exact privileged argv rejected"),
260 (f"/bin/bash -p {INSTALL} --prefix /tmp/x\n", 0, "target arguments rejected"),
261 (f"/bin/bash -p -- {INSTALL}\n", 1, "extra interpreter option accepted"),
262 (f"./{INSTALL}\n", 0, "direct verified entry rejected"),
263 (f"$ROOT/{INSTALL} --help\n", 0, "literal rooted direct entry rejected"),
264 (f"/usr/bin/bash {INSTALL}\n", 1, "/usr/bin/bash accepted"),
265 (f"/usr/local/bin/bash {INSTALL}\n", 1, "/usr/local/bin/bash accepted"),
266 (f'"/bin/bash" {INSTALL}\n', 1, "quoted weak Bash accepted"),
267 (f"/bin/ba\\\nsh {INSTALL}\n", 1, "split weak Bash accepted"),
268 ("bash scripts/ci/\\\ninstall_unicorn.sh\n", 1, "split target accepted"),
269 (
270 f"/bin/bash -p {INSTALL}\nbash scripts/ci/\\\ninstall_unicorn.sh\n",
271 1,
272 "exact plus weak child accepted",
273 ),
274 (f'runner=/bin/bash; "$runner" {INSTALL}\n', 1, "variable Bash accepted"),
275 (f'script={INSTALL}; /bin/bash -p "$script"\n', 1, "variable target accepted"),
276 (f"/bin/bash -p {INFRA}\n", 0, "infra target rejected"),
277 (f"/bin/bash -p {EXTENSIONLESS}\n", 0, "extensionless target rejected"),
278 (f"/bin/bash -p {SOURCED}\n", 1, "sourced-only target executed"),
279 (f"source {SOURCED}\n", 1, "unprivileged source parent accepted"),
280 (f"source {DUAL}\n", 0, "portable dual-use source rejected"),
281 (f"exec /bin/bash -p {INSTALL} --help\n", 0, "exec prefix rejected"),
282 (f"FILES=(\n {SOURCED}\n)\n", 0, "array data treated as a sourced-helper launch"),
283 (
284 'OWNER_BASH=/bin/bash\n[[ -x "$OWNER_BASH" ]]\n',
285 0,
286 "conditional path data treated as an indirect launch",
287 ),
288 (f"/bin/bash -p -n {INSTALL}\n", 1, "unregistered interpreter-option accepted"),
289 (
290 f"printf '%s\\n' item | xargs -P 2 -I{{}} /bin/bash -p {INSTALL} {{}}\n",
291 0,
292 "xargs protected child argv rejected",
293 ),
294 (
295 f"printf '%s\\n' item | xargs -P 2 -I{{}} bash {INSTALL} {{}}\n",
296 1,
297 "xargs weak child argv accepted",
298 ),
299)
300
301PYTHON_CASES = (
302 (
303 f'import subprocess\nsubprocess.run(["/bin/bash", "-p", "{INSTALL}"])\n',
304 0,
305 "safe Python argv rejected",
306 ),
307 (
308 f'import subprocess\nsubprocess.run(["/bin/bash", "{INSTALL}"])\n',
309 1,
310 "weak Python argv accepted",
311 ),
312 (
313 f'import subprocess\na=["/usr/bin/bash", "{INSTALL}"]\nsubprocess.run(a)\n',
314 1,
315 "Python argv dataflow accepted",
316 ),
317 (
318 f'FIXTURE = "/usr/bin/bash {INSTALL}"\n',
319 0,
320 "inert Python fixture string treated as a process launch",
321 ),
322)
323
324SURFACE_CASES = (
325 (f'{{"command":"/bin/bash","args":["{INFRA}"]}}', "json", 1, "JSON weak"),
326 (
327 f'{{"command":"/bin/bash","args":["-p","{INFRA}"]}}',
328 "json",
329 0,
330 "grouped JSON argv was re-scanned as detached args",
331 ),
332 (f"run: /usr/bin/bash {INSTALL}\n", "yaml", 1, "YAML weak argv accepted"),
333 (
334 f"run: >-\n /bin/bash -p\n {INSTALL}\n --help\n",
335 "yaml",
336 0,
337 "YAML folded exact privileged argv rejected",
338 ),
339 (
340 f"run: >-\n bash\n {INSTALL}\n --help\n",
341 "yaml",
342 1,
343 "YAML folded weak argv accepted",
344 ),
345 (
346 f"run: >-\n /bin/bash -p\n {{{{ (repo_dir ~ '/{INSTALL}') | quote }}}}\n",
347 "yaml",
348 0,
349 "YAML quoted literal-path template rejected",
350 ),
351 (
352 f"run: >-\n bash\n {{{{ (repo_dir ~ '/{INSTALL}') | quote }}}}\n",
353 "yaml",
354 1,
355 "YAML weak templated argv accepted",
356 ),
357 (
358 f"run: >-\n /bin/bash -p\n {{{{ (repo_dir ~ '/{INSTALL}') }}}}\n",
359 "yaml",
360 1,
361 "YAML unquoted path template accepted",
362 ),
363 (
364 f"description: /usr/bin/bash {INSTALL}\n",
365 "yaml",
366 0,
367 "YAML data field treated as a command",
368 ),
369 (f"RUN /usr/local/bin/bash {INSTALL}\n", "docker", 1, "Docker weak argv"),
370 (
371 f"```shell\n/bin/bash {INSTALL}\n```\n",
372 "markdown",
373 1,
374 "Markdown shell weak argv accepted",
375 ),
376 (
377 f'```json\n{{"command":"/bin/bash","args":["{INFRA}"]}}\n```\n',
378 "markdown",
379 1,
380 "Markdown JSON weak argv accepted",
381 ),
382 (
383 f"The historical spelling `/usr/bin/bash {INSTALL}` is prose.\n",
384 "markdown",
385 0,
386 "Markdown prose treated as executable",
387 ),
388)
389
390JUST_CASES = (
391 (
392 f"safe image:\n #!/bin/bash -p\n source {SOURCED}\n",
393 0,
394 "privileged Just source context rejected",
395 ),
396 (
397 f"weak image:\n #!/usr/bin/env bash\n source {SOURCED}\n",
398 1,
399 "portable Just source context accepted",
400 ),
401 (f"direct:\n @/bin/bash -p {INSTALL}\n", 0, "Just quiet prefix broke exact argv"),
402 (
403 'clean := "/usr/bin/env -i PATH=/usr/bin:/bin"\n'
404 f"setup:\n {{{{ clean }}}} /bin/bash -p {INSTALL}\n",
405 0,
406 "Just clean-environment prefix broke exact protected argv",
407 ),
408)