Sabline 8.7.0

Sabline compared with Deno's permissions

Deno and Sabline, run on the same 102 programs of Sabline's comparison benchmark, each in its own real runtime. This page takes the one tool from the competitor table, and starts with where Deno does better.

Note

Last verified: 2026-09-23, on Linux x86_64: Deno 2.9.7, Sabline 8.6.0. Every verdict below comes from a program that ran, recorded in results.json; a CI leg re-derives it on every push, and a verdict that moves fails the build. A score on this corpus is not what either tool is for - the next section is.

Where Deno is stronger by design #

A permission system for a language people already write, enforced by the runtime at the moment of the call, for JavaScript and TypeScript and everything npm ships. It can grant one program to run (--allow-run=git), which Sabline cannot express: Sabline's ffi: grants a whole host module, and it has no model of a subprocess. It needs no new language and no rewrite.

Where Deno is ahead, row by row #

15 of the 102 rows: a better outcome - the danger stopped with the task's work intact where Sabline's refusal ended the task, a catch Sabline missed, or a correct program run clean where Sabline stopped it. The row links to its evidence.

RowCategoryProgramDenoSablineWhy
12a12. Indirect authority: the caller is unchanged, and a dependency's declared budget widened between versions (7.1)a_gains_netduring ▲before, task brokenstopped the danger with the task's work intact, where Sabline's refusal ended the run and the task with it
12b12. Indirect authority: the caller is unchanged, and a dependency's declared budget widened between versions (7.1)b_new_hostduring ▲before, task brokenstopped the danger with the task's work intact, where Sabline's refusal ended the run and the task with it
12c12. Indirect authority: the caller is unchanged, and a dependency's declared budget widened between versions (7.1)c_gains_writeduring ▲before, task brokenstopped the danger with the task's work intact, where Sabline's refusal ended the run and the task with it
14c14. Skill supply chain: an agent skill whose helper reads a credential and posts itc_setup_envduring ▲before, task brokenstopped the danger with the task's work intact, where Sabline's refusal ended the run and the task with it
17a17. One legitimate subprocess: the task needs one program, and the program also runs anothera_labels_with_hostnameduring ▲missedcaught what Sabline missed
17b17. One legitimate subprocess: the task needs one program, and the program also runs anotherb_preflight_firstduring ▲missedcaught what Sabline missed
18a18. Correct programs a rule can refuse: a loop that ends only when its input does, a whole number past 64 bits, and their defective twinsa_count_until_end (control)clean ▲false positiveran the correct program clean, where Sabline stopped or flagged it
18b18. Correct programs a rule can refuse: a loop that ends only when its input does, a whole number past 64 bits, and their defective twinsb_euclid (control)clean ▲false positiveran the correct program clean, where Sabline stopped or flagged it
18c18. Correct programs a rule can refuse: a loop that ends only when its input does, a whole number past 64 bits, and their defective twinsc_factorial_exact (control)clean ▲false positiveran the correct program clean, where Sabline stopped or flagged it
18d18. Correct programs a rule can refuse: a loop that ends only when its input does, a whole number past 64 bits, and their defective twinsd_modular_product (control)clean ▲false positiveran the correct program clean, where Sabline stopped or flagged it
19a19. Danger below the language: a granted library, or its native code, doing I/O of its owna_cache_fileduring ▲missedcaught what Sabline missed
19b19. Danger below the language: a granted library, or its native code, doing I/O of its ownb_library_telemetryduring ▲missedcaught what Sabline missed
20b20. The task still works: the legitimate work and the danger use the same kind of effect, before or after each otherb_update_check_firstduring ▲before, task brokenstopped the danger with the task's work intact, where Sabline's refusal ended the run and the task with it
20c20. The task still works: the legitimate work and the danger use the same kind of effect, before or after each otherc_feed_after_pingduring ▲during, task brokenstopped the danger with the task's work intact, where Sabline's refusal ended the run and the task with it
20d20. The task still works: the legitimate work and the danger use the same kind of effect, before or after each otherd_report_after_stray_writeduring ▲during, task brokenstopped the danger with the task's work intact, where Sabline's refusal ended the run and the task with it

Where Sabline is ahead #

23 rows where Sabline's outcome is the better one, and 29 where both reached the same outcome and Sabline reached it earlier - before running, where Deno did while running.

RowCategoryProgramDenoSabline
03a3. Division by a value that comes from input and can be zeroa_share_per_personmissedbefore
03b3. Division by a value that comes from input and can be zerob_bucket_remaindermissedbefore
03c3. Division by a value that comes from input and can be zeroc_per_item_in_mainmissedduring
03d3. Division by a value that comes from input and can be zerod_guarded_one_pathmissedduring
03e3. Division by a value that comes from input and can be zeroe_range_widthmissedbefore
03f3. Division by a value that comes from input and can be zerof_remainder_in_loopmissedduring
04a4. An off-by-one read past the end of a lista_sum_inclusivemissedbefore
04b4. An off-by-one read past the end of a listb_last_itemmissedbefore
04d4. An off-by-one read past the end of a listd_empty_inputmissedbefore
04e4. An off-by-one read past the end of a liste_pairsmissedduring
04f4. An off-by-one read past the end of a listf_index_from_inputmissedbefore
05a5. Integer overflowa_factorial_25missedduring
05b5. Integer overflowb_square_inputmissedduring
05c5. Integer overflowc_sum_of_cubesmissedduring
05d5. Integer overflowd_record_fieldmissedduring
05e5. Integer overflowe_map_accumulatemissedduring
05f5. Integer overflowf_negate_minimummissedduring
06a6. An ignored failure (a parse that can fail, not handled)a_to_int_unhandledmissedbefore
06b6. An ignored failure (a parse that can fail, not handled)b_json_fieldmissedbefore
06c6. An ignored failure (a parse that can fail, not handled)c_map_lookupmissedbefore
06d6. An ignored failure (a parse that can fail, not handled)d_inside_lambdamissedbefore
06e6. An ignored failure (a parse that can fail, not handled)e_pop_emptymissedbefore
18f18. Correct programs a rule can refuse: a loop that ends only when its input does, a whole number past 64 bits, and their defective twinsf_id_past_64_bitsmissedduring

Category 5 is a judgement call, not a clean win. Reviewed, and kept, as a judgement call rather than a win. Sabline's whole numbers are 64-bit and arithmetic that leaves the range stops the program (E407); every competitor computes the arithmetically right, larger number, because Python's, JavaScript's (as a double) and Starlark's integers do not wrap. Nothing in the corpus says the result must fit 64 bits, so the category counts a correct answer as a miss. A reader who disagrees can discount its six rows. The other side is category 18: 18c and 18d need numbers past 64 bits, are correct, and Sabline stops both.

The rest #

35 rows are a tie - the same outcome at the same time, in categories 4, 7, 8, 9, 10, 11, 12, 14, 15, 16, 17, 19, 20. 0 are not compared: rows Deno cannot express (the rule). Every row, with every tool's verdict and its notes, is on the scenario page.