mirror of
https://github.com/evennia/evennia.git
synced 2026-03-16 21:06:30 +01:00
Add strip_unsafe_input/INPUT_CLEANUP_BYPASS_PERMISSIONS helpers to strip unsafe input on a per-command level. Resolves #1738.
This commit is contained in:
parent
0556f527fe
commit
2a8cc57bbe
6 changed files with 74 additions and 2 deletions
|
|
@ -186,6 +186,9 @@ without arguments starts a full interactive Python console.
|
|||
- Fixes in multi-match situations - don't allow finding/listing multimatches for 3-box when
|
||||
only two boxes in location.
|
||||
- Fix for TaskHandler with proper deferred returns/ability to cancel etc (PR by davewiththenicehat)
|
||||
- Add `PermissionHandler.check` method for straight string perm-checks without needing lockstrings.
|
||||
- Add `evennia.utils.utils.strip_unsafe_input` for removing html/newlines/tags from user input. The
|
||||
`INPUT_CLEANUP_BYPASS_PERMISSIONS` is a list of perms that bypass this safety stripping.
|
||||
|
||||
|
||||
## Evennia 0.9 (2018-2019)
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ from evennia.locks.lockhandler import LockException
|
|||
from evennia.comms.comms import DefaultChannel
|
||||
from evennia.utils import create, logger, utils
|
||||
from evennia.utils.logger import tail_log_file
|
||||
from evennia.utils.utils import class_from_module
|
||||
from evennia.utils.utils import class_from_module, strip_unsafe_input
|
||||
from evennia.utils.evmenu import ask_yes_no
|
||||
|
||||
COMMAND_DEFAULT_CLASS = class_from_module(settings.COMMAND_DEFAULT_CLASS)
|
||||
|
|
@ -298,6 +298,9 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
|
|||
caller.msg(f"You are not allowed to send messages to channel {channel}")
|
||||
return
|
||||
|
||||
# avoid unsafe tokens in message
|
||||
message = strip_unsafe_input(message, self.session)
|
||||
|
||||
channel.msg(message, senders=self.caller, **kwargs)
|
||||
|
||||
def get_channel_history(self, channel, start_index=0):
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ def text(session, *args, **kwargs):
|
|||
arguments are ignored.
|
||||
|
||||
"""
|
||||
|
||||
# from evennia.server.profiling.timetrace import timetrace
|
||||
# text = timetrace(text, "ServerSession.data_in")
|
||||
|
||||
|
|
|
|||
|
|
@ -722,6 +722,12 @@ CREATION_THROTTLE_LIMIT = 2
|
|||
CREATION_THROTTLE_TIMEOUT = 10 * 60
|
||||
LOGIN_THROTTLE_LIMIT = 5
|
||||
LOGIN_THROTTLE_TIMEOUT = 5 * 60
|
||||
# Certain characters, like html tags, line breaks and tabs are stripped
|
||||
# from user input for commands using the `evennia.utils.strip_unsafe_input` helper
|
||||
# since they can be exploitative. This list defines Account-level permissions
|
||||
# (and higher) that bypass this stripping. It is used as a fallback if a
|
||||
# specific list of perms are not given to the helper function.
|
||||
INPUT_CLEANUP_BYPASS_PERMISSIONS = ['Builder']
|
||||
|
||||
|
||||
######################################################################
|
||||
|
|
|
|||
|
|
@ -252,6 +252,9 @@ class ANSIParser(object):
|
|||
# instance of each
|
||||
ansi_escapes = re.compile(r"(%s)" % "|".join(ANSI_ESCAPES), re.DOTALL)
|
||||
|
||||
# tabs/linebreaks |/ and |- should be able to be cleaned
|
||||
unsafe_tokens = re.compile(r"\|\/|\|-", re.DOTALL)
|
||||
|
||||
def sub_ansi(self, ansimatch):
|
||||
"""
|
||||
Replacer used by `re.sub` to replace ANSI
|
||||
|
|
@ -430,6 +433,13 @@ class ANSIParser(object):
|
|||
string = self.mxp_url_sub.sub(r"\1", string) # replace with url verbatim
|
||||
return string
|
||||
|
||||
def strip_unsafe_tokens(self, string):
|
||||
"""
|
||||
Strip explicitly ansi line breaks and tabs.
|
||||
|
||||
"""
|
||||
return self.unsafe_tokens.sub('', string)
|
||||
|
||||
def parse_ansi(self, string, strip_ansi=False, xterm256=False, mxp=False):
|
||||
"""
|
||||
Parses a string, subbing color codes according to the stored
|
||||
|
|
@ -564,6 +574,15 @@ def strip_raw_ansi(string, parser=ANSI_PARSER):
|
|||
return parser.strip_raw_codes(string)
|
||||
|
||||
|
||||
def strip_unsafe_tokens(string, parser=ANSI_PARSER):
|
||||
"""
|
||||
Strip markup that can be used to create visual exploits
|
||||
(notably linebreaks and tags)
|
||||
|
||||
"""
|
||||
return parser.strip_unsafe_tokens(string)
|
||||
|
||||
|
||||
def raw(string):
|
||||
"""
|
||||
Escapes a string into a form which won't be colorized by the ansi
|
||||
|
|
|
|||
|
|
@ -24,12 +24,13 @@ from simpleeval import simple_eval
|
|||
from unicodedata import east_asian_width
|
||||
from twisted.internet.task import deferLater
|
||||
from twisted.internet.defer import returnValue # noqa - used as import target
|
||||
from twisted.internet import threads, reactor
|
||||
from os.path import join as osjoin
|
||||
from inspect import ismodule, trace, getmembers, getmodule, getmro
|
||||
from collections import defaultdict, OrderedDict
|
||||
from twisted.internet import threads, reactor
|
||||
from django.conf import settings
|
||||
from django.utils import timezone
|
||||
from django.utils.html import strip_tags
|
||||
from django.utils.translation import gettext as _
|
||||
from django.apps import apps
|
||||
from django.core.validators import validate_email as django_validate_email
|
||||
|
|
@ -44,6 +45,7 @@ ENCODINGS = settings.ENCODINGS
|
|||
|
||||
_TASK_HANDLER = None
|
||||
_TICKER_HANDLER = None
|
||||
_STRIP_UNSAFE_TOKENS = None
|
||||
|
||||
_GA = object.__getattribute__
|
||||
_SA = object.__setattr__
|
||||
|
|
@ -2588,3 +2590,41 @@ def safe_convert_to_types(converters, *args, raise_errors=True, **kwargs):
|
|||
if raise_errors:
|
||||
raise
|
||||
return args, kwargs
|
||||
|
||||
|
||||
def strip_unsafe_input(txt, session=None, bypass_perms=None):
|
||||
"""
|
||||
Remove 'unsafe' text codes from text; these are used to elimitate
|
||||
exploits in user-provided data, such as html-tags, line breaks etc.
|
||||
|
||||
Args:
|
||||
txt (str): The text to clean.
|
||||
session (Session, optional): A Session in order to determine if
|
||||
the check should be bypassed by permission (will be checked
|
||||
with the 'perm' lock, taking permission hierarchies into account).
|
||||
bypass_perms (list, optional): Iterable of permission strings
|
||||
to check for bypassing the strip. If not given, use
|
||||
`settings.INPUT_CLEANUP_BYPASS_PERMISSIONS`.
|
||||
|
||||
Returns:
|
||||
str: The cleaned string.
|
||||
|
||||
Notes:
|
||||
The `INPUT_CLEANUP_BYPASS_PERMISSIONS` list defines what account
|
||||
permissions are required to bypass this strip.
|
||||
|
||||
"""
|
||||
global _STRIP_UNSAFE_TOKENS
|
||||
if not _STRIP_UNSAFE_TOKENS:
|
||||
from evennia.utils.ansi import strip_unsafe_tokens as _STRIP_UNSAFE_TOKENS
|
||||
|
||||
if session:
|
||||
obj = session.puppet if session.puppet else session.account
|
||||
bypass_perms = bypass_perms or settings.INPUT_CLEANUP_BYPASS_PERMISSIONS
|
||||
if obj.permissions.check(*bypass_perms):
|
||||
return txt
|
||||
|
||||
# remove html codes
|
||||
txt = strip_tags(txt)
|
||||
txt = _STRIP_UNSAFE_TOKENS(txt)
|
||||
return txt
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue