On 13.07.2026 15:43, Jean Louis Faucher wrote:


On 13 Jul 2026, at 13:10, Rony G. Flatscher <[email protected]> wrote:

A few thoughts about the security manager: it exists to allow for supervising running Rexx programs. There are sensible instructions/actions in the language that could be exploited in a malevolent manner; one can mitigate this by appointing a security manager to determine how to handle them.

Sensible instructions/actions are calls to external routines or commands, access to stream-related built-in functions (charin, charout, chars, linein, lineout, lines, stream), requiring (calling) packages/programs, access to any protected method, and access to the environment directories .local and .environment.

All of this has been working in ooRexx since its existence; ooRexx 5.0.0 broke the supervision of static requires directives, and it still does not work, which makes the whole concept of a security manager moot, it seems.

Looking at the security manager-related APIs, there are three classes that possess a setSecurityManager method: .routine, .package, and .method. How about adding an optional new trailing "securityManager" argument to their constructors? Supplying it would cause the supervision messages (CALL, COMMAND, STREAM, METHOD, REQUIRES, LOCAL, ENVIRONMENT) to be sent to the supplied security manager. Could that mitigate the situation regarding REQUIRES?


I don't know.
Months ago, I worked on this, but I've forgotten most of the details.

https://sourceforge.net/p/oorexx/mailman/oorexx-devel/thread/c728c239-9ac8-494c-b85d-5a38abe5ed31%40wu.ac.at/#msg59259308


I remember that a security manager at the interpreter level catches the 
::requires.

+1 +1 +1


https://sourceforge.net/p/oorexx/patches/223/
That was a WIP, was interruped because of a recursion problem with a BSF test 
case.
And that would probably reduce performance because all security checkpoints would be triggered everywhere.

What would be your assessment in the light of your patch v3? Would the 
recursion problem be solvable?

In principle being able to set a security manager (temporarily) for an ooRexx instance may be very helpful in certain use-cases (e.g., to get statistics about security checkpoints triggered by an application with all its constituents; to get coarse profiling data, etc.), and performance then might not be a critical factor for such use cases at all.

I would be very much in favor of getting this WIP into production as its considerable value for developing and testing professional ooRexx applications!

---

Still, I wonder whether it would be become possible again for routine, method and package "code blocks" to get the REQUIRES security checkpoint to be triggered for them?

Even if a solution is not backwardly compatible (like the idea with supplying an optional security manager argument when creating routines, methods and packages; or allowing to set a default security manager at the class level of .routine, .method, .package that would be used at creation time; ...).


---

Another concern is that the setSecurityManager method is not protected. This allows a code block (from a routine, method, or package) to use it to set/change, or remove a security manager.


Well, they are protected (P in col 7).

ooRexx[sh]> ?m setSecurityManager

P. P.GP.   'SETSECURITYMANAGER' : 'Method' (REXX)

P. P.GP.   'SETSECURITYMANAGER' : 'Package' (REXX)

P. P.GP.   'SETSECURITYMANAGER' : 'Routine' (REXX)

Yes, you are right, sorry!

Missed the respective METHOD check points in the (locally overwhelming) debug output, very sorry for the noise!


---

When experimenting with this ability (to change the security manager from within the supervised code block), the following observations were taken:

  * the security manager of the supervised code block wil get the supervise 
messages CALL,
    COMMAND, STREAM, METHOD, REQUIRES (for dynamic requires only!), LOCAL, 
ENVIRONMENT

  * removing the security manager of the supervised code block by sending
    ".context~executable~setSecurityManager": this affects the supervise 
messages CALL, COMMAND,
    LOCAL, ENVIRONMENT, and STREAM, which do not get sent anymore. However, the 
supervise
    messages METHOD, REQUIRES still get sent to the originally set security 
manager, which seems
    to be a bug

  * adding a new security manager to the code block by
    sending ".context~executable~setSecurityManager(.allowAll~new)": this 
affects the supervise
    messages CALL, COMMAND, LOCAL, ENVIRONMENT, which get sent to the new 
security manager.
    However, the supervise message STREAM does not get sent to it; the 
supervise messages METHOD,
    REQUIRES still get sent to the originally set security manager, which seems 
to be a bug

So something is wrong when changing the security managers for code blocks depending on the supervise messages:

  * the original security manager for the supervise messages METHOD, REQUIRES 
does not get changed
  * the supervise message STREAM, once the security manager got removed, does 
not get
    re-established to a newly set security manager

---

It is interesting to note, and potentially a bug, that accessing some environment symbols are not supervised (neither the LOCAL nor the ENVIRONMENT supervise message gets sent), e.g. .Object, .true


I think that .True is no longer an environment symbol.

According to "1.13.6. Environment Symbols" (documenting short-circuits introduced with 5.0 if recalling correctly), and "Chapter 6. Rexx Runtime Objects" .True is an environment symbol.

Here the full list of the entries in .local and .environment:

   C:\Users\Administrator>rexxtry
   REXX-ooRexx_5.2.0(MT)_64-bit 6.06 18 Apr 2026
      rexxtry.rex lets you interactively try REXX statements.
        Each string is executed when you hit Enter.
        Enter 'call tell' for a description of the features.
      Go on - try a few...            Enter 'exit' to end.
   call rgf_util2
      ........................................... rexxtry.rex on WindowsNT
   call dump2 .local
   type: The Directory class: (10 items)

        #  1: index=[DEBUGINPUT]  -> item=[The DEBUG INPUT monitor 
id#_FFFFFE07_31C09E2F]
        #  2: index=[ERROR]       -> item=[The ERROR monitor 
id#_FFFFFE07_31C0854F]
        #  3: index=[INPUT]       -> item=[The INPUT monitor 
id#_FFFFFE07_31C10CCF]
        #  4: index=[OUTPUT]      -> item=[The OUTPUT monitor 
id#_FFFFFE07_31C091BF]
        #  5: index=[STDERR]      -> item=[STDERR id#_FFFFFE07_31C12AAF]
        #  6: index=[STDIN]       -> item=[STDIN id#_FFFFFE07_31C1581F]
        #  7: index=[STDOUT]      -> item=[STDOUT id#_FFFFFE07_31C141BF]
        #  8: index=[STDQUE]      -> item=[SESSION id#_FFFFFE07_31C06C6F]
        #  9: index=[SYSCARGS]    -> item=[an Array (0 items) 
id#_FFFFFE07_31C05FAF]
        # 10: index=[TRACEOUTPUT] -> item=[The TRACE OUTPUT monitor 
id#_FFFFFE07_31C078DF]
   --------------------------------------------------
      ........................................... rexxtry.rex on WindowsNT
   call dump2 .environment
   type: The Directory class: (78 items)

        #  1: index=[ALARM]                        -> item=[The Alarm class 
id#_FFFFFE07_31CA9BEF]
        #  2: index=[ALARMNOTIFICATION]            -> item=[The 
AlarmNotification class id#_FFFFFE07_31D1659F]
        #  3: index=[ARGUTIL]                      -> item=[The ArgUtil class 
id#_FFFFFE07_31C9B22F]
        #  4: index=[ARRAY]                        -> item=[The Array class 
id#_FFFFFE07_31E1199F]
        #  5: index=[BAG]                          -> item=[The Bag class 
id#_FFFFFE07_31DC003F]
        #  6: index=[BUFFER]                       -> item=[The Buffer class 
id#_FFFFFE07_31CF181F]
        #  7: index=[CASELESSCOLUMNCOMPARATOR]     -> item=[The 
CaselessColumnComparator class id#_FFFFFE07_31CB023F]
        #  8: index=[CASELESSCOMPARATOR]           -> item=[The 
CaselessComparator class id#_FFFFFE07_31CC4AAF]
        #  9: index=[CASELESSDESCENDINGCOMPARATOR] -> item=[The 
CaselessDescendingComparator class id#_FFFFFE07_31CC0AFF]
        # 10: index=[CIRCULARQUEUE]                -> item=[The CircularQueue 
class id#_FFFFFE07_31D9AB9F]
        # 11: index=[CLASS]                        -> item=[The Class class 
id#_FFFFFE07_31E475BF]
        # 12: index=[COLLECTION]                   -> item=[The Collection 
class id#_FFFFFE07_31E113EF]
        # 13: index=[COLUMNCOMPARATOR]             -> item=[The 
ColumnComparator class id#_FFFFFE07_31CBCAFF]
        # 14: index=[COMPARABLE]                   -> item=[The Comparable 
class id#_FFFFFE07_31E44A3F]
        # 15: index=[COMPARATOR]                   -> item=[The Comparator 
class id#_FFFFFE07_31CCA69F]
        # 16: index=[DATETIME]                     -> item=[The DateTime class 
id#_FFFFFE07_31E3F90F]
        # 17: index=[DESCENDINGCOMPARATOR]         -> item=[The 
DescendingComparator class id#_FFFFFE07_31CC8CFF]
        # 18: index=[DIRECTORY]                    -> item=[The Directory class 
id#_FFFFFE07_31DD92CF]
        # 19: index=[ENDOFLINE]                    -> item=["0D0A"x]
        # 20: index=[ENVIRONMENT]                  -> item=[The Environment 
Directory (78 items) id#_FFFFFE07_31E47EBF]
        # 21: index=[EVENTSEMAPHORE]               -> item=[The EventSemaphore 
class id#_FFFFFE07_31CF994F]
        # 22: index=[FALSE]                        -> item=[0]
        # 23: index=[FILE]                         -> item=[The File class 
id#_FFFFFE07_31E1967F]
        # 24: index=[IDENTITYTABLE]                -> item=[The IdentityTable 
class id#_FFFFFE07_31DFAADF]
        # 25: index=[INPUTOUTPUTSTREAM]            -> item=[The 
InputOutputStream class id#_FFFFFE07_31E161AF]
        # 26: index=[INPUTSTREAM]                  -> item=[The InputStream 
class id#_FFFFFE07_31E14A9F]
        # 27: index=[INVERTINGCOMPARATOR]          -> item=[The 
InvertingComparator class id#_FFFFFE07_31CB884F]
        # 28: index=[LIST]                         -> item=[The List class 
id#_FFFFFE07_31E0FB9F]
        # 29: index=[LOCAL]                        -> item=[The Local Directory 
(10 items) id#_FFFFFE07_31C0D2AF]
        # 30: index=[MAPCOLLECTION]                -> item=[The MapCollection 
class id#_FFFFFE07_31DFDD7F]
        # 31: index=[MESSAGE]                      -> item=[The Message class 
id#_FFFFFE07_31D16A0F]
        # 32: index=[MESSAGENOTIFICATION]          -> item=[The 
MessageNotification class id#_FFFFFE07_31D1662F]
        # 33: index=[METHOD]                       -> item=[The Method class 
id#_FFFFFE07_31DE3FAF]
        # 34: index=[MONITOR]                      -> item=[The Monitor class 
id#_FFFFFE07_31CD7FBF]
        # 35: index=[MUTABLEBUFFER]                -> item=[The MutableBuffer 
class id#_FFFFFE07_31DEF44F]
        # 36: index=[MUTEXSEMAPHORE]               -> item=[The MutexSemaphore 
class id#_FFFFFE07_31CF6D6F]
        # 37: index=[NIL]                          -> item=[The NIL object 
id#_FFFFFE07_31E475EF]
        # 38: index=[NUMERICCOMPARATOR]            -> item=[The 
NumericComparator class id#_FFFFFE07_31CB45EF]
        *# 39: index=[OBJECT] -> item=[The Object class id#_FFFFFE07_31E4647F]*
        # 40: index=[OLEOBJECT]                    -> item=[The OLEObject class 
id#_FFFFFE07_31C92F4F]
        # 41: index=[OLEVARIANT]                   -> item=[The OLEVariant 
class id#_FFFFFE07_31C8A31F]
        # 42: index=[ORDERABLE]                    -> item=[The Orderable class 
id#_FFFFFE07_31E3E3FF]
        # 43: index=[ORDEREDCOLLECTION]            -> item=[The 
OrderedCollection class id#_FFFFFE07_31E115BF]
        # 44: index=[OUTPUTSTREAM]                 -> item=[The OutputStream 
class id#_FFFFFE07_31E14CEF]
        # 45: index=[PACKAGE]                      -> item=[The Package class 
id#_FFFFFE07_31D088EF]
        # 46: index=[POINTER]                      -> item=[The Pointer class 
id#_FFFFFE07_31CF434F]
        # 47: index=[PROPERTIES]                   -> item=[The Properties 
class id#_FFFFFE07_31DD8EAF]
        # 48: index=[QUEUE]                        -> item=[The Queue class 
id#_FFFFFE07_31D9AFBF]
        # 49: index=[RELATION]                     -> item=[The Relation class 
id#_FFFFFE07_31DCC1DF]
        # 50: index=[REXXCONTEXT]                  -> item=[The RexxContext 
class id#_FFFFFE07_31D0361F]
        # 51: index=[REXXINFO]                     -> item=[a RexxInfo 
id#_FFFFFE07_31C2668F]
        # 52: index=[REXXQUEUE]                    -> item=[The RexxQueue class 
id#_FFFFFE07_31CD26AF]
        # 53: index=[RGF.ALPHA]                    -> 
item=[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]
        # 54: index=[RGF.ALPHA.LOW]                -> 
item=[abcdefghijklmnopqrstuvwxyz]
        # 55: index=[RGF.ALPHA.UPPER]              -> 
item=[ABCDEFGHIJKLMNOPQRSTUVWXYZ]
        # 56: index=[RGF.ALPHANUMERIC]             -> 
item=[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]
        # 57: index=[RGF.DIGITS]                   -> item=[0123456789]
        # 58: index=[RGF.NON.PRINTABLE]            -> 
item=["000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1FFF"x]
        # 59: index=[RGF.SYMBOL.CHARS]             -> item=[.!_?]
        # 60: index=[ROUTINE]                      -> item=[The Routine class 
id#_FFFFFE07_31D0B79F]
        # 61: index=[SET]                          -> item=[The Set class 
id#_FFFFFE07_31DC1D6F]
        # 62: index=[SETCOLLECTION]                -> item=[The SetCollection 
class id#_FFFFFE07_31DC198F]
        # 63: index=[SINGLETON]                    -> item=[The Singleton class 
id#_FFFFFE07_31C7DEBF]
        # 64: index=[STACKFRAME]                   -> item=[The StackFrame 
class id#_FFFFFE07_31CECF9F]
        # 65: index=[STEM]                         -> item=[The Stem class 
id#_FFFFFE07_31DACF8F]
        # 66: index=[STREAM]                       -> item=[The Stream class 
id#_FFFFFE07_31E1636F]
        # 67: index=[STREAMSUPPLIER]               -> item=[The StreamSupplier 
class id#_FFFFFE07_31E0A03F]
        # 68: index=[STRING]                       -> item=[The String class 
id#_FFFFFE07_31E44E1F]
        # 69: index=[STRINGTABLE]                  -> item=[The StringTable 
class id#_FFFFFE07_31DF3BEF]
        # 70: index=[SUPPLIER]                     -> item=[The Supplier class 
id#_FFFFFE07_31E0A45F]
        # 71: index=[TABLE]                        -> item=[The Table class 
id#_FFFFFE07_31DF6B0F]
        # 72: index=[TICKER]                       -> item=[The TICKER class 
id#_FFFFFE07_31CA14CF]
        # 73: index=[TIMESPAN]                     -> item=[The TimeSpan class 
id#_FFFFFE07_31E3C7DF]
        # 74: index=[TRACEOBJECT]                  -> item=[The TraceObject 
class id#_FFFFFE07_31DF37CF]
        *# 75: index=[TRUE] -> item=[1]*
        # 76: index=[VALIDATE]                     -> item=[The Validate class 
id#_FFFFFE07_31E3A5EF]
        # 77: index=[VARIABLEREFERENCE]            -> item=[The 
VariableReference class id#_FFFFFE07_31CFC48F]
        # 78: index=[WEAKREFERENCE]                -> item=[The WeakReference 
class id#_FFFFFE07_31CEF84F]
   --------------------------------------------------

In the short-circuit cases (.True is dubbed an "environment constant" in  rexxref.pdf's "1.13.6. Environment Symbols") and some other cases LOCAL and ENVIRONMENT do not get consulted, such that there would be no need for a security checkpoint, as no access of .local or .environment is taking place. This should be probably documented in the security manager chapter ("Chapter 13. The Security Manager").


---

So there are different aspects in this context that need to be thought about, 
checked and fixed.

Any thoughts about this? Any comments, ideas how to proceed from here on?

Also, how about the terminology used here (supervise messages that get sent to a security manager), is it understandable, clearer, easier than the current documentation?


Not sure...
https://chatgpt.com/s/t_6a54e7f6c2fc8191b93392e26fcdf0f8

I tend to trust this kind of feedback, it's very helpful for me as a non-native 
English speaker.

Thank you *very* much, I concur (not being a native English speaker myself), sounds much clearer ("security checkpoint"; we also should update the rexxref.pdf documentation accordingly)! The clearer the concepts and the language, the "easier" to comprehend the concepts and how they are put to work.

---rony

P.S.: Also terms like "code block" (I think that was the term Josep Maria suggested, but I may be mistaken) should be defined in the documentation as they ease the communication, once the term got defined.



_______________________________________________
Oorexx-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/oorexx-devel

Reply via email to