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
+38
View File
@@ -1,6 +1,7 @@
# frozen_string_literal: true
require_relative 'test_helper'
ENV['EDITOR'] = 'true' # a test must never open a real editor
require 'pty'
require_relative '../lib/rdb'
@@ -416,6 +417,29 @@ class FastAccessTest < RdbCase
run3('unlock', 'inventory', '333', '15', '25')
end
def test_lock_directory_is_private
run3('lock', 'inventory', '111', '10', '20', '0', '0')
dir = File.join(Dir.tmpdir, "rdb-locks-#{Process.uid}")
assert_equal 0o700, File.stat(dir).mode & 0o777
run3('unlock', 'inventory', '111', '10', '20')
end
def test_vilock_refuses_a_table_that_is_already_locked
write('LOCKinventory', 'x')
_o, e, st = run3('vilock', 'inventory')
refute st.success?
assert_match(/is locked/, e)
assert File.exist?(File.join(@dir, 'inventory'))
end
def test_vilock_edits_with_an_editor_that_has_arguments
out, _e, st = Open3.capture3({ 'EDITOR' => 'sh -c "echo edited >> \"$0\""', 'PATH' => "#{BIN}:#{ENV['PATH']}" },
File.join(BIN, 'vilock'), 'inventory', chdir: @dir)
assert st.success?, out
assert_match(/edited/, File.read(File.join(@dir, 'inventory')))
refute File.exist?(File.join(@dir, 'LOCKinventory'))
end
def test_enter_appends_rows
out = rdb('enter', '-1', 'inventory', stdin: "8\n2\n3\n4\nnew thing\n")
assert_includes out, 'Item: '
@@ -468,6 +492,20 @@ class ReportTest < RdbCase
assert_equal "Ronald McDonald|Memphis\n|<Nope>\nChiquita Banana|San Jose\n|<Nope>\n", rdb('report', 'f2', file: 'maillist')
end
def test_report_does_not_run_commands_hidden_in_data
write('evil', "Name\tCmd\n----\t---\nx\ttouch PWNED; echo\n")
write('f3', "<!echo <Cmd>!>\n")
out = rdb('report', 'f3', file: 'evil')
assert_equal "touch PWNED; echo\n\n", out
refute File.exist?(File.join(@dir, 'PWNED'))
end
def test_screen_rejects_unsafe_variable_names
_o, e, st = run3('screen', stdin: "<a b; touch X>\n")
refute st.success?
assert_match(/not a valid shell variable name/, e)
end
def test_label
assert_equal "Ronald McDonald\nMcDonalds\n123 Mac Attack\nMemphis, TENN 30000\n", rdb('label', file: 'maillist').lines.first(4).join
end