namespace eval secret {}The keeper of the secrets, the proc that may change values: proc secret::keeper {name val} {
variable $name $val
protect [namespace current]::$name $val
}The (oversimplified) protection mechanism: proc protect {name val} {trace var $name w [list check $val]}
proc check {val name el op} {
if {[info level]<2 || [lindex [info level -1] 0] ne "secret::keeper"} {
uplevel 1 [list set $name $val]
error "forbidden"
}
}Testing - first set such a variable:% secret::keeper foo 42Trying to change it directly:
% set secret::foo 45 can't set "secret::foo": forbiddenThe variable is unchanged.
% set secret::foo 42Now let's build a little attacker proc that tries the same:
% proc intruder {name value} {set secret::$name $value}and testing:% intruder foo 666 can't set "secret::foo": forbiddenChecking whether we still have the original value:
% set secret::foo 42But the keeper of the secret can still change it to his heart's delight:
% secret::keeper foo 123 % set secret::foo 123Of course this isn't really secure - you just have to know the privileged name secret::keeper ...
Arts and crafts of Tcl-Tk programming

