Security Model
TinyMUX enforces a layered security model that governs who may read, modify, and execute objects and commands. This article describes the major components of that model.
The Control Hierarchy
Privilege levels form a strict hierarchy:
- God (#1) – Player #1 has absolute authority. God can set and clear the WIZARD flag on other players, use
@icmd, and access features marked with thegodpermission. No object controls God except God. - Wizards – Players with the WIZARD flag control every object in the database (except #1). Only #1 can grant or revoke WIZARD. Wizards cannot turn off their own WIZARD flag.
- Royalty – Players with the ROYALTY flag can see, examine, and teleport like wizards, but cannot modify objects they do not own or use wizard-only commands.
- Staff – The STAFF flag marks game staff. In the source,
Staff(x)is true if the object is a Wizard, Royalty, or has the STAFF flag set. The STAFF flag is wizard-settable only. - Mortals – Ordinary players with no special flags. They can only modify objects they own, subject to further restrictions.
Object Ownership and the Controls Check
The Controls(p, x) check is the central gatekeeper. In the source (flags.h), it evaluates to true when all of the following hold:
xis a valid object.- If
xis God, thenpmust also be God. - Any one of:
phasControl_All(thecontrol_allpower, or is a Wizard);pandxshare the same owner and eitherpinherits orxdoes not inherit; orppasses the zone check onx.
The ownership test (Owner(p) == Owner(x)) is the most common path for mortals. The Inherit clause prevents non-INHERIT objects from controlling INHERIT objects owned by the same player, which is the key to protecting privileged softcode.
Unlinked exits are a special case: anyone controls an unlinked exit, even through locks. Builders should link or secure exits promptly to avoid theft.
The INHERIT Flag
By default, objects owned by a Wizard do not have wizard powers. An object gains its owner’s Wizard (or Royalty) privileges only when:
- The object itself has the INHERIT flag set, or
- The owning player has the INHERIT flag set (which makes all owned objects inherit).
Players are always considered to inherit for themselves (a player is its own owner). The INHERIT flag can only be set by players, and it is automatically cleared during @chown.
The Inherits(x) macro in the source is true when the object has INHERIT, or its owner has INHERIT, or the object is a player. This is used by the Wizard(x) and Royalty(x) macros to decide whether an object acts with elevated privilege.
Permission Categories
TinyMUX commands and functions carry permission flags checked at dispatch time. The access config parameter modifies command permissions; function_access does the same for functions. Key permission levels include:
wizard– requires Wizard-level authority (flag or inherited).god– only #1.staff– STAFF, Royalty, or Wizard.builder– Wizard, Royalty, or the BUILDER power.disabled– no one can use the feature.no_guest,no_slave,no_suspect– exclude players with those flags.
These permissions can be viewed with @list permissions and modified at runtime with @admin access.
The Powers System
Powers provide fine-grained capabilities without granting full Wizard status. They are assigned with @power and checked individually. Notable powers include:
control_all– modify any object, equivalent to Wizard for control purposes.tel_anywhere/tel_anything– unrestricted teleportation.see_all– read mortal-visible attributes on any object.comm_all– wizard-level channel access.chown_anything– transfer ownership of any object.free_money/free_quota– unlimited resources.siteadmin– can@shutdownand@restart.boot,halt,announce,search,prog– individual privileged operations.
The full list is available via help powers list.
Site-Based Access Control
Connection-time restrictions are applied by matching the client IP address against an ordered site list. Four independent groups exist:
- Forbid / Permit / Register –
forbid_siterejects connections outright.permit_siteoverrides a broader forbid.register_siteallows connection but blocks character creation without registration. - Guest / NoGuest – controls whether guests may connect from a site.
- Suspect / Trust –
suspect_siteflags new connections;trust_siteexempts them. - Sitemon / NoSitemon – controls connection monitoring.
Sites are specified using address/mask pairs or CIDR notation, and both IPv4 and IPv6 are supported. More specific entries override broader ones regardless of the order they appear in the config file.
Function Access Restrictions
The function_access config parameter controls who may call each built-in function. If a caller lacks the required privileges, the function returns #-1 PERMISSION DENIED. Functions can also be renamed (function_name) or aliased (function_alias) to obscure or customize the interface.
Command Hooks
The @hook system and its config-file equivalent hook_cmd allow administrators to attach softcode checks to any built-in command. A single global hook object (set via hook_obj) holds attributes named with a prefix convention:
P_<command>– permit: if it returns anything other than null or1, the command is denied with “Permission denied.”I_<command>– ignore: if triggered, the command silently fails as if unrecognized.B_<command>/A_<command>– before and after: code that runs immediately before or after the command executes.
Hooks persist across reboots only if configured via hook_cmd in the .conf file or placed in @startup.
@icmd: Per-Object Command Restriction
The @icmd command (restricted to #1) removes specific commands from individual players or rooms:
@icmd/disable <player>=<commands>– the player receives “Permission denied.”@icmd/ignore <player>=<commands>– the commands are silently skipped.@icmd/droomand@icmd/iroomapply the same restrictions by location or zone.@icmd/clearremoves all restrictions from a player.
This is useful for restricting abusive players to a minimal command set without resorting to @boot or site bans.
Common Security Pitfalls
INHERIT leaks. Setting INHERIT on a wizard player causes every object they own to run with wizard privileges. This is dangerous if any of those objects accept user input (via @trigger, $commands, or listen patterns). Prefer setting INHERIT on individual objects that genuinely need elevated access.
Eval chains and user input. Functions like u(), eval(), and s() can evaluate attacker-controlled strings. Wizard-INHERIT objects must sanitize all external input to avoid granting unintended control. Never store raw user input in attributes that are later evaluated.
Unlinked exits. Anyone controls an unlinked exit. A wizard or builder who creates exits without immediately linking them risks having those exits stolen or redirected.
@chown clears INHERIT. Transferring ownership of an object automatically strips the INHERIT flag. This is intentional: it prevents a mortal from receiving a wizard-INHERIT object and retaining wizard powers through it.
Zone trust boundaries. Zone masters extend control to objects in their zone tree. Misconfigured zones can grant unintended modification rights across ownership boundaries.