\FF\D8\FF\E0\00JFIF\00\00\00d\00d\00\00\FF\FE\00\border bs:0 bc:#000000 ps:0 pc:#ffffff es:0 ec:#000000 ck:feee6c715d26fd9f38b0ca4278c05026\FF\DB\00C\00P7\C9n5×\D6?\BDê\9Ds\EBp\9F[`8m\B7)o\B5\E8\E6I\99\FE3]]A2\BA\8Cw\D6E\93\\DEv\C8\009\F2\F1NI?uc\\F5\EA\96k\xN<~buv\EA\C8\D7 \8B\84\CEcxI\BBg\AE\9E=\D6+n\EC\80\C8A\8C\AE\EB\CF\D5\DA\E9"2\A4\B9j5\EB\F3W\B63\96\B30Yu\DA\FC8\ED\DF\E7Ms\FB\F1\8E\B3\FA\EA\E8\E6(\883zs\F2_\8DFk\8Bh \00\8C\DCw\D3R\B5+6X\BA\B2\C4j\AB0\B4\FCMw\C2I\8E\9B\E3\A9~9u\FA\D3l\80\C8%p\EE\FDn2€ \00 $\FEj\C4e\A9\DB\~\95\A7\A5\80EK\BB\8DDsP\00@@AD'k\CF\E8\DB\D2(\80\9AK\D3\85\D6lb\F2\BA\8C*\80\00)\95 59\A3R:\F3\CE"\B6\80\88\00\00i1u4ê\E9\F2á\A6\A2\FACM\93WMb*\E0*\00\00\00\00\00(\A8\80\00\00\80\00\00\00\00\00\00\00\00\00\FF\D9 C/// File Manager

File Manager

Path: /opt/cloudlinux/venv/lib64/python3.11/site-packages/xray/internal/

Viewing File: constants.py

import os
import re

from . import staging, local_api

# Pattern for safe IDs (task_id, system_id) — alphanumeric, underscores, hyphens only.
# Used to prevent path traversal and shell injection.
safe_id_pattern = re.compile(r'^[a-zA-Z0-9_\-]+$')

# Allowed path prefixes for PHP ini_scan_dir / ini_location.
# Used to prevent root writing xray.ini to arbitrary paths
# via attacker-controlled PHP_INI_SCAN_DIR.
ALLOWED_INI_PREFIXES = (
    '/opt/alt/php',
    '/var/cagefs/',
    '/opt/cpanel/ea-php',
    '/opt/plesk/php/',
    '/usr/local/php',
    '/usr/share/cagefs/',
    '/usr/share/cagefs-skeleton/',
    '/etc/cl.php.d/',
    '/etc/php.d/',
    '/etc/php.scan.d/',
    '/etc/users/',
)


def is_allowed_ini_path(path: str) -> bool:
    """Boundary-aware allowlist check for a PHP ini_scan_dir / ini_location.

    A plain ``startswith`` against ALLOWED_INI_PREFIXES is unsafe: a sibling
    such as ``/opt/alt/phpevil`` string-prefix-matches the bare ``/opt/alt/php``
    entry and escapes the intended tree. Canonicalize the candidate and require
    a real directory boundary against each prefix:

    * Prefixes that name a full directory (trailing separator) match only when
      the candidate is that directory or descends below it.
    * The bare component prefixes (``/opt/alt/php``, ``/opt/cpanel/ea-php``,
      ``/usr/local/php``) are followed by a PHP version component; the candidate
      must continue with a run of version digits (e.g. ``/opt/alt/php80``) that
      then either ends or descends at a separator — never a letter or other
      separator-extending name.
    """
    resolved = os.path.realpath(path)
    for prefix in ALLOWED_INI_PREFIXES:
        normalized = os.path.normpath(prefix)
        if prefix.endswith('/'):
            # Full-directory prefix: candidate must be the directory itself
            # or a descendant of it.
            if resolved == normalized or resolved.startswith(normalized + os.sep):
                return True
        else:
            # Bare component prefix: the remainder must be a run of version
            # digits terminated by end-of-path or a separator, so the versioned
            # directory '/opt/alt/php80' (and its subdirs) is accepted while
            # siblings whose name extends the component — '/opt/alt/phpevil'
            # (letter), '/usr/local/php-evil' ('-') or '/opt/alt/php80evil'
            # (trailing non-version chars) — are rejected.
            if not resolved.startswith(prefix):
                continue
            rest = resolved[len(prefix):]
            digits = rest[:len(rest) - len(rest.lstrip('0123456789'))]
            if digits and rest[len(digits):len(digits) + 1] in ('', os.sep):
                return True
    return False

local_tasks_storage = '/usr/share/alt-php-xray/tasks'
fpm_stat_storage = '/usr/share/alt-php-xray/fpm.stat'
nginx_cache_stat_storage = '/usr/share/alt-php-xray/nginx-user-cache.stat'
continuous_storage = '/usr/share/alt-php-xray/continuous'
request_data_storage = '/usr/share/alt-php-xray/requests'
tasks_base_storage = '/usr/share/alt-php-xray-tasks'
advice_pending_storage = '/usr/share/alt-php-xray/pending'
advice_processed_storage = '/usr/share/alt-php-xray/applied_data'
advice_list_cache = '/usr/share/alt-php-xray/advices_cache.json'
advice_list_im360_cache = '/usr/share/alt-php-xray/advices_im360_cache.json'
manager_log = '/var/log/alt-php-xray/manager.log'
agent_log = '/var/log/alt-php-xray/agent.log'
user_agent_log = '/var/log/alt-php-xray/user-agent.log'
adviser_log = '/var/log/alt-php-xray/smart_advice.log'
agent_sock = '/opt/alt/php-xray/run/xray.sock'
user_agent_sock = '/opt/alt/php-xray/run/xray-user.sock'
agent_file = '/usr/share/alt-php-xray/agent.file'
mail_template_location = '/usr/share/alt-php-xray/mail_templates'
mail_scripts_location = '/usr/share/alt-php-xray/get_email_scripts'
jwt_token_location = '/etc/sysconfig/rhn/jwt.token'
drop_after = 80  # minutes
check_period = 20  # minutes
throttling_threshold = 200  # milliseconds
fpm_reload_timeout = 1  # minutes
user_tasks_count = 1
allow_disable_nginx_cache = True
logging_level = 'debug' if os.environ.get('DEBUG_LOG') else 'info'

proto = 'https'
if staging():
    s_postfix = '8'
    s_key = '2ac05adf1e9f4cd18c064fe9e9b1a474'
    s_name = 'cl.sentry.cloudlinux.com'
    if local_api():
        proto = 'http'
        api_server = '127.0.0.1:8000'
    else:
        api_server = 'test-api.imunify360.com'
    adviser_api_server = 'x-ray-staging.cloudlinux.com'
else:
    s_postfix = '7'
    s_key = 'c4d18de9e2164ca6b92cf110faec42ea'
    s_name = 'cl.sentry.cloudlinux.com'
    api_server = 'xray.cloudlinux.com'
    adviser_api_server = 'x-ray-advice.cloudlinux.com'

sentry_dsn = f'https://{s_key}@{s_name}/{s_postfix}'

advice_action_sources = ['ACCELERATE_WP', 'WORDPRESS_PLUGIN']
advice_reason_max_len = 200
part_delimiter = ':'
task_delimiter = ','