Sicherheit: report/screen maskieren Shell-Eingaben, Sperren privat und atomar

report setzt Zellwerte in <!befehl!> maskiert ein, screen verlangt gültige
Variablennamen, lock/unlock nutzen /tmp/rdb-locks-<UID> mit flock, vilock
sperrt per Hardlink. EDITOR darf Argumente haben. Doku und Tests ergänzt.
This commit is contained in:
wkh
2026-10-30 09:45:18 +01:00
parent df8bcdfaf1
commit 9f6c450492
7 changed files with 203 additions and 14 deletions
+7 -1
View File
@@ -2,13 +2,17 @@
# Reports, forms and mailing lists.
require 'shellwords'
# Fill in a form for one row: <Column> is replaced by the value, <!command!>
# by the output of the shell command, and <!cmd <Column>!> passes data to it.
# Values inside a command are shell-escaped, so a cell can never add commands
# of its own; they arrive as one word each (do not put them in quotes).
def fill_form(form, head, row)
values = head.zip(row).to_h { |h, v| [h.strip, v.to_s] }
form.gsub(/<!(.*?)!>|<([^<>!\n]*)>/m) do
if Regexp.last_match(1)
cmd = Regexp.last_match(1).gsub(/<([^<>!\n]*)>/) { values.fetch(Regexp.last_match(1).strip, Regexp.last_match(0)) }
cmd = Regexp.last_match(1).gsub(/<([^<>!\n]*)>/) { Shellwords.escape(values.fetch(Regexp.last_match(1).strip, Regexp.last_match(0))) }
`#{cmd}`
else
name = Regexp.last_match(2).strip
@@ -57,6 +61,8 @@ Rdb.register('screen', 'Convert a form into a screen-input shell program', 'scre
reads << format('cursor %2d %2d ; %s;', n + 1, col, m[1].strip)
else
names << m[2].strip
# the name becomes a shell variable in the generated program
die "screen: '#{m[2].strip}' is not a valid shell variable name" unless names.last.match?(/\A[A-Za-z_]\w*\z/)
reads << format('cursor %2d %2d ; read %s;', n + 1, col, m[2].strip)
end
out[m.begin(0), m[0].size] = ' ' * m[0].size