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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: devshield-scanner
3
- Version: 0.2.0
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. Example for the large container export discussed during validation: `devshield --remediate-running --max-files 200000 --max-filesize-mb 1536 --max-scansize-mb 2048`. Limits do not apply to process snapshots, which retain ClamAV defaults with limit alerts. 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.
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. Example for the large container export discussed during validation: `devshield --remediate-running --max-files 200000 --max-filesize-mb 1536 --max-scansize-mb 2048`. Limits do not apply to process snapshots, which retain ClamAV defaults with limit alerts. 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.
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.0')
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
- if args.max_filesize_mb is not None:
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(['clamscan', '--infected', '--alert-exceeds-max=yes', '--', str(snapshot)], f'Process executable PID {pid}')
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.0
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. Example for the large container export discussed during validation: `devshield --remediate-running --max-files 200000 --max-filesize-mb 1536 --max-scansize-mb 2048`. Limits do not apply to process snapshots, which retain ClamAV defaults with limit alerts. 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.
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.0"
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"