diff --git a/.sonarcloud.properties b/.sonarcloud.properties index 28eead4702..649b785465 100644 --- a/.sonarcloud.properties +++ b/.sonarcloud.properties @@ -1,4 +1,4 @@ sonar.sources=. sonar.exclusions=mobsf/static/**/*,mobsf/templates/**/* sonar.sourceEncoding=UTF-8 -sonar.python.version=3.10, 3.11 \ No newline at end of file +sonar.python.version=3.10, 3.11, 3.12 \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index cb4fe5ec80..0000000000 --- a/docker-compose.yml +++ /dev/null @@ -1,37 +0,0 @@ -services: - postgres: - image: "postgres:latest" - restart: always - volumes: - - $HOME/MobSF/postgresql_data:/var/lib/postgresql - environment: - - POSTGRES_USER=postgres - - POSTGRES_PASSWORD=password - - POSTGRES_DB=mobsf - ports: - - "5432:5432" - networks: - - mobsf - - mobsf: - environment: - - POSTGRES_USER=postgres - - POSTGRES_PASSWORD=password - - POSTGRES_DB=mobsf - - POSTGRES_HOST=postgres - - POSTGRES_PORT=5432 - build: - context: . - dockerfile: Dockerfile - volumes: - - $HOME/MobSF/mobsf_data:/home/mobsf/.MobSF - ports: - - "8000:8000" - networks: - - mobsf - depends_on: - - postgres - links: - - "postgres" -networks: - mobsf: diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml new file mode 100644 index 0000000000..6667dbc94c --- /dev/null +++ b/docker/docker-compose.yml @@ -0,0 +1,47 @@ +services: + + postgres: + image: "postgres:13" + restart: always + volumes: + - $HOME/MobSF/postgresql_data:/var/lib/postgresql/data + environment: + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=password + - POSTGRES_DB=mobsf + networks: + - mobsf_network + + nginx: + image: nginx:latest + restart: always + ports: + - "80:4000" + volumes: + - ./nginx.conf:/etc/nginx/nginx.conf:ro + depends_on: + - mobsf + networks: + - mobsf_network + + mobsf: + image: opensecurity/mobile-security-framework-mobsf:latest + restart: always + volumes: + - $HOME/MobSF/mobsf_data:/home/mobsf/.MobSF + environment: + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=password + - POSTGRES_DB=mobsf + - POSTGRES_HOST=postgres + - POSTGRES_PORT=5432 + healthcheck: + test: curl -f http://localhost:8000/login/ || exit 1 + depends_on: + - postgres + networks: + - mobsf_network + +networks: + mobsf_network: + driver: bridge diff --git a/docker/docker-compose_swarm.yml b/docker/docker-compose_swarm.yml new file mode 100644 index 0000000000..9f61faa4b1 --- /dev/null +++ b/docker/docker-compose_swarm.yml @@ -0,0 +1,48 @@ +services: + + postgres: + image: "postgres:${POSTGRES_VERSION:-17.0-bookworm}" + restart: always + volumes: + - $HOME/MobSF/postgresql_data:/var/lib/postgresql/data + environment: + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD_FILE=/run/secrets/mobsfDB_password + - POSTGRES_DB=mobsf + networks: + - mobsf_network + secrets: + - mobsfDB_password + + mobsf: + image: ${MOBSF_IMAGE:-opensecurity/mobile-security-framework-mobsf:latest} + restart: always + ports: + - "8000:8000" + volumes: + - $HOME/MobSF/mobsf_data:/home/mobsf/.MobSF + environment: + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD_FILE=/run/secrets/mobsfDB_password + - POSTGRES_DB=mobsf + - POSTGRES_HOST=postgres + - POSTGRES_PORT=5432 + - MOBSF_API_KEY_FILE=/run/secrets/mobsf_api_key + healthcheck: + test: curl -f http://localhost:8000/login/ || exit 1 + depends_on: + - postgres + networks: + - mobsf_network + secrets: + - mobsfDB_password + - mobsf_api_key + +networks: + mobsf_network: + +secrets: + mobsfDB_password: + external: true + mobsf_api_key: + external: true diff --git a/docker/nginx.conf b/docker/nginx.conf new file mode 100644 index 0000000000..6fcd8598cb --- /dev/null +++ b/docker/nginx.conf @@ -0,0 +1,20 @@ +user nginx; +events { + worker_connections 1000; +} +http { + server { + listen 4000; + location / { + proxy_set_header X-Forwarded-Host $host; + proxy_set_header X-Forwarded-Port 443; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + proxy_pass http://mobsf:8000; + proxy_redirect off; + proxy_read_timeout 900; + proxy_buffering on; + } + client_max_body_size 256M; + } +} diff --git a/mobsf/MobSF/init.py b/mobsf/MobSF/init.py index d9c27faa0e..fff61d291f 100644 --- a/mobsf/MobSF/init.py +++ b/mobsf/MobSF/init.py @@ -6,6 +6,8 @@ import sys import shutil import threading +from hashlib import sha256 +from pathlib import Path from importlib import ( machinery, util, @@ -16,7 +18,7 @@ logger = logging.getLogger(__name__) -VERSION = '4.1.4' +VERSION = '4.1.5' BANNER = r""" __ __ _ ____ _____ _ _ _ | \/ | ___ | |__/ ___|| ___|_ _| || | / | @@ -29,16 +31,17 @@ def first_run(secret_file, base_dir, mobsf_home): # Based on https://gist.github.com/ndarville/3452907#file-secret-key-gen-py - if 'MOBSF_SECRET_KEY' in os.environ: + base_dir = Path(base_dir) + mobsf_home = Path(mobsf_home) + secret_file = Path(secret_file) + if os.getenv('MOBSF_SECRET_KEY'): secret_key = os.environ['MOBSF_SECRET_KEY'] - elif os.path.isfile(secret_file): - secret_key = open(secret_file).read().strip() + elif secret_file.exists() and secret_file.is_file(): + secret_key = secret_file.read_text().strip() else: try: secret_key = get_random() - secret = open(secret_file, 'w') - secret.write(secret_key) - secret.close() + secret_file.write_text(secret_key) except IOError: raise Exception('Secret file generation failed' % secret_file) # Run Once @@ -48,20 +51,19 @@ def first_run(secret_file, base_dir, mobsf_home): thread = threading.Thread( target=install_jadx, name='install_jadx', - args=(mobsf_home,)) + args=(mobsf_home.as_posix(),)) thread.start() # Windows Setup - windows_config_local(mobsf_home) + windows_config_local(mobsf_home.as_posix()) return secret_key def create_user_conf(mobsf_home, base_dir): try: - config_path = os.path.join(mobsf_home, 'config.py') - if not os.path.isfile(config_path): - sample_conf = os.path.join(base_dir, 'MobSF/settings.py') - with open(sample_conf, 'r') as f: - dat = f.readlines() + config_path = mobsf_home / 'config.py' + if not config_path.exists(): + sample_conf = base_dir / 'MobSF' / 'settings.py' + dat = sample_conf.read_text().splitlines() config = [] add = False for line in dat: @@ -72,20 +74,20 @@ def create_user_conf(mobsf_home, base_dir): if add: config.append(line.lstrip()) config.pop(0) - conf_str = ''.join(config) - with open(config_path, 'w') as f: - f.write(conf_str) + conf_str = '\n'.join(config) + config_path.write_text(conf_str) except Exception: logger.exception('Cannot create config file') def django_operation(cmds, base_dir): """Generic Function for Djano operations.""" - manage = os.path.join(base_dir, '../manage.py') - if not os.path.exists(manage): + manage = base_dir.parent / 'manage.py' + if manage.exists() and manage.is_file(): # Bail out for package return - args = [sys.executable, manage] + print(manage) + args = [sys.executable, manage.as_posix()] args.extend(cmds) subprocess.call(args) @@ -116,42 +118,43 @@ def get_random(): def get_mobsf_home(use_home, base_dir): try: + base_dir = Path(base_dir) mobsf_home = '' if use_home: - mobsf_home = os.path.join(os.path.expanduser('~'), '.MobSF') + mobsf_home = Path.home() / '.MobSF' + custom_home = os.getenv('MOBSF_HOME_DIR') + if custom_home: + p = Path(custom_home) + if p.exists() and p.is_absolute() and p.is_dir(): + mobsf_home = p # MobSF Home Directory - if not os.path.exists(mobsf_home): - os.makedirs(mobsf_home) + if not mobsf_home.exists(): + mobsf_home.mkdir(parents=True, exist_ok=True) create_user_conf(mobsf_home, base_dir) else: mobsf_home = base_dir # Download Directory - dwd_dir = os.path.join(mobsf_home, 'downloads/') - if not os.path.exists(dwd_dir): - os.makedirs(dwd_dir) + dwd_dir = mobsf_home / 'downloads' + dwd_dir.mkdir(parents=True, exist_ok=True) # Screenshot Directory - screen_dir = os.path.join(dwd_dir, 'screen/') - if not os.path.exists(screen_dir): - os.makedirs(screen_dir) + screen_dir = mobsf_home / 'screen' + screen_dir.mkdir(parents=True, exist_ok=True) # Upload Directory - upload_dir = os.path.join(mobsf_home, 'uploads/') - if not os.path.exists(upload_dir): - os.makedirs(upload_dir) + upload_dir = mobsf_home / 'uploads' + upload_dir.mkdir(parents=True, exist_ok=True) # Downloaded tools - downloaded_tools_dir = os.path.join(mobsf_home, 'tools/') - if not os.path.exists(downloaded_tools_dir): - os.makedirs(downloaded_tools_dir) - # Signature Directory - sig_dir = os.path.join(mobsf_home, 'signatures/') + downloaded_tools_dir = mobsf_home / 'tools' + downloaded_tools_dir.mkdir(parents=True, exist_ok=True) + # Signatures Directory + sig_dir = mobsf_home / 'signatures' + sig_dir.mkdir(parents=True, exist_ok=True) if use_home: - src = os.path.join(base_dir, 'signatures/') + src = Path(base_dir) / 'signatures' try: shutil.copytree(src, sig_dir, dirs_exist_ok=True) except Exception: pass - elif not os.path.exists(sig_dir): - os.makedirs(sig_dir) - return mobsf_home + return mobsf_home.as_posix() except Exception: logger.exception('Creating MobSF Home Directory') @@ -166,3 +169,46 @@ def load_source(modname, filename): module = util.module_from_spec(spec) loader.exec_module(module) return module + + +def get_docker_secret_by_file(secret_key): + try: + secret_path = os.environ.get(secret_key) + path = Path(secret_path) + if path.exists() and path.is_file(): + return path.read_text().strip() + except Exception: + logger.exception('Cannot read secret from %s', secret_path) + raise Exception('Cannot read secret from file') + + +def get_secret_from_file_or_env(env_secret_key): + docker_secret_key = f'{env_secret_key}_FILE' + if os.environ.get(docker_secret_key): + return get_docker_secret_by_file(docker_secret_key) + else: + return os.environ[env_secret_key] + + +def api_key(home_dir): + """Print REST API Key.""" + # Form Docker Secrets + if os.environ.get('MOBSF_API_KEY_FILE'): + logger.info('\nAPI Key read from docker secrets') + try: + return get_docker_secret_by_file('MOBSF_API_KEY_FILE') + except Exception: + logger.exception('Cannot read API Key from docker secrets') + # From Environment Variable + if os.environ.get('MOBSF_API_KEY'): + logger.info('\nAPI Key read from environment variable') + return os.environ['MOBSF_API_KEY'] + home_dir = Path(home_dir) + secret_file = home_dir / 'secret' + if secret_file.exists() and secret_file.is_file(): + try: + _api_key = secret_file.read_bytes().strip() + return sha256(_api_key).hexdigest() + except Exception: + logger.exception('Cannot Read API Key') + return None diff --git a/mobsf/MobSF/settings.py b/mobsf/MobSF/settings.py index ffc05b5f4b..cc1a0885f3 100644 --- a/mobsf/MobSF/settings.py +++ b/mobsf/MobSF/settings.py @@ -12,11 +12,11 @@ first_run, get_mobsf_home, get_mobsf_version, + get_secret_from_file_or_env, load_source, ) logger = logging.getLogger(__name__) - # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! # MOBSF CONFIGURATION # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @@ -27,28 +27,28 @@ # MobSF Data Directory BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) -MobSF_HOME = get_mobsf_home(USE_HOME, BASE_DIR) +MOBSF_HOME = get_mobsf_home(USE_HOME, BASE_DIR) # Download Directory -DWD_DIR = os.path.join(MobSF_HOME, 'downloads/') +DWD_DIR = os.path.join(MOBSF_HOME, 'downloads/') # Screenshot Directory -SCREEN_DIR = os.path.join(MobSF_HOME, 'downloads/screen/') +SCREEN_DIR = os.path.join(MOBSF_HOME, 'downloads/screen/') # Upload Directory -UPLD_DIR = os.path.join(MobSF_HOME, 'uploads/') +UPLD_DIR = os.path.join(MOBSF_HOME, 'uploads/') # Database Directory -DB_DIR = os.path.join(MobSF_HOME, 'db.sqlite3') +DB_DIR = os.path.join(MOBSF_HOME, 'db.sqlite3') # Signatures used by modules -SIGNATURE_DIR = os.path.join(MobSF_HOME, 'signatures/') +SIGNATURE_DIR = os.path.join(MOBSF_HOME, 'signatures/') # Tools Directory TOOLS_DIR = os.path.join(BASE_DIR, 'DynamicAnalyzer/tools/') # Downloaded Tools Directory -DOWNLOADED_TOOLS_DIR = os.path.join(MobSF_HOME, 'tools/') +DOWNLOADED_TOOLS_DIR = os.path.join(MOBSF_HOME, 'tools/') # Secret File -SECRET_FILE = os.path.join(MobSF_HOME, 'secret') +SECRET_FILE = os.path.join(MOBSF_HOME, 'secret') # ==========Load MobSF User Settings========== try: if USE_HOME: - USER_CONFIG = os.path.join(MobSF_HOME, 'config.py') + USER_CONFIG = os.path.join(MOBSF_HOME, 'config.py') sett = load_source('user_settings', USER_CONFIG) locals().update( # lgtm [py/modification-of-locals] {k: v for k, v in list(sett.__dict__.items()) @@ -61,7 +61,7 @@ CONFIG_HOME = False # ===MOBSF SECRET GENERATION AND DB MIGRATION==== -SECRET_KEY = first_run(SECRET_FILE, BASE_DIR, MobSF_HOME) +SECRET_KEY = first_run(SECRET_FILE, BASE_DIR, MOBSF_HOME) # =============ALLOWED DOWNLOAD EXTENSIONS===== ALLOWED_EXTENSIONS = { @@ -150,14 +150,15 @@ # Database # https://docs.djangoproject.com/en/dev/ref/settings/#databases if (os.environ.get('POSTGRES_USER') - and os.environ.get('POSTGRES_PASSWORD') + and (os.environ.get('POSTGRES_PASSWORD') + or os.environ.get('POSTGRES_PASSWORD_FILE')) and os.environ.get('POSTGRES_HOST')): # Postgres support default = { 'ENGINE': 'django.db.backends.postgresql_psycopg2', 'NAME': os.getenv('POSTGRES_DB', 'mobsf'), 'USER': os.environ['POSTGRES_USER'], - 'PASSWORD': os.environ['POSTGRES_PASSWORD'], + 'PASSWORD': get_secret_from_file_or_env('POSTGRES_PASSWORD'), 'HOST': os.environ['POSTGRES_HOST'], 'PORT': int(os.getenv('POSTGRES_PORT', 5432)), } @@ -291,7 +292,7 @@ 'logfile': { 'level': 'DEBUG', 'class': 'logging.FileHandler', - 'filename': os.path.join(MobSF_HOME, 'debug.log'), + 'filename': os.path.join(MOBSF_HOME, 'debug.log'), 'formatter': 'standard', }, 'console': { diff --git a/mobsf/MobSF/utils.py b/mobsf/MobSF/utils.py index 18d7e9e07b..0b9fbebcc2 100755 --- a/mobsf/MobSF/utils.py +++ b/mobsf/MobSF/utils.py @@ -35,6 +35,7 @@ from django.utils import timezone from mobsf.StaticAnalyzer.models import RecentScansDB +from mobsf.MobSF. init import api_key from . import settings @@ -91,34 +92,20 @@ def upstream_proxy(flaw_type): return proxies, verify -def api_key(): - """Print REST API Key.""" - if os.environ.get('MOBSF_API_KEY'): - logger.info('\nAPI Key read from environment variable') - return os.environ['MOBSF_API_KEY'] - - secret_file = os.path.join(settings.MobSF_HOME, 'secret') - if is_file_exists(secret_file): - try: - _api_key = open(secret_file).read().strip() - return gen_sha256_hash(_api_key) - except Exception: - logger.exception('Cannot Read API Key') - - def print_version(): """Print MobSF Version.""" logger.info(settings.BANNER) ver = settings.MOBSF_VER logger.info('Author: Ajin Abraham | opensecurity.in') + mobsf_api_key = api_key(settings.MOBSF_HOME) if platform.system() == 'Windows': logger.info('Mobile Security Framework %s', ver) - print('REST API Key: ' + api_key()) + print(f'REST API Key: {mobsf_api_key}') print('Default Credentials: mobsf/mobsf') else: logger.info( '%sMobile Security Framework %s%s', Color.GREY, ver, Color.END) - print(f'REST API Key: {Color.BOLD}{api_key()}{Color.END}') + print(f'REST API Key: {Color.BOLD}{mobsf_api_key}{Color.END}') print(f'Default Credentials: {Color.BOLD}mobsf/mobsf{Color.END}') os = platform.system() pltfm = platform.platform() diff --git a/mobsf/MobSF/views/api/api_middleware.py b/mobsf/MobSF/views/api/api_middleware.py index 48bc992e5f..5b04132698 100644 --- a/mobsf/MobSF/views/api/api_middleware.py +++ b/mobsf/MobSF/views/api/api_middleware.py @@ -1,9 +1,12 @@ # -*- coding: utf_8 -*- """REST API Middleware.""" +from hmac import compare_digest + from django.http import JsonResponse from django.utils.deprecation import MiddlewareMixin +from django.conf import settings -from mobsf.MobSF.utils import api_key +from mobsf.MobSF.init import api_key OK = 200 @@ -22,10 +25,11 @@ def make_api_response(data, status=OK): def api_auth(meta): """Check if API Key Matches.""" + mobsf_api_key = api_key(settings.MOBSF_HOME) if 'HTTP_X_MOBSF_API_KEY' in meta: - return bool(api_key() == meta['HTTP_X_MOBSF_API_KEY']) + return compare_digest(mobsf_api_key, meta['HTTP_X_MOBSF_API_KEY']) elif 'HTTP_AUTHORIZATION' in meta: - return bool(api_key() == meta['HTTP_AUTHORIZATION']) + return compare_digest(mobsf_api_key, meta['HTTP_AUTHORIZATION']) return False diff --git a/mobsf/MobSF/views/home.py b/mobsf/MobSF/views/home.py index 1671c49dd9..84a1568124 100755 --- a/mobsf/MobSF/views/home.py +++ b/mobsf/MobSF/views/home.py @@ -23,7 +23,6 @@ from mobsf.MobSF.forms import FormUtil, UploadFileForm from mobsf.MobSF.utils import ( MD5_REGEX, - api_key, get_md5, is_dir_exists, is_file_exists, @@ -33,6 +32,7 @@ print_n_send_error_response, python_dict, ) +from mobsf.MobSF.init import api_key from mobsf.MobSF.views.helpers import FileType from mobsf.MobSF.views.scanning import Scanning from mobsf.MobSF.views.apk_downloader import apk_download @@ -195,7 +195,7 @@ def api_docs(request): if (settings.DISABLE_AUTHENTICATION == '1' or request.user.is_staff or request.user.groups.filter(name=MAINTAINER_GROUP).exists()): - key = api_key() + key = api_key(settings.MOBSF_HOME) except Exception: logger.exception('[ERROR] Failed to get API key') context = { diff --git a/mobsf/StaticAnalyzer/tests.py b/mobsf/StaticAnalyzer/tests.py index 24d796ae39..510fce87f9 100755 --- a/mobsf/StaticAnalyzer/tests.py +++ b/mobsf/StaticAnalyzer/tests.py @@ -4,12 +4,12 @@ import os import platform +from mobsf.MobSF.init import api_key + from django.conf import settings from django.http import HttpResponse from django.test import Client, TestCase -from mobsf.MobSF.utils import api_key - logger = logging.getLogger(__name__) RESCAN = False @@ -175,7 +175,7 @@ def static_analysis_test(): def api_test(): """View for Handling REST API Test.""" logger.info('\nRunning REST API Unit test') - auth = api_key() + auth = api_key(settings.MOBSF_HOME) try: uploaded = [] logger.info('Running Test on Upload API') diff --git a/mobsf/StaticAnalyzer/tools/ios/CgbiPngFix/CgbiPngFix.exe b/mobsf/StaticAnalyzer/tools/ios/CgbiPngFix/CgbiPngFix.exe new file mode 100755 index 0000000000..8b28e7bb0c Binary files /dev/null and b/mobsf/StaticAnalyzer/tools/ios/CgbiPngFix/CgbiPngFix.exe differ diff --git a/mobsf/StaticAnalyzer/tools/ios/CgbiPngFix/CgbiPngFix_amd64 b/mobsf/StaticAnalyzer/tools/ios/CgbiPngFix/CgbiPngFix_amd64 new file mode 100755 index 0000000000..4a583f03a6 Binary files /dev/null and b/mobsf/StaticAnalyzer/tools/ios/CgbiPngFix/CgbiPngFix_amd64 differ diff --git a/mobsf/StaticAnalyzer/tools/ios/CgbiPngFix/CgbiPngFix_arm64 b/mobsf/StaticAnalyzer/tools/ios/CgbiPngFix/CgbiPngFix_arm64 new file mode 100755 index 0000000000..5e68ab4542 Binary files /dev/null and b/mobsf/StaticAnalyzer/tools/ios/CgbiPngFix/CgbiPngFix_arm64 differ diff --git a/mobsf/StaticAnalyzer/views/android/views/source_tree.py b/mobsf/StaticAnalyzer/views/android/views/source_tree.py index a96f293c34..ff50d7eb36 100644 --- a/mobsf/StaticAnalyzer/views/android/views/source_tree.py +++ b/mobsf/StaticAnalyzer/views/android/views/source_tree.py @@ -10,8 +10,8 @@ render, ) +from mobsf.MobSF.init import api_key from mobsf.MobSF.utils import ( - api_key, is_md5, print_n_send_error_response, ) @@ -71,7 +71,7 @@ def run(request): 'hash': md5, 'source_type': typ, 'version': settings.MOBSF_VER, - 'api_key': api_key(), + 'api_key': api_key(settings.MOBSF_HOME), } template = 'static_analysis/source_tree.html' return render(request, template, context) diff --git a/mobsf/StaticAnalyzer/views/ios/icon_analysis.py b/mobsf/StaticAnalyzer/views/ios/icon_analysis.py index 1f50264994..bec66a398a 100644 --- a/mobsf/StaticAnalyzer/views/ios/icon_analysis.py +++ b/mobsf/StaticAnalyzer/views/ios/icon_analysis.py @@ -37,12 +37,16 @@ def get_icon_from_ipa(app_dict, binary): return icon_file = icons.pop() outfile = Path(settings.DWD_DIR) / f'{md5}-icon.png' - if platform.system() == 'Darwin': + tools_dir = Path(settings.BASE_DIR) / 'StaticAnalyzer' / 'tools' / 'ios' + cgbipng_bin = None + arch = platform.machine() + system = platform.system() + # Uncrush PNG. CgBI -> PNG + # https://iphonedevwiki.net/index.php/CgBI_file_format + if system == 'Darwin': args = ['xcrun', '-sdk', 'iphoneos', 'pngcrush', '-q', '-revert-iphone-optimizations', icon_file, outfile.as_posix()] - # Uncrush PNG. CgBI -> PNG, Mac only - # https://iphonedevwiki.net/index.php/CgBI_file_format try: out = subprocess.run(args, capture_output=True) if b'libpng error:' in out.stdout: @@ -50,6 +54,21 @@ def get_icon_from_ipa(app_dict, binary): raise ValueError('PNG is not CgBI') except Exception: shutil.copy2(icon_file, outfile.as_posix()) + elif system == 'Windows' and arch in ('AMD64', 'x86'): + cgbipng_bin = 'CgbiPngFix.exe' + elif system == 'Linux' and arch == 'x86_64': + cgbipng_bin = 'CgbiPngFix_amd64' + elif system == 'Linux' and arch == 'aarch64': + cgbipng_bin = 'CgbiPngFix_arm64' + if cgbipng_bin: + cbin = tools_dir / 'CgbiPngFix' / cgbipng_bin + args = [cbin.as_posix(), '-i', + icon_file, '-o', outfile.as_posix()] + try: + out = subprocess.run(args, capture_output=True) + except Exception: + # Fails or PNG is not crushed + shutil.copy2(icon_file, outfile.as_posix()) else: shutil.copy2(icon_file, outfile.as_posix()) app_dict['icon_path'] = outfile.name diff --git a/mobsf/StaticAnalyzer/views/ios/rules/ipa_rules.py b/mobsf/StaticAnalyzer/views/ios/rules/ipa_rules.py index eb5ac884f4..d610760853 100644 --- a/mobsf/StaticAnalyzer/views/ios/rules/ipa_rules.py +++ b/mobsf/StaticAnalyzer/views/ios/rules/ipa_rules.py @@ -2,7 +2,9 @@ """IPA Binary Analysis Rules.""" from libsast.standards import get_standards - +HIGH = 'high' +WARNING = 'warning' +INFO = 'info' STDS = get_standards() IPA_RULES = [ { @@ -20,7 +22,7 @@ rb'\b_wcslen\n\b|\b_wcsncat\n\b|\b_wcsncpy\n\b|\b_wcstok\n\b|' rb'\b_wmemcpy\n\b|\b_fopen\n\b|\b_chmod\n\b|\b_chown\n\b|' rb'\b_stat\n\b|\b_mktemp\n\b'), - 'severity': 'high', + 'severity': WARNING, 'input_case': 'exact', 'cvss': 6, 'cwe': STDS['cwe']['cwe-676'], @@ -39,7 +41,7 @@ rb'\bkCCAlgorithmRC4\b|' rb'\bkCCOptionECBMode\b|' rb'\bkCCOptionCBCMode\b'), - 'severity': 'high', + 'severity': WARNING, 'input_case': 'exact', 'cvss': 3, 'cwe': STDS['cwe']['cwe-327'], @@ -88,7 +90,7 @@ rb'SecTrustSetVerifyDate\b|\bSecCertificateRef\b|\b' rb'SecIdentityRef\b|\bSecKeyRef\b|\bSecPolicyRef\b|\b' rb'SecTrustRef\b'), - 'severity': 'info', + 'severity': INFO, 'input_case': 'exact', 'cvss': 0, 'cwe': '', @@ -113,7 +115,7 @@ rb'CC_SHA1_Update\b|\b' rb'CC_SHA1_Final\b|\bCC_SHA1\b|\bSHA1_Init\b|\b' rb'SHA1_Update\b|\bSHA1_Final\b'), - 'severity': 'high', + 'severity': WARNING, 'input_case': 'exact', 'cvss': 3, 'cwe': STDS['cwe']['cwe-327'], @@ -140,7 +142,7 @@ rb'CC_SHA512_Update\b|\bCC_SHA512_Final\b|\b' rb'CC_SHA512\b|\bSHA512_Init\b|\b' rb'SHA512_Update\b|\bSHA512_Final\b'), - 'severity': 'info', + 'severity': INFO, 'input_case': 'exact', 'cvss': 0, 'cwe': '', @@ -154,7 +156,7 @@ 'insecure Random function(s) {}'), 'type': 'Regex', 'pattern': rb'\b_srand\n\b|\b_random\n\b', - 'severity': 'high', + 'severity': WARNING, 'input_case': 'exact', 'cvss': 3, 'cwe': STDS['cwe']['cwe-330'], @@ -167,7 +169,7 @@ 'The binary may use {} function for logging.'), 'type': 'Regex', 'pattern': rb'\b_NSLog\n\b', - 'severity': 'info', + 'severity': INFO, 'input_case': 'exact', 'cvss': 7.5, 'cwe': STDS['cwe']['cwe-532'], @@ -180,7 +182,7 @@ 'The binary may use {} function instead of calloc'), 'type': 'Regex', 'pattern': rb'_malloc\n', - 'severity': 'high', + 'severity': WARNING, 'input_case': 'exact', 'cvss': 2, 'cwe': STDS['cwe']['cwe-789'], @@ -197,7 +199,7 @@ ' from AppStore.'), 'type': 'Regex', 'pattern': rb'\b_ptrace\b', - 'severity': 'warning', + 'severity': WARNING, 'input_case': 'exact', 'cvss': 0, 'cwe': '', @@ -209,7 +211,7 @@ 'detailed_desc': 'The binary may use UIWebView Component.', 'type': 'Regex', 'pattern': b'UIWebView', - 'severity': 'info', + 'severity': INFO, 'input_case': 'exact', 'cvss': 0, 'cwe': '', diff --git a/poetry.lock b/poetry.lock index b6271f3e60..c88fdfd2b9 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2386,114 +2386,101 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"] [[package]] name = "rpds-py" -version = "0.20.1" +version = "0.21.0" description = "Python bindings to Rust's persistent data structures (rpds)" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "rpds_py-0.20.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:a649dfd735fff086e8a9d0503a9f0c7d01b7912a333c7ae77e1515c08c146dad"}, - {file = "rpds_py-0.20.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f16bc1334853e91ddaaa1217045dd7be166170beec337576818461268a3de67f"}, - {file = "rpds_py-0.20.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:14511a539afee6f9ab492b543060c7491c99924314977a55c98bfa2ee29ce78c"}, - {file = "rpds_py-0.20.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3ccb8ac2d3c71cda472b75af42818981bdacf48d2e21c36331b50b4f16930163"}, - {file = "rpds_py-0.20.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c142b88039b92e7e0cb2552e8967077e3179b22359e945574f5e2764c3953dcf"}, - {file = "rpds_py-0.20.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f19169781dddae7478a32301b499b2858bc52fc45a112955e798ee307e294977"}, - {file = "rpds_py-0.20.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13c56de6518e14b9bf6edde23c4c39dac5b48dcf04160ea7bce8fca8397cdf86"}, - {file = "rpds_py-0.20.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:925d176a549f4832c6f69fa6026071294ab5910e82a0fe6c6228fce17b0706bd"}, - {file = "rpds_py-0.20.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:78f0b6877bfce7a3d1ff150391354a410c55d3cdce386f862926a4958ad5ab7e"}, - {file = "rpds_py-0.20.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3dd645e2b0dcb0fd05bf58e2e54c13875847687d0b71941ad2e757e5d89d4356"}, - {file = "rpds_py-0.20.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:4f676e21db2f8c72ff0936f895271e7a700aa1f8d31b40e4e43442ba94973899"}, - {file = "rpds_py-0.20.1-cp310-none-win32.whl", hash = "sha256:648386ddd1e19b4a6abab69139b002bc49ebf065b596119f8f37c38e9ecee8ff"}, - {file = "rpds_py-0.20.1-cp310-none-win_amd64.whl", hash = "sha256:d9ecb51120de61e4604650666d1f2b68444d46ae18fd492245a08f53ad2b7711"}, - {file = "rpds_py-0.20.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:762703bdd2b30983c1d9e62b4c88664df4a8a4d5ec0e9253b0231171f18f6d75"}, - {file = "rpds_py-0.20.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0b581f47257a9fce535c4567782a8976002d6b8afa2c39ff616edf87cbeff712"}, - {file = "rpds_py-0.20.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:842c19a6ce894493563c3bd00d81d5100e8e57d70209e84d5491940fdb8b9e3a"}, - {file = "rpds_py-0.20.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42cbde7789f5c0bcd6816cb29808e36c01b960fb5d29f11e052215aa85497c93"}, - {file = "rpds_py-0.20.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6c8e9340ce5a52f95fa7d3b552b35c7e8f3874d74a03a8a69279fd5fca5dc751"}, - {file = "rpds_py-0.20.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ba6f89cac95c0900d932c9efb7f0fb6ca47f6687feec41abcb1bd5e2bd45535"}, - {file = "rpds_py-0.20.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a916087371afd9648e1962e67403c53f9c49ca47b9680adbeef79da3a7811b0"}, - {file = "rpds_py-0.20.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:200a23239781f46149e6a415f1e870c5ef1e712939fe8fa63035cd053ac2638e"}, - {file = "rpds_py-0.20.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:58b1d5dd591973d426cbb2da5e27ba0339209832b2f3315928c9790e13f159e8"}, - {file = "rpds_py-0.20.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:6b73c67850ca7cae0f6c56f71e356d7e9fa25958d3e18a64927c2d930859b8e4"}, - {file = "rpds_py-0.20.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d8761c3c891cc51e90bc9926d6d2f59b27beaf86c74622c8979380a29cc23ac3"}, - {file = "rpds_py-0.20.1-cp311-none-win32.whl", hash = "sha256:cd945871335a639275eee904caef90041568ce3b42f402c6959b460d25ae8732"}, - {file = "rpds_py-0.20.1-cp311-none-win_amd64.whl", hash = "sha256:7e21b7031e17c6b0e445f42ccc77f79a97e2687023c5746bfb7a9e45e0921b84"}, - {file = "rpds_py-0.20.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:36785be22066966a27348444b40389f8444671630063edfb1a2eb04318721e17"}, - {file = "rpds_py-0.20.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:142c0a5124d9bd0e2976089484af5c74f47bd3298f2ed651ef54ea728d2ea42c"}, - {file = "rpds_py-0.20.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dbddc10776ca7ebf2a299c41a4dde8ea0d8e3547bfd731cb87af2e8f5bf8962d"}, - {file = "rpds_py-0.20.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:15a842bb369e00295392e7ce192de9dcbf136954614124a667f9f9f17d6a216f"}, - {file = "rpds_py-0.20.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:be5ef2f1fc586a7372bfc355986226484e06d1dc4f9402539872c8bb99e34b01"}, - {file = "rpds_py-0.20.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbcf360c9e3399b056a238523146ea77eeb2a596ce263b8814c900263e46031a"}, - {file = "rpds_py-0.20.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ecd27a66740ffd621d20b9a2f2b5ee4129a56e27bfb9458a3bcc2e45794c96cb"}, - {file = "rpds_py-0.20.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d0b937b2a1988f184a3e9e577adaa8aede21ec0b38320d6009e02bd026db04fa"}, - {file = "rpds_py-0.20.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6889469bfdc1eddf489729b471303739bf04555bb151fe8875931f8564309afc"}, - {file = "rpds_py-0.20.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:19b73643c802f4eaf13d97f7855d0fb527fbc92ab7013c4ad0e13a6ae0ed23bd"}, - {file = "rpds_py-0.20.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3c6afcf2338e7f374e8edc765c79fbcb4061d02b15dd5f8f314a4af2bdc7feb5"}, - {file = "rpds_py-0.20.1-cp312-none-win32.whl", hash = "sha256:dc73505153798c6f74854aba69cc75953888cf9866465196889c7cdd351e720c"}, - {file = "rpds_py-0.20.1-cp312-none-win_amd64.whl", hash = "sha256:8bbe951244a838a51289ee53a6bae3a07f26d4e179b96fc7ddd3301caf0518eb"}, - {file = "rpds_py-0.20.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:6ca91093a4a8da4afae7fe6a222c3b53ee4eef433ebfee4d54978a103435159e"}, - {file = "rpds_py-0.20.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b9c2fe36d1f758b28121bef29ed1dee9b7a2453e997528e7d1ac99b94892527c"}, - {file = "rpds_py-0.20.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f009c69bc8c53db5dfab72ac760895dc1f2bc1b62ab7408b253c8d1ec52459fc"}, - {file = "rpds_py-0.20.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6740a3e8d43a32629bb9b009017ea5b9e713b7210ba48ac8d4cb6d99d86c8ee8"}, - {file = "rpds_py-0.20.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:32b922e13d4c0080d03e7b62991ad7f5007d9cd74e239c4b16bc85ae8b70252d"}, - {file = "rpds_py-0.20.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fe00a9057d100e69b4ae4a094203a708d65b0f345ed546fdef86498bf5390982"}, - {file = "rpds_py-0.20.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49fe9b04b6fa685bd39237d45fad89ba19e9163a1ccaa16611a812e682913496"}, - {file = "rpds_py-0.20.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:aa7ac11e294304e615b43f8c441fee5d40094275ed7311f3420d805fde9b07b4"}, - {file = "rpds_py-0.20.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6aa97af1558a9bef4025f8f5d8c60d712e0a3b13a2fe875511defc6ee77a1ab7"}, - {file = "rpds_py-0.20.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:483b29f6f7ffa6af845107d4efe2e3fa8fb2693de8657bc1849f674296ff6a5a"}, - {file = "rpds_py-0.20.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:37fe0f12aebb6a0e3e17bb4cd356b1286d2d18d2e93b2d39fe647138458b4bcb"}, - {file = "rpds_py-0.20.1-cp313-none-win32.whl", hash = "sha256:a624cc00ef2158e04188df5e3016385b9353638139a06fb77057b3498f794782"}, - {file = "rpds_py-0.20.1-cp313-none-win_amd64.whl", hash = "sha256:b71b8666eeea69d6363248822078c075bac6ed135faa9216aa85f295ff009b1e"}, - {file = "rpds_py-0.20.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:5b48e790e0355865197ad0aca8cde3d8ede347831e1959e158369eb3493d2191"}, - {file = "rpds_py-0.20.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3e310838a5801795207c66c73ea903deda321e6146d6f282e85fa7e3e4854804"}, - {file = "rpds_py-0.20.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2249280b870e6a42c0d972339e9cc22ee98730a99cd7f2f727549af80dd5a963"}, - {file = "rpds_py-0.20.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e79059d67bea28b53d255c1437b25391653263f0e69cd7dec170d778fdbca95e"}, - {file = "rpds_py-0.20.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2b431c777c9653e569986ecf69ff4a5dba281cded16043d348bf9ba505486f36"}, - {file = "rpds_py-0.20.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:da584ff96ec95e97925174eb8237e32f626e7a1a97888cdd27ee2f1f24dd0ad8"}, - {file = "rpds_py-0.20.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:02a0629ec053fc013808a85178524e3cb63a61dbc35b22499870194a63578fb9"}, - {file = "rpds_py-0.20.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fbf15aff64a163db29a91ed0868af181d6f68ec1a3a7d5afcfe4501252840bad"}, - {file = "rpds_py-0.20.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:07924c1b938798797d60c6308fa8ad3b3f0201802f82e4a2c41bb3fafb44cc28"}, - {file = "rpds_py-0.20.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:4a5a844f68776a7715ecb30843b453f07ac89bad393431efbf7accca3ef599c1"}, - {file = "rpds_py-0.20.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:518d2ca43c358929bf08f9079b617f1c2ca6e8848f83c1225c88caeac46e6cbc"}, - {file = "rpds_py-0.20.1-cp38-none-win32.whl", hash = "sha256:3aea7eed3e55119635a74bbeb80b35e776bafccb70d97e8ff838816c124539f1"}, - {file = "rpds_py-0.20.1-cp38-none-win_amd64.whl", hash = "sha256:7dca7081e9a0c3b6490a145593f6fe3173a94197f2cb9891183ef75e9d64c425"}, - {file = "rpds_py-0.20.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:b41b6321805c472f66990c2849e152aff7bc359eb92f781e3f606609eac877ad"}, - {file = "rpds_py-0.20.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0a90c373ea2975519b58dece25853dbcb9779b05cc46b4819cb1917e3b3215b6"}, - {file = "rpds_py-0.20.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:16d4477bcb9fbbd7b5b0e4a5d9b493e42026c0bf1f06f723a9353f5153e75d30"}, - {file = "rpds_py-0.20.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:84b8382a90539910b53a6307f7c35697bc7e6ffb25d9c1d4e998a13e842a5e83"}, - {file = "rpds_py-0.20.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4888e117dd41b9d34194d9e31631af70d3d526efc363085e3089ab1a62c32ed1"}, - {file = "rpds_py-0.20.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5265505b3d61a0f56618c9b941dc54dc334dc6e660f1592d112cd103d914a6db"}, - {file = "rpds_py-0.20.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e75ba609dba23f2c95b776efb9dd3f0b78a76a151e96f96cc5b6b1b0004de66f"}, - {file = "rpds_py-0.20.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1791ff70bc975b098fe6ecf04356a10e9e2bd7dc21fa7351c1742fdeb9b4966f"}, - {file = "rpds_py-0.20.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:d126b52e4a473d40232ec2052a8b232270ed1f8c9571aaf33f73a14cc298c24f"}, - {file = "rpds_py-0.20.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:c14937af98c4cc362a1d4374806204dd51b1e12dded1ae30645c298e5a5c4cb1"}, - {file = "rpds_py-0.20.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:3d089d0b88996df627693639d123c8158cff41c0651f646cd8fd292c7da90eaf"}, - {file = "rpds_py-0.20.1-cp39-none-win32.whl", hash = "sha256:653647b8838cf83b2e7e6a0364f49af96deec64d2a6578324db58380cff82aca"}, - {file = "rpds_py-0.20.1-cp39-none-win_amd64.whl", hash = "sha256:fa41a64ac5b08b292906e248549ab48b69c5428f3987b09689ab2441f267d04d"}, - {file = "rpds_py-0.20.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:7a07ced2b22f0cf0b55a6a510078174c31b6d8544f3bc00c2bcee52b3d613f74"}, - {file = "rpds_py-0.20.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:68cb0a499f2c4a088fd2f521453e22ed3527154136a855c62e148b7883b99f9a"}, - {file = "rpds_py-0.20.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fa3060d885657abc549b2a0f8e1b79699290e5d83845141717c6c90c2df38311"}, - {file = "rpds_py-0.20.1-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:95f3b65d2392e1c5cec27cff08fdc0080270d5a1a4b2ea1d51d5f4a2620ff08d"}, - {file = "rpds_py-0.20.1-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2cc3712a4b0b76a1d45a9302dd2f53ff339614b1c29603a911318f2357b04dd2"}, - {file = "rpds_py-0.20.1-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5d4eea0761e37485c9b81400437adb11c40e13ef513375bbd6973e34100aeb06"}, - {file = "rpds_py-0.20.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f5179583d7a6cdb981151dd349786cbc318bab54963a192692d945dd3f6435d"}, - {file = "rpds_py-0.20.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2fbb0ffc754490aff6dabbf28064be47f0f9ca0b9755976f945214965b3ace7e"}, - {file = "rpds_py-0.20.1-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:a94e52537a0e0a85429eda9e49f272ada715506d3b2431f64b8a3e34eb5f3e75"}, - {file = "rpds_py-0.20.1-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:92b68b79c0da2a980b1c4197e56ac3dd0c8a149b4603747c4378914a68706979"}, - {file = "rpds_py-0.20.1-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:93da1d3db08a827eda74356f9f58884adb254e59b6664f64cc04cdff2cc19b0d"}, - {file = "rpds_py-0.20.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:754bbed1a4ca48479e9d4182a561d001bbf81543876cdded6f695ec3d465846b"}, - {file = "rpds_py-0.20.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ca449520e7484534a2a44faf629362cae62b660601432d04c482283c47eaebab"}, - {file = "rpds_py-0.20.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:9c4cb04a16b0f199a8c9bf807269b2f63b7b5b11425e4a6bd44bd6961d28282c"}, - {file = "rpds_py-0.20.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb63804105143c7e24cee7db89e37cb3f3941f8e80c4379a0b355c52a52b6780"}, - {file = "rpds_py-0.20.1-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:55cd1fa4ecfa6d9f14fbd97ac24803e6f73e897c738f771a9fe038f2f11ff07c"}, - {file = "rpds_py-0.20.1-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0f8f741b6292c86059ed175d80eefa80997125b7c478fb8769fd9ac8943a16c0"}, - {file = "rpds_py-0.20.1-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fc212779bf8411667234b3cdd34d53de6c2b8b8b958e1e12cb473a5f367c338"}, - {file = "rpds_py-0.20.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ad56edabcdb428c2e33bbf24f255fe2b43253b7d13a2cdbf05de955217313e6"}, - {file = "rpds_py-0.20.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0a3a1e9ee9728b2c1734f65d6a1d376c6f2f6fdcc13bb007a08cc4b1ff576dc5"}, - {file = "rpds_py-0.20.1-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:e13de156137b7095442b288e72f33503a469aa1980ed856b43c353ac86390519"}, - {file = "rpds_py-0.20.1-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:07f59760ef99f31422c49038964b31c4dfcfeb5d2384ebfc71058a7c9adae2d2"}, - {file = "rpds_py-0.20.1-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:59240685e7da61fb78f65a9f07f8108e36a83317c53f7b276b4175dc44151684"}, - {file = "rpds_py-0.20.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:83cba698cfb3c2c5a7c3c6bac12fe6c6a51aae69513726be6411076185a8b24a"}, - {file = "rpds_py-0.20.1.tar.gz", hash = "sha256:e1791c4aabd117653530dccd24108fa03cc6baf21f58b950d0a73c3b3b29a350"}, + {file = "rpds_py-0.21.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:a017f813f24b9df929674d0332a374d40d7f0162b326562daae8066b502d0590"}, + {file = "rpds_py-0.21.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:20cc1ed0bcc86d8e1a7e968cce15be45178fd16e2ff656a243145e0b439bd250"}, + {file = "rpds_py-0.21.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad116dda078d0bc4886cb7840e19811562acdc7a8e296ea6ec37e70326c1b41c"}, + {file = "rpds_py-0.21.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:808f1ac7cf3b44f81c9475475ceb221f982ef548e44e024ad5f9e7060649540e"}, + {file = "rpds_py-0.21.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de552f4a1916e520f2703ec474d2b4d3f86d41f353e7680b597512ffe7eac5d0"}, + {file = "rpds_py-0.21.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:efec946f331349dfc4ae9d0e034c263ddde19414fe5128580f512619abed05f1"}, + {file = "rpds_py-0.21.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b80b4690bbff51a034bfde9c9f6bf9357f0a8c61f548942b80f7b66356508bf5"}, + {file = "rpds_py-0.21.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:085ed25baac88953d4283e5b5bd094b155075bb40d07c29c4f073e10623f9f2e"}, + {file = "rpds_py-0.21.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:daa8efac2a1273eed2354397a51216ae1e198ecbce9036fba4e7610b308b6153"}, + {file = "rpds_py-0.21.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:95a5bad1ac8a5c77b4e658671642e4af3707f095d2b78a1fdd08af0dfb647624"}, + {file = "rpds_py-0.21.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3e53861b29a13d5b70116ea4230b5f0f3547b2c222c5daa090eb7c9c82d7f664"}, + {file = "rpds_py-0.21.0-cp310-none-win32.whl", hash = "sha256:ea3a6ac4d74820c98fcc9da4a57847ad2cc36475a8bd9683f32ab6d47a2bd682"}, + {file = "rpds_py-0.21.0-cp310-none-win_amd64.whl", hash = "sha256:b8f107395f2f1d151181880b69a2869c69e87ec079c49c0016ab96860b6acbe5"}, + {file = "rpds_py-0.21.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:5555db3e618a77034954b9dc547eae94166391a98eb867905ec8fcbce1308d95"}, + {file = "rpds_py-0.21.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:97ef67d9bbc3e15584c2f3c74bcf064af36336c10d2e21a2131e123ce0f924c9"}, + {file = "rpds_py-0.21.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ab2c2a26d2f69cdf833174f4d9d86118edc781ad9a8fa13970b527bf8236027"}, + {file = "rpds_py-0.21.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4e8921a259f54bfbc755c5bbd60c82bb2339ae0324163f32868f63f0ebb873d9"}, + {file = "rpds_py-0.21.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8a7ff941004d74d55a47f916afc38494bd1cfd4b53c482b77c03147c91ac0ac3"}, + {file = "rpds_py-0.21.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5145282a7cd2ac16ea0dc46b82167754d5e103a05614b724457cffe614f25bd8"}, + {file = "rpds_py-0.21.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de609a6f1b682f70bb7163da745ee815d8f230d97276db049ab447767466a09d"}, + {file = "rpds_py-0.21.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:40c91c6e34cf016fa8e6b59d75e3dbe354830777fcfd74c58b279dceb7975b75"}, + {file = "rpds_py-0.21.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d2132377f9deef0c4db89e65e8bb28644ff75a18df5293e132a8d67748397b9f"}, + {file = "rpds_py-0.21.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0a9e0759e7be10109645a9fddaaad0619d58c9bf30a3f248a2ea57a7c417173a"}, + {file = "rpds_py-0.21.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9e20da3957bdf7824afdd4b6eeb29510e83e026473e04952dca565170cd1ecc8"}, + {file = "rpds_py-0.21.0-cp311-none-win32.whl", hash = "sha256:f71009b0d5e94c0e86533c0b27ed7cacc1239cb51c178fd239c3cfefefb0400a"}, + {file = "rpds_py-0.21.0-cp311-none-win_amd64.whl", hash = "sha256:e168afe6bf6ab7ab46c8c375606298784ecbe3ba31c0980b7dcbb9631dcba97e"}, + {file = "rpds_py-0.21.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:30b912c965b2aa76ba5168fd610087bad7fcde47f0a8367ee8f1876086ee6d1d"}, + {file = "rpds_py-0.21.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ca9989d5d9b1b300bc18e1801c67b9f6d2c66b8fd9621b36072ed1df2c977f72"}, + {file = "rpds_py-0.21.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f54e7106f0001244a5f4cf810ba8d3f9c542e2730821b16e969d6887b664266"}, + {file = "rpds_py-0.21.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fed5dfefdf384d6fe975cc026886aece4f292feaf69d0eeb716cfd3c5a4dd8be"}, + {file = "rpds_py-0.21.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:590ef88db231c9c1eece44dcfefd7515d8bf0d986d64d0caf06a81998a9e8cab"}, + {file = "rpds_py-0.21.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f983e4c2f603c95dde63df633eec42955508eefd8d0f0e6d236d31a044c882d7"}, + {file = "rpds_py-0.21.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b229ce052ddf1a01c67d68166c19cb004fb3612424921b81c46e7ea7ccf7c3bf"}, + {file = "rpds_py-0.21.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ebf64e281a06c904a7636781d2e973d1f0926a5b8b480ac658dc0f556e7779f4"}, + {file = "rpds_py-0.21.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:998a8080c4495e4f72132f3d66ff91f5997d799e86cec6ee05342f8f3cda7dca"}, + {file = "rpds_py-0.21.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:98486337f7b4f3c324ab402e83453e25bb844f44418c066623db88e4c56b7c7b"}, + {file = "rpds_py-0.21.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a78d8b634c9df7f8d175451cfeac3810a702ccb85f98ec95797fa98b942cea11"}, + {file = "rpds_py-0.21.0-cp312-none-win32.whl", hash = "sha256:a58ce66847711c4aa2ecfcfaff04cb0327f907fead8945ffc47d9407f41ff952"}, + {file = "rpds_py-0.21.0-cp312-none-win_amd64.whl", hash = "sha256:e860f065cc4ea6f256d6f411aba4b1251255366e48e972f8a347cf88077b24fd"}, + {file = "rpds_py-0.21.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:ee4eafd77cc98d355a0d02f263efc0d3ae3ce4a7c24740010a8b4012bbb24937"}, + {file = "rpds_py-0.21.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:688c93b77e468d72579351a84b95f976bd7b3e84aa6686be6497045ba84be560"}, + {file = "rpds_py-0.21.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c38dbf31c57032667dd5a2f0568ccde66e868e8f78d5a0d27dcc56d70f3fcd3b"}, + {file = "rpds_py-0.21.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2d6129137f43f7fa02d41542ffff4871d4aefa724a5fe38e2c31a4e0fd343fb0"}, + {file = "rpds_py-0.21.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:520ed8b99b0bf86a176271f6fe23024323862ac674b1ce5b02a72bfeff3fff44"}, + {file = "rpds_py-0.21.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aaeb25ccfb9b9014a10eaf70904ebf3f79faaa8e60e99e19eef9f478651b9b74"}, + {file = "rpds_py-0.21.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af04ac89c738e0f0f1b913918024c3eab6e3ace989518ea838807177d38a2e94"}, + {file = "rpds_py-0.21.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b9b76e2afd585803c53c5b29e992ecd183f68285b62fe2668383a18e74abe7a3"}, + {file = "rpds_py-0.21.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5afb5efde74c54724e1a01118c6e5c15e54e642c42a1ba588ab1f03544ac8c7a"}, + {file = "rpds_py-0.21.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:52c041802a6efa625ea18027a0723676a778869481d16803481ef6cc02ea8cb3"}, + {file = "rpds_py-0.21.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ee1e4fc267b437bb89990b2f2abf6c25765b89b72dd4a11e21934df449e0c976"}, + {file = "rpds_py-0.21.0-cp313-none-win32.whl", hash = "sha256:0c025820b78817db6a76413fff6866790786c38f95ea3f3d3c93dbb73b632202"}, + {file = "rpds_py-0.21.0-cp313-none-win_amd64.whl", hash = "sha256:320c808df533695326610a1b6a0a6e98f033e49de55d7dc36a13c8a30cfa756e"}, + {file = "rpds_py-0.21.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:2c51d99c30091f72a3c5d126fad26236c3f75716b8b5e5cf8effb18889ced928"}, + {file = "rpds_py-0.21.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cbd7504a10b0955ea287114f003b7ad62330c9e65ba012c6223dba646f6ffd05"}, + {file = "rpds_py-0.21.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6dcc4949be728ede49e6244eabd04064336012b37f5c2200e8ec8eb2988b209c"}, + {file = "rpds_py-0.21.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f414da5c51bf350e4b7960644617c130140423882305f7574b6cf65a3081cecb"}, + {file = "rpds_py-0.21.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9afe42102b40007f588666bc7de82451e10c6788f6f70984629db193849dced1"}, + {file = "rpds_py-0.21.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3b929c2bb6e29ab31f12a1117c39f7e6d6450419ab7464a4ea9b0b417174f044"}, + {file = "rpds_py-0.21.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8404b3717da03cbf773a1d275d01fec84ea007754ed380f63dfc24fb76ce4592"}, + {file = "rpds_py-0.21.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e12bb09678f38b7597b8346983d2323a6482dcd59e423d9448108c1be37cac9d"}, + {file = "rpds_py-0.21.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:58a0e345be4b18e6b8501d3b0aa540dad90caeed814c515e5206bb2ec26736fd"}, + {file = "rpds_py-0.21.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:c3761f62fcfccf0864cc4665b6e7c3f0c626f0380b41b8bd1ce322103fa3ef87"}, + {file = "rpds_py-0.21.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c2b2f71c6ad6c2e4fc9ed9401080badd1469fa9889657ec3abea42a3d6b2e1ed"}, + {file = "rpds_py-0.21.0-cp39-none-win32.whl", hash = "sha256:b21747f79f360e790525e6f6438c7569ddbfb1b3197b9e65043f25c3c9b489d8"}, + {file = "rpds_py-0.21.0-cp39-none-win_amd64.whl", hash = "sha256:0626238a43152918f9e72ede9a3b6ccc9e299adc8ade0d67c5e142d564c9a83d"}, + {file = "rpds_py-0.21.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:6b4ef7725386dc0762857097f6b7266a6cdd62bfd209664da6712cb26acef035"}, + {file = "rpds_py-0.21.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:6bc0e697d4d79ab1aacbf20ee5f0df80359ecf55db33ff41481cf3e24f206919"}, + {file = "rpds_py-0.21.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da52d62a96e61c1c444f3998c434e8b263c384f6d68aca8274d2e08d1906325c"}, + {file = "rpds_py-0.21.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:98e4fe5db40db87ce1c65031463a760ec7906ab230ad2249b4572c2fc3ef1f9f"}, + {file = "rpds_py-0.21.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:30bdc973f10d28e0337f71d202ff29345320f8bc49a31c90e6c257e1ccef4333"}, + {file = "rpds_py-0.21.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:faa5e8496c530f9c71f2b4e1c49758b06e5f4055e17144906245c99fa6d45356"}, + {file = "rpds_py-0.21.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:32eb88c30b6a4f0605508023b7141d043a79b14acb3b969aa0b4f99b25bc7d4a"}, + {file = "rpds_py-0.21.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a89a8ce9e4e75aeb7fa5d8ad0f3fecdee813802592f4f46a15754dcb2fd6b061"}, + {file = "rpds_py-0.21.0-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:241e6c125568493f553c3d0fdbb38c74babf54b45cef86439d4cd97ff8feb34d"}, + {file = "rpds_py-0.21.0-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:3b766a9f57663396e4f34f5140b3595b233a7b146e94777b97a8413a1da1be18"}, + {file = "rpds_py-0.21.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:af4a644bf890f56e41e74be7d34e9511e4954894d544ec6b8efe1e21a1a8da6c"}, + {file = "rpds_py-0.21.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:3e30a69a706e8ea20444b98a49f386c17b26f860aa9245329bab0851ed100677"}, + {file = "rpds_py-0.21.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:031819f906bb146561af051c7cef4ba2003d28cff07efacef59da973ff7969ba"}, + {file = "rpds_py-0.21.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:b876f2bc27ab5954e2fd88890c071bd0ed18b9c50f6ec3de3c50a5ece612f7a6"}, + {file = "rpds_py-0.21.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dc5695c321e518d9f03b7ea6abb5ea3af4567766f9852ad1560f501b17588c7b"}, + {file = "rpds_py-0.21.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b4de1da871b5c0fd5537b26a6fc6814c3cc05cabe0c941db6e9044ffbb12f04a"}, + {file = "rpds_py-0.21.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:878f6fea96621fda5303a2867887686d7a198d9e0f8a40be100a63f5d60c88c9"}, + {file = "rpds_py-0.21.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8eeec67590e94189f434c6d11c426892e396ae59e4801d17a93ac96b8c02a6c"}, + {file = "rpds_py-0.21.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ff2eba7f6c0cb523d7e9cff0903f2fe1feff8f0b2ceb6bd71c0e20a4dcee271"}, + {file = "rpds_py-0.21.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a429b99337062877d7875e4ff1a51fe788424d522bd64a8c0a20ef3021fdb6ed"}, + {file = "rpds_py-0.21.0-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:d167e4dbbdac48bd58893c7e446684ad5d425b407f9336e04ab52e8b9194e2ed"}, + {file = "rpds_py-0.21.0-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:4eb2de8a147ffe0626bfdc275fc6563aa7bf4b6db59cf0d44f0ccd6ca625a24e"}, + {file = "rpds_py-0.21.0-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:e78868e98f34f34a88e23ee9ccaeeec460e4eaf6db16d51d7a9b883e5e785a5e"}, + {file = "rpds_py-0.21.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:4991ca61656e3160cdaca4851151fd3f4a92e9eba5c7a530ab030d6aee96ec89"}, + {file = "rpds_py-0.21.0.tar.gz", hash = "sha256:ed6378c9d66d0de903763e7706383d60c33829581f0adff47b6535f1802fa6db"}, ] [[package]] diff --git a/pyproject.toml b/pyproject.toml index a7c3195ac5..0ea75177a0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "mobsf" -version = "4.1.4" +version = "4.1.5" description = "Mobile Security Framework (MobSF) is an automated, all-in-one mobile application (Android/iOS/Windows) pen-testing, malware analysis and security assessment framework capable of performing static and dynamic analysis." keywords = ["mobsf", "mobile security framework", "mobile security", "security tool", "static analysis", "dynamic analysis", "malware analysis"] authors = ["Ajin Abraham "]