flyshell 1.1.0__tar.gz → 1.1.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {flyshell-1.1.0/src/flyshell.egg-info → flyshell-1.1.2}/PKG-INFO +1 -1
- {flyshell-1.1.0 → flyshell-1.1.2}/src/flyshell/builtin/system.py +20 -15
- {flyshell-1.1.0 → flyshell-1.1.2}/src/flyshell/constants.py +2 -5
- {flyshell-1.1.0 → flyshell-1.1.2}/src/flyshell/core/directory.py +3 -0
- {flyshell-1.1.0 → flyshell-1.1.2}/src/flyshell/core/loader.py +2 -1
- {flyshell-1.1.0 → flyshell-1.1.2/src/flyshell.egg-info}/PKG-INFO +1 -1
- {flyshell-1.1.0 → flyshell-1.1.2}/tests/test_security.py +8 -0
- {flyshell-1.1.0 → flyshell-1.1.2}/LICENSE +0 -0
- {flyshell-1.1.0 → flyshell-1.1.2}/README.md +0 -0
- {flyshell-1.1.0 → flyshell-1.1.2}/pyproject.toml +0 -0
- {flyshell-1.1.0 → flyshell-1.1.2}/setup.cfg +0 -0
- {flyshell-1.1.0 → flyshell-1.1.2}/src/flyshell/__init__.py +0 -0
- {flyshell-1.1.0 → flyshell-1.1.2}/src/flyshell/abstract/__init__.py +0 -0
- {flyshell-1.1.0 → flyshell-1.1.2}/src/flyshell/abstract/base_cmd.py +0 -0
- {flyshell-1.1.0 → flyshell-1.1.2}/src/flyshell/abstract/base_plugin.py +0 -0
- {flyshell-1.1.0 → flyshell-1.1.2}/src/flyshell/abstract/parent_cmd.py +0 -0
- {flyshell-1.1.0 → flyshell-1.1.2}/src/flyshell/builtin/__init__.py +0 -0
- {flyshell-1.1.0 → flyshell-1.1.2}/src/flyshell/builtin/diskops.py +0 -0
- {flyshell-1.1.0 → flyshell-1.1.2}/src/flyshell/builtin/fs.py +0 -0
- {flyshell-1.1.0 → flyshell-1.1.2}/src/flyshell/builtin/utils.py +0 -0
- {flyshell-1.1.0 → flyshell-1.1.2}/src/flyshell/core/__init__.py +0 -0
- {flyshell-1.1.0 → flyshell-1.1.2}/src/flyshell/core/auth.py +0 -0
- {flyshell-1.1.0 → flyshell-1.1.2}/src/flyshell/core/console.py +0 -0
- {flyshell-1.1.0 → flyshell-1.1.2}/src/flyshell/core/data.py +0 -0
- {flyshell-1.1.0 → flyshell-1.1.2}/src/flyshell/main.py +0 -0
- {flyshell-1.1.0 → flyshell-1.1.2}/src/flyshell.egg-info/SOURCES.txt +0 -0
- {flyshell-1.1.0 → flyshell-1.1.2}/src/flyshell.egg-info/dependency_links.txt +0 -0
- {flyshell-1.1.0 → flyshell-1.1.2}/src/flyshell.egg-info/entry_points.txt +0 -0
- {flyshell-1.1.0 → flyshell-1.1.2}/src/flyshell.egg-info/requires.txt +0 -0
- {flyshell-1.1.0 → flyshell-1.1.2}/src/flyshell.egg-info/top_level.txt +0 -0
- {flyshell-1.1.0 → flyshell-1.1.2}/tests/test_auth.py +0 -0
- {flyshell-1.1.0 → flyshell-1.1.2}/tests/test_data.py +0 -0
- {flyshell-1.1.0 → flyshell-1.1.2}/tests/test_directory.py +0 -0
- {flyshell-1.1.0 → flyshell-1.1.2}/tests/test_loader.py +0 -0
|
@@ -73,32 +73,36 @@ class SysExe(BaseCmd):
|
|
|
73
73
|
aliases = []
|
|
74
74
|
|
|
75
75
|
def execute(self, args):
|
|
76
|
+
if not args:
|
|
77
|
+
return (1, "\nCommand Error: 'sys' requires at least 1 parameter(s).\n")
|
|
76
78
|
if args[0] in ["-f", "--force"]:
|
|
77
79
|
override = True
|
|
78
|
-
|
|
79
|
-
if not
|
|
80
|
+
cmd_args = args[1:]
|
|
81
|
+
if not cmd_args:
|
|
80
82
|
return (1, "\nCommand Error: 'sys' requires at least 1 parameter(s).\n")
|
|
81
83
|
else:
|
|
82
84
|
override = False
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
for
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
85
|
+
cmd_args = args
|
|
86
|
+
tokens_lower = [token.lower().strip("\"'") for token in cmd_args]
|
|
87
|
+
|
|
88
|
+
def matches_pattern(target_set):
|
|
89
|
+
for token in tokens_lower:
|
|
90
|
+
base_name = os.path.splitext(os.path.basename(token))[0]
|
|
91
|
+
if token in target_set or base_name in target_set:
|
|
92
|
+
return True
|
|
93
|
+
return False
|
|
94
|
+
|
|
95
|
+
if matches_pattern(c.BLOCKED_COMMANDS):
|
|
96
|
+
cmd_display = " ".join(cmd_args)
|
|
93
97
|
return (
|
|
94
98
|
1,
|
|
95
99
|
(
|
|
96
100
|
"\nSecurity Error: Flyshell has blocked execution of this command.\n"
|
|
97
|
-
f"This command '{
|
|
101
|
+
f"This command '{cmd_display}' is permanently restricted by Flyshell safety policy.\n"
|
|
98
102
|
"Flyshell has blocked your command to prevent damage to your computer.\n"
|
|
99
103
|
),
|
|
100
104
|
)
|
|
101
|
-
|
|
105
|
+
if not override and matches_pattern(c.DANGER_COMMANDS):
|
|
102
106
|
password = getpass.getpass(
|
|
103
107
|
"\nThis command is restricted. To execute, enter your password: "
|
|
104
108
|
)
|
|
@@ -109,7 +113,8 @@ class SysExe(BaseCmd):
|
|
|
109
113
|
return (1, "\nAccount Error: Password does not match.\n")
|
|
110
114
|
try:
|
|
111
115
|
print()
|
|
112
|
-
|
|
116
|
+
raw_cmd = " ".join(cmd_args)
|
|
117
|
+
result = subprocess.run(raw_cmd, shell=True)
|
|
113
118
|
print()
|
|
114
119
|
return (result.returncode, "")
|
|
115
120
|
except KeyboardInterrupt:
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
# src\flyshell\constants.py
|
|
2
2
|
|
|
3
|
-
from flyshell.core.directory import COMMAND_REGISTRY
|
|
4
|
-
|
|
5
3
|
from pathlib import Path
|
|
6
4
|
import os
|
|
7
5
|
import platform
|
|
8
6
|
import time
|
|
9
7
|
|
|
10
|
-
BUILD =
|
|
11
|
-
VERSION = "1.1.
|
|
8
|
+
BUILD = 115
|
|
9
|
+
VERSION = "1.1.2"
|
|
12
10
|
|
|
13
11
|
|
|
14
12
|
def _resolve_app_dir() -> Path:
|
|
@@ -36,7 +34,6 @@ SESSION_START_TIME = time.time()
|
|
|
36
34
|
SESSION_CMD_COUNT = 0
|
|
37
35
|
|
|
38
36
|
PLUGINS = {}
|
|
39
|
-
RESERVED_NAMES = set(COMMAND_REGISTRY.keys())
|
|
40
37
|
|
|
41
38
|
BLOCKED_COMMANDS = frozenset({"format", "diskpart", "dd"})
|
|
42
39
|
DANGER_COMMANDS = frozenset({"del", "rmdir", "rd", "rm", "taskkill", "killall"})
|
|
@@ -71,12 +71,15 @@ INSTALLED_COMMANDS: list[BaseCmd] = [
|
|
|
71
71
|
system.SysExe(),
|
|
72
72
|
diskops.Touch(),
|
|
73
73
|
]
|
|
74
|
+
|
|
74
75
|
COMMAND_REGISTRY: dict[str, BaseCmd] = {}
|
|
75
76
|
for cmd_obj in INSTALLED_COMMANDS:
|
|
76
77
|
COMMAND_REGISTRY[cmd_obj.name] = cmd_obj
|
|
77
78
|
for alias_name in cmd_obj.aliases:
|
|
78
79
|
COMMAND_REGISTRY[alias_name] = cmd_obj
|
|
79
80
|
|
|
81
|
+
RESERVED_NAMES = set(COMMAND_REGISTRY.keys())
|
|
82
|
+
|
|
80
83
|
|
|
81
84
|
def log(cmd):
|
|
82
85
|
utc_now = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
from flyshell import constants as c
|
|
4
4
|
from flyshell.abstract.base_plugin import BasePlugin
|
|
5
5
|
from flyshell.core import data
|
|
6
|
+
from flyshell.core.directory import RESERVED_NAMES
|
|
6
7
|
|
|
7
8
|
from pathlib import Path
|
|
8
9
|
import importlib.util
|
|
@@ -51,7 +52,7 @@ def scan_plugins(plugin_folder=None):
|
|
|
51
52
|
first_print = True
|
|
52
53
|
for name, entries in candidates.items():
|
|
53
54
|
failed = False
|
|
54
|
-
if name in
|
|
55
|
+
if name in RESERVED_NAMES:
|
|
55
56
|
print(
|
|
56
57
|
f"\n⚠️ Collision Error - Plugin '{name}' conflicts with a built-in Flyshell command and will not be loaded."
|
|
57
58
|
)
|
|
@@ -31,3 +31,11 @@ def test_sysexe_force_flag_without_arguments_returns_error():
|
|
|
31
31
|
code, message = system.SysExe().execute(["-f"])
|
|
32
32
|
assert code == 1
|
|
33
33
|
assert "requires at least 1 parameter" in message
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def test_sysexe_blocks_command_with_path_or_extension():
|
|
37
|
+
for cmd in ["/bin/dd if=/dev/zero", "diskpart.exe", "format.com"]:
|
|
38
|
+
tokens = cmd.split()
|
|
39
|
+
code, message = system.SysExe().execute(tokens)
|
|
40
|
+
assert code == 1
|
|
41
|
+
assert "Security Error" in message
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|