devshield-scanner 0.2.0__tar.gz → 0.2.1__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.
- {devshield_scanner-0.2.0/devshield_scanner.egg-info → devshield_scanner-0.2.1}/PKG-INFO +4 -2
- {devshield_scanner-0.2.0 → devshield_scanner-0.2.1}/README.md +3 -1
- {devshield_scanner-0.2.0 → devshield_scanner-0.2.1}/devshield_linux.py +15 -8
- {devshield_scanner-0.2.0 → devshield_scanner-0.2.1}/devshield_processes.py +6 -2
- {devshield_scanner-0.2.0 → devshield_scanner-0.2.1/devshield_scanner.egg-info}/PKG-INFO +4 -2
- {devshield_scanner-0.2.0 → devshield_scanner-0.2.1}/pyproject.toml +1 -1
- {devshield_scanner-0.2.0 → devshield_scanner-0.2.1}/LICENSE +0 -0
- {devshield_scanner-0.2.0 → devshield_scanner-0.2.1}/devshield_scanner.egg-info/SOURCES.txt +0 -0
- {devshield_scanner-0.2.0 → devshield_scanner-0.2.1}/devshield_scanner.egg-info/dependency_links.txt +0 -0
- {devshield_scanner-0.2.0 → devshield_scanner-0.2.1}/devshield_scanner.egg-info/entry_points.txt +0 -0
- {devshield_scanner-0.2.0 → devshield_scanner-0.2.1}/devshield_scanner.egg-info/top_level.txt +0 -0
- {devshield_scanner-0.2.0 → devshield_scanner-0.2.1}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: devshield-scanner
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: Linux host/Docker inspection with opt-in response for detected process executables
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Classifier: Development Status :: 3 - Alpha
|
|
@@ -14,13 +14,15 @@ Dynamic: license-file
|
|
|
14
14
|
|
|
15
15
|
# DevShield for Linux
|
|
16
16
|
|
|
17
|
+
0.2.1 fixes custom scan-limit propagation: `--max-filesize-mb`, `--max-scansize-mb`, and `--max-files` now apply to running-process snapshots as well as filesystem/container scans. Use `--remediate-running --skip-host --skip-docker` to run only the process stage. This remains an opt-in mode that can interrupt services.
|
|
18
|
+
|
|
17
19
|
## Process-first response (0.2.0)
|
|
18
20
|
|
|
19
21
|
`sudo /opt/devshield/bin/devshield --remediate-running` first snapshots and scans running executables, sends SIGKILL to signature-detected processes, and attempts to move matching host executables into `/var/lib/devshield/quarantine`. It then scans host files and Docker data. Without this flag, scanning remains read-only. This is an experimental opt-in response mode and can interrupt production services. Process response currently requires root and Python/Linux pidfd support (normally Python 3.9+ and Linux 5.3+).
|
|
20
22
|
|
|
21
23
|
Heuristic, PUA, encrypted-content, scan-limit and EICAR test alerts never trigger automatic process response. Evidence copies and action records are saved before termination. PID 1, DevShield and its ancestors are excluded. Original-file moves require a matching inode and a same-filesystem rename; failures are reported rather than falling back to destructive copy/delete. Container executables are not moved: rebuild affected containers from trusted images. Supervisors may restart terminated processes. Script interpreters, injected code, memory-only malware and persistence are not comprehensively inspected, and files found during the subsequent host/container scan are not automatically removed. Quarantine samples must not be executed. Quarantine is excluded from later scans.
|
|
22
24
|
|
|
23
|
-
`--max-files 200000` raises the archive member-count limit when needed.
|
|
25
|
+
`--max-files 200000` raises the archive member-count limit when needed. Increasing limits raises resource use. A privileged attacker can still evade or interfere with live-host inspection. There is no guarantee of complete malware removal.
|
|
24
26
|
|
|
25
27
|
An installable Python CLI package is included. The Python distribution is `devshield-scanner`; the command is `devshield`. See **INSTALL.md** for isolated installation under `/opt/devshield`. `devshield --version` displays the CLI version.
|
|
26
28
|
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
# DevShield for Linux
|
|
2
2
|
|
|
3
|
+
0.2.1 fixes custom scan-limit propagation: `--max-filesize-mb`, `--max-scansize-mb`, and `--max-files` now apply to running-process snapshots as well as filesystem/container scans. Use `--remediate-running --skip-host --skip-docker` to run only the process stage. This remains an opt-in mode that can interrupt services.
|
|
4
|
+
|
|
3
5
|
## Process-first response (0.2.0)
|
|
4
6
|
|
|
5
7
|
`sudo /opt/devshield/bin/devshield --remediate-running` first snapshots and scans running executables, sends SIGKILL to signature-detected processes, and attempts to move matching host executables into `/var/lib/devshield/quarantine`. It then scans host files and Docker data. Without this flag, scanning remains read-only. This is an experimental opt-in response mode and can interrupt production services. Process response currently requires root and Python/Linux pidfd support (normally Python 3.9+ and Linux 5.3+).
|
|
6
8
|
|
|
7
9
|
Heuristic, PUA, encrypted-content, scan-limit and EICAR test alerts never trigger automatic process response. Evidence copies and action records are saved before termination. PID 1, DevShield and its ancestors are excluded. Original-file moves require a matching inode and a same-filesystem rename; failures are reported rather than falling back to destructive copy/delete. Container executables are not moved: rebuild affected containers from trusted images. Supervisors may restart terminated processes. Script interpreters, injected code, memory-only malware and persistence are not comprehensively inspected, and files found during the subsequent host/container scan are not automatically removed. Quarantine samples must not be executed. Quarantine is excluded from later scans.
|
|
8
10
|
|
|
9
|
-
`--max-files 200000` raises the archive member-count limit when needed.
|
|
11
|
+
`--max-files 200000` raises the archive member-count limit when needed. Increasing limits raises resource use. A privileged attacker can still evade or interfere with live-host inspection. There is no guarantee of complete malware removal.
|
|
10
12
|
|
|
11
13
|
An installable Python CLI package is included. The Python distribution is `devshield-scanner`; the command is `devshield`. See **INSTALL.md** for isolated installation under `/opt/devshield`. `devshield --version` displays the CLI version.
|
|
12
14
|
|
|
@@ -15,6 +15,17 @@ import time
|
|
|
15
15
|
from devshield_processes import inspect_running
|
|
16
16
|
|
|
17
17
|
|
|
18
|
+
def clamav_limits(args):
|
|
19
|
+
options = []
|
|
20
|
+
if args.max_filesize_mb is not None:
|
|
21
|
+
options.append(f'--max-filesize={args.max_filesize_mb}M')
|
|
22
|
+
if args.max_scansize_mb is not None:
|
|
23
|
+
options.append(f'--max-scansize={args.max_scansize_mb}M')
|
|
24
|
+
if args.max_files is not None:
|
|
25
|
+
options.append(f'--max-files={args.max_files}')
|
|
26
|
+
return options
|
|
27
|
+
|
|
28
|
+
|
|
18
29
|
def coverage_warnings(log_path):
|
|
19
30
|
"""Read logs incrementally; a zero exit code alone does not establish coverage."""
|
|
20
31
|
warnings = set()
|
|
@@ -36,7 +47,7 @@ def coverage_warnings(log_path):
|
|
|
36
47
|
|
|
37
48
|
def main():
|
|
38
49
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
39
|
-
parser.add_argument('--version', action='version', version='DevShield 0.2.
|
|
50
|
+
parser.add_argument('--version', action='version', version='DevShield 0.2.1')
|
|
40
51
|
parser.add_argument('--remediate-running', action='store_true', help='FIRST scan process executables; kill signature-detected processes and quarantine host binaries. Can interrupt services.')
|
|
41
52
|
parser.add_argument('--quarantine', default='/var/lib/devshield/quarantine', help='Root-owned 0700 quarantine directory')
|
|
42
53
|
parser.add_argument('--max-files', type=int, help='ClamAV maximum archive member count')
|
|
@@ -49,6 +60,7 @@ def main():
|
|
|
49
60
|
parser.add_argument('--temp-dir', help='Scratch filesystem with enough space for container exports')
|
|
50
61
|
parser.add_argument('--heartbeat', type=int, default=10)
|
|
51
62
|
args = parser.parse_args()
|
|
63
|
+
scan_options = clamav_limits(args)
|
|
52
64
|
if not sys.platform.startswith('linux'):
|
|
53
65
|
parser.error('Run this script on Linux.')
|
|
54
66
|
if args.heartbeat < 1:
|
|
@@ -110,12 +122,7 @@ def main():
|
|
|
110
122
|
def scan(path, label, excludes=()):
|
|
111
123
|
command = ['clamscan', '--recursive=yes', '--infected', '--verbose', '--scan-archive=yes',
|
|
112
124
|
'--cross-fs=yes', '--follow-dir-symlinks=0', '--follow-file-symlinks=0', '--alert-exceeds-max=yes']
|
|
113
|
-
|
|
114
|
-
command.append(f'--max-filesize={args.max_filesize_mb}M')
|
|
115
|
-
if args.max_scansize_mb is not None:
|
|
116
|
-
command.append(f'--max-scansize={args.max_scansize_mb}M')
|
|
117
|
-
if args.max_files is not None:
|
|
118
|
-
command.append(f'--max-files={args.max_files}')
|
|
125
|
+
command.extend(scan_options)
|
|
119
126
|
command.extend('--exclude-dir=^' + re.escape(str(Path(p).resolve())) + r'(/|$)' for p in excludes)
|
|
120
127
|
rc, log = run([*command, '--', str(path)], label)
|
|
121
128
|
warnings = coverage_warnings(log)
|
|
@@ -136,7 +143,7 @@ def main():
|
|
|
136
143
|
report['engine'] = version.stdout.strip()
|
|
137
144
|
save()
|
|
138
145
|
if args.remediate_running:
|
|
139
|
-
inspect_running(run, issue, save, report, scratch.name, args.quarantine, coverage_warnings)
|
|
146
|
+
inspect_running(run, issue, save, report, scratch.name, args.quarantine, coverage_warnings, scan_options)
|
|
140
147
|
if not args.skip_host:
|
|
141
148
|
if not Path(args.host_root).is_dir():
|
|
142
149
|
issue('Host root is not a directory: ' + args.host_root)
|
|
@@ -7,6 +7,10 @@ import signal
|
|
|
7
7
|
import stat
|
|
8
8
|
|
|
9
9
|
|
|
10
|
+
def process_scan_command(snapshot, scan_options=()):
|
|
11
|
+
return ['clamscan', '--infected', '--alert-exceeds-max=yes', *scan_options, '--', str(snapshot)]
|
|
12
|
+
|
|
13
|
+
|
|
10
14
|
def signature_names(log_path):
|
|
11
15
|
names = []
|
|
12
16
|
with open(log_path, encoding='utf-8', errors='replace') as stream:
|
|
@@ -56,7 +60,7 @@ def move_original(source, before, destination):
|
|
|
56
60
|
os.close(parentfd)
|
|
57
61
|
|
|
58
62
|
|
|
59
|
-
def inspect_running(run, issue, save, report, scratch, quarantine, coverage_warnings):
|
|
63
|
+
def inspect_running(run, issue, save, report, scratch, quarantine, coverage_warnings, scan_options=()):
|
|
60
64
|
"""Scan immutable copies, pin process identities, preserve evidence before SIGKILL."""
|
|
61
65
|
if os.geteuid() != 0:
|
|
62
66
|
issue('Running-process response requires root; stage skipped.')
|
|
@@ -97,7 +101,7 @@ def inspect_running(run, issue, save, report, scratch, quarantine, coverage_warn
|
|
|
97
101
|
target.write(block)
|
|
98
102
|
with snapshot.open('rb') as target:
|
|
99
103
|
snapshot_hash = digest(target)
|
|
100
|
-
rc, log = run(
|
|
104
|
+
rc, log = run(process_scan_command(snapshot, scan_options), f'Process executable PID {pid}')
|
|
101
105
|
for warning in coverage_warnings(log):
|
|
102
106
|
issue(f'PID {pid}: {warning} See {log}')
|
|
103
107
|
names = signature_names(log) if rc == 1 else []
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: devshield-scanner
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: Linux host/Docker inspection with opt-in response for detected process executables
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Classifier: Development Status :: 3 - Alpha
|
|
@@ -14,13 +14,15 @@ Dynamic: license-file
|
|
|
14
14
|
|
|
15
15
|
# DevShield for Linux
|
|
16
16
|
|
|
17
|
+
0.2.1 fixes custom scan-limit propagation: `--max-filesize-mb`, `--max-scansize-mb`, and `--max-files` now apply to running-process snapshots as well as filesystem/container scans. Use `--remediate-running --skip-host --skip-docker` to run only the process stage. This remains an opt-in mode that can interrupt services.
|
|
18
|
+
|
|
17
19
|
## Process-first response (0.2.0)
|
|
18
20
|
|
|
19
21
|
`sudo /opt/devshield/bin/devshield --remediate-running` first snapshots and scans running executables, sends SIGKILL to signature-detected processes, and attempts to move matching host executables into `/var/lib/devshield/quarantine`. It then scans host files and Docker data. Without this flag, scanning remains read-only. This is an experimental opt-in response mode and can interrupt production services. Process response currently requires root and Python/Linux pidfd support (normally Python 3.9+ and Linux 5.3+).
|
|
20
22
|
|
|
21
23
|
Heuristic, PUA, encrypted-content, scan-limit and EICAR test alerts never trigger automatic process response. Evidence copies and action records are saved before termination. PID 1, DevShield and its ancestors are excluded. Original-file moves require a matching inode and a same-filesystem rename; failures are reported rather than falling back to destructive copy/delete. Container executables are not moved: rebuild affected containers from trusted images. Supervisors may restart terminated processes. Script interpreters, injected code, memory-only malware and persistence are not comprehensively inspected, and files found during the subsequent host/container scan are not automatically removed. Quarantine samples must not be executed. Quarantine is excluded from later scans.
|
|
22
24
|
|
|
23
|
-
`--max-files 200000` raises the archive member-count limit when needed.
|
|
25
|
+
`--max-files 200000` raises the archive member-count limit when needed. Increasing limits raises resource use. A privileged attacker can still evade or interfere with live-host inspection. There is no guarantee of complete malware removal.
|
|
24
26
|
|
|
25
27
|
An installable Python CLI package is included. The Python distribution is `devshield-scanner`; the command is `devshield`. See **INSTALL.md** for isolated installation under `/opt/devshield`. `devshield --version` displays the CLI version.
|
|
26
28
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "devshield-scanner"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.1"
|
|
8
8
|
description = "Linux host/Docker inspection with opt-in response for detected process executables"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.8"
|
|
File without changes
|
|
File without changes
|
{devshield_scanner-0.2.0 → devshield_scanner-0.2.1}/devshield_scanner.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{devshield_scanner-0.2.0 → devshield_scanner-0.2.1}/devshield_scanner.egg-info/entry_points.txt
RENAMED
|
File without changes
|
{devshield_scanner-0.2.0 → devshield_scanner-0.2.1}/devshield_scanner.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|