legion-gui

maintainer pacmanics · 1 votes · scanned 2026-08-03 00:08:14.047287
LOW
View on AUR ↗
Why flagged The flagged 'pip install' is not present; the PKGBUILD uses system packages and modifies bundled Python scripts for Arch compatibility, with no execution of remote code or untrusted dependencies.

Triggered rules

LOW AI review downgraded a static finding llm_review

The static rules flagged this MEDIUM, but an AI model (qwen/qwen3-235b-a22b-07-25) reviewed the full PKGBUILD and judged it LOW (confidence 95%): The flagged 'pip install' is not present; the PKGBUILD uses system packages and modifies bundled Python scripts for Arch compatibility, with no execution of remote code or untrusted dependencies.

1 higher static finding superseded - not the current verdict (shown for transparency)
MEDIUM pip install of an external package pip_install_external

`pip install <package>` fetches an unpinned package from PyPI at build time, outside source=() and makepkg's checksums.

  • PKGBUILD:399 eyewitness-venv/bin/pip install -U pip wheel setuptools
  • PKGBUILD:400 eyewitness-venv/bin/pip install -r setup/requirements.txt

PKGBUILD

2 offending line(s) highlighted
1pkgname=legion-gui
2pkgver=0.7.0.r0.c4a3604
3pkgrel=14
4pkgdesc="Legion GUI (Sparta successor), ported from Kali Linux for Arch Linux"
5arch=("any")
6url="https://gitlab.com/kalilinux/packages/legion"
7license=("GPL-3.0-only")
8backup=("etc/legion.conf")
9depends=("python" "polkit" "nmap" "xterm" "xdg-utils" "python-colorama" "python-pandas" "python-pyfiglet" "python-pyqt6" "python-qasync" "python-requests" "python-rich" "python-service-identity" "python-six" "python-sqlalchemy" "python-termcolor" "python-urllib3" "chromium" "xorg-server-xvfb" "curl" "nikto" "whatweb" "wpscan" "hydra" "gobuster" "feroxbuster-bin" "nuclei-bin" "httpx-bin" "dirsearch" "ffuf" "katana-bin" "dirb" "smtp-user-enum-git")
10optdepends=()
11makedepends=("git" "patch" "perl" "python-pip")
12source=("git+https://gitlab.com/kalilinux/packages/legion.git#branch=kali/master" "eyewitness::git+https://github.com/RedSiege/EyeWitness.git#branch=master" "legion-gui.desktop" "legion-gui-launcher")
13sha256sums=("SKIP" "SKIP" "SKIP" "SKIP")
14
15prepare() {
16 cd "$srcdir/legion"
17
18 patch -Np1 -i debian/patches/use-python3-shebang.patch
19 patch -Np1 -i debian/patches/fix-paths.patch
20 patch -Np1 -i debian/patches/Remove-rwho-usage.patch
21 patch -Np1 -i debian/patches/Fix-sqlalchemy.exc.ArgumentError.patch
22 patch -Np1 -i debian/patches/fix-pyexploitdb-import.patch
23 patch -Np1 -i debian/patches/fix-typo-in-ssh-user-list.patch
24
25 sed -i "s|^texteditor-path=.*|texteditor-path=/usr/bin/xdg-open|" legion.conf
26 sed -i "s|smtp-user-enum -M|smtp-user-enum.pl -M|" legion.conf
27 grep -q '^nikto="http,https,ssl,soap,http-proxy,http-alt,https-alt", tcp$' legion.conf || sed -i '/^screenshooter="http,https,ssl,http-proxy,http-alt,https-alt", tcp$/a nikto="http,https,ssl,soap,http-proxy,http-alt,https-alt", tcp' legion.conf
28
29 cat > scripts/python/pyShodan.py <<'PYSHODAN'
30#!/usr/bin/env python3
31import sys
32
33
34class PyShodanScript:
35 def __init__(self):
36 self.dbHost = None
37 self.session = None
38
39 def setDbHost(self, dbHost):
40 self.dbHost = dbHost
41
42 def setSession(self, session):
43 self.session = session
44
45 def run(self):
46 if not self.dbHost or not hasattr(self.dbHost, "ipv4"):
47 print("No dbHost or ipv4 provided.")
48 return {}
49
50 ip = str(self.dbHost.ipv4)
51 return self.lookup(ip)
52
53 def lookup(self, ip):
54 try:
55 from pyShodan import PyShodan
56 except ImportError:
57 print("pyShodan module not installed.")
58 return {}
59
60 try:
61 pyShodanObj = PyShodan()
62 pyShodanObj.apiKey = ""
63 pyShodanObj.createSession()
64 pyShodanResults = pyShodanObj.searchIp(ip, allData=True)
65
66 if isinstance(pyShodanResults, dict) and pyShodanResults:
67 if self.dbHost and self.session:
68 self.dbHost.latitude = pyShodanResults.get("latitude", "unknown")
69 self.dbHost.longitude = pyShodanResults.get("longitude", "unknown")
70 self.dbHost.asn = pyShodanResults.get("asn", "unknown")
71 self.dbHost.isp = pyShodanResults.get("isp", "unknown")
72 self.dbHost.city = pyShodanResults.get("city", "unknown")
73 self.dbHost.countryCode = pyShodanResults.get("country_code", "unknown")
74 self.session.add(self.dbHost)
75
76 print(pyShodanResults)
77 return pyShodanResults
78
79 print("No results found or error in response.")
80 return {}
81 except Exception as exc:
82 print(f"Error: {exc}")
83 return {}
84
85
86if __name__ == "__main__":
87 if len(sys.argv) < 2:
88 print("Usage: pyShodan.py <ip>")
89 sys.exit(1)
90
91 script = PyShodanScript()
92 script.lookup(sys.argv[1])
93PYSHODAN
94
95 python -m py_compile scripts/python/pyShodan.py
96
97
98 python - <<'PSCREEN'
99from pathlib import Path
100
101p = Path("app/Screenshooter.py")
102s = p.read_text()
103
104old = ''' # Use eyewitness under Kali.
105 # Use webdriver if not Kali.
106 # Once eyewitness is more broadly available, the counter case can be eliminated.
107 if isKali():
108 eyewitness_path = "/usr/bin/eyewitness"
109 else:
110 eyewitness_path = "/usr/local/bin/eyewitness"
111'''
112new = ''' # Prefer packaged EyeWitness path on Arch/Linux, fall back to legacy path.
113 if os.path.isfile("/usr/bin/eyewitness"):
114 eyewitness_path = "/usr/bin/eyewitness"
115 else:
116 eyewitness_path = "/usr/local/bin/eyewitness"
117'''
118if old in s:
119 s = s.replace(old, new, 1)
120
121legacy_err = ' raise FileNotFoundError("EyeWitness not found at /usr/bin/eyewitness. Please install it.")'
122new_err = ' raise FileNotFoundError(f"EyeWitness not found at {eyewitness_path}. Please install it.")'
123if legacy_err in s:
124 s = s.replace(legacy_err, new_err, 1)
125
126p.write_text(s)
127PSCREEN
128
129 python - <<'PARCHFINAL'
130from pathlib import Path
131import ast
132import re
133import py_compile
134
135def replace_method(src: str, name: str, new_def: str) -> str:
136 tree = ast.parse(src)
137 lines = src.splitlines(True)
138
139 for node in ast.walk(tree):
140 if isinstance(node, ast.FunctionDef) and node.name == name:
141 start = node.lineno - 1
142 end = node.end_lineno
143 indent = re.match(r"^(\s*)", lines[start]).group(1)
144 lines[start:end] = [new_def.replace("{indent}", indent)]
145 return "".join(lines)
146
147 return src
148
149settings = Path("app/settings.py")
150s = settings.read_text(encoding="utf-8")
151
152s = s.replace("httpx-toolkit-toolkit", "httpx-toolkit")
153s = s.replace("-content-type-toolkit", "-content-type")
154s = s.replace("-kf robotstxt,sitemapxml", "-kf all")
155s = s.replace("raft-medium-directories.txt", "common.txt")
156
157while "-content-type -content-type" in s:
158 s = s.replace("-content-type -content-type", "-content-type")
159
160s = re.sub(
161 r'(?ms)^ HTTPX_COMMAND = \(\n.*?^ \)\n',
162 ''' HTTPX_COMMAND = (
163 "(command -v httpx-toolkit >/dev/null 2>&1 && "
164 "httpx-toolkit -silent -json -title -tech-detect -web-server -status-code -content-type "
165 "-u [WEB_URL] -o [OUTPUT].jsonl)"
166 )
167''',
168 s,
169 count=1,
170)
171
172s = replace_method(
173 s,
174 "_ensure_httpx_command",
175 '''{indent}def _ensure_httpx_command(cls, command: str) -> str:
176{indent} raw = cls._canonicalize_web_target_placeholders(str(command or ""))
177{indent} if "httpx" not in raw.lower() and "httpx-toolkit" not in raw.lower():
178{indent} return raw
179{indent} return cls.HTTPX_COMMAND
180'''
181)
182
183s = replace_method(
184 s,
185 "_ensure_katana_command",
186 '''{indent}def _ensure_katana_command(cls, command: str) -> str:
187{indent} raw = cls._canonicalize_web_target_placeholders(str(command or ""))
188{indent} if "katana" not in raw.lower():
189{indent} return raw
190{indent} return "(command -v katana >/dev/null 2>&1 && katana -silent -jsonl -d 2 -jc -kf all -c 5 -p 1 -rl 5 -u [WEB_URL] -o [OUTPUT].jsonl)"
191'''
192)
193
194s = replace_method(
195 s,
196 "_ensure_dirsearch_command",
197 '''{indent}def _ensure_dirsearch_command(cls, command: str) -> str:
198{indent} raw = cls._canonicalize_web_target_placeholders(str(command or ""))
199{indent} if "dirsearch" not in raw.lower():
200{indent} return raw
201{indent} return "(command -v dirsearch >/dev/null 2>&1 && dirsearch -u [WEB_URL]/ --quiet-mode --format=json --output=[OUTPUT].json)"
202'''
203)
204
205s = replace_method(
206 s,
207 "_ensure_ffuf_command",
208 '''{indent}def _ensure_ffuf_command(cls, command: str) -> str:
209{indent} raw = cls._canonicalize_web_target_placeholders(str(command or ""))
210{indent} if "ffuf" not in raw.lower():
211{indent} return raw
212{indent} return "(command -v ffuf >/dev/null 2>&1 && ffuf -s -of json -o [OUTPUT].json -u [WEB_URL]/FUZZ -w /usr/share/wordlists/dirb/common.txt)"
213'''
214)
215
216s = re.sub(
217 r"feroxbuster -u https://\[IP\]:\[PORT\] -k --silent(?! -w )",
218 "feroxbuster -u https://[IP]:[PORT] -k --silent -w /usr/share/wordlists/dirb/common.txt",
219 s,
220)
221s = re.sub(
222 r"feroxbuster -u http://\[IP\]:\[PORT\] --silent(?! -w )",
223 "feroxbuster -u http://[IP]:[PORT] --silent -w /usr/share/wordlists/dirb/common.txt",
224 s,
225)
226s = re.sub(
227 r"wpscan --disable-tls-checks --no-update --format json --output \[OUTPUT\]\.json --url \[WEB_URL\]",
228 "RUBYOPT=-W0 wpscan --disable-tls-checks --no-update --format json --output [OUTPUT].json --url [WEB_URL]",
229 s,
230)
231
232s = re.sub(r';\s*else\s+echo\s+[^;]+?\s+not found;\s*fi', '; fi', s)
233s = re.sub(r'\s*\|\|\s*echo\s+[^,"\n]+?\s+not found', '', s)
234s = re.sub(r'fallback\s*=\s*["\']\s*\|\|\s*echo\s+[^"\']+?not found["\']', 'fallback = ""', s)
235s = re.sub(r'fallback or ["\']\s*\|\|\s*echo\s+[^"\']+?not found["\']', 'fallback or ""', s)
236
237
238# Remove split upstream default "tool not found" fallback strings.
239s = re.sub(r'\s*\|\|\s*"\n\s*"echo [^"]+ not found"\n', '"\n', s)
240s = re.sub(r'else echo [^"]+ not found; fi', 'fi', s)
241s = re.sub(r'\s*\|\|\s*echo\s+[^,"\n]+?\s+not found(?:\s+-o\s+\S+)?(?=,|"|\n|$)', '', s)
242
243settings.write_text(s, encoding="utf-8")
244py_compile.compile(str(settings), doraise=True)
245
246fixed_lines = {
247 "wpscan": 'wpscan=Run wpscan,"(command -v wpscan >/dev/null 2>&1 && RUBYOPT=-W0 wpscan --disable-tls-checks --no-update --format json --output [OUTPUT].json --url [WEB_URL])","http,https,ssl,soap,http-proxy,http-alt,https-alt"',
248 "web-content-discovery": 'web-content-discovery=Run web content discovery (feroxbuster/gobuster),"((command -v feroxbuster >/dev/null 2>&1 && (feroxbuster -u https://[IP]:[PORT] -k --silent -w /usr/share/wordlists/dirb/common.txt -o [OUTPUT].txt || feroxbuster -u http://[IP]:[PORT] --silent -w /usr/share/wordlists/dirb/common.txt -o [OUTPUT].txt)) || (command -v gobuster >/dev/null 2>&1 && ((gobuster -m dir -k -q -u https://[IP]:[PORT]/ -w /usr/share/wordlists/dirb/common.txt -o [OUTPUT].txt || gobuster -m dir -q -u http://[IP]:[PORT]/ -w /usr/share/wordlists/dirb/common.txt -o [OUTPUT].txt) || (gobuster dir -k -q -u https://[IP]:[PORT]/ -w /usr/share/wordlists/dirb/common.txt -o [OUTPUT].txt || gobuster dir -q -u http://[IP]:[PORT]/ -w /usr/share/wordlists/dirb/common.txt -o [OUTPUT].txt))))","http,https,ssl,soap,http-proxy,http-alt,https-alt"',
249 "httpx": 'httpx=Run httpx,"(command -v httpx-toolkit >/dev/null 2>&1 && httpx-toolkit -silent -json -title -tech-detect -web-server -status-code -content-type -u [WEB_URL] -o [OUTPUT].jsonl)","http,https,ssl,soap,http-proxy,http-alt,https-alt"',
250 "katana": 'katana=Run katana,"(command -v katana >/dev/null 2>&1 && katana -silent -jsonl -d 2 -jc -kf all -c 5 -p 1 -rl 5 -u [WEB_URL] -o [OUTPUT].jsonl)","http,https,ssl,soap,http-proxy,http-alt,https-alt"',
251 "dirsearch": 'dirsearch=Run dirsearch,"(command -v dirsearch >/dev/null 2>&1 && dirsearch -u [WEB_URL]/ --quiet-mode --format=json --output=[OUTPUT].json)","http,https,ssl,soap,http-proxy,http-alt,https-alt"',
252 "ffuf": 'ffuf=Run ffuf,"(command -v ffuf >/dev/null 2>&1 && ffuf -s -of json -o [OUTPUT].json -u [WEB_URL]/FUZZ -w /usr/share/wordlists/dirb/common.txt)","http,https,ssl,soap,http-proxy,http-alt,https-alt"',
253}
254
255conf = Path("legion.conf")
256if conf.exists():
257 text = conf.read_text(encoding="utf-8", errors="ignore")
258 text = text.replace("httpx-toolkit-toolkit", "httpx-toolkit")
259 text = text.replace("-content-type-toolkit", "-content-type")
260 text = text.replace("-kf robotstxt,sitemapxml", "-kf all")
261 text = text.replace("raft-medium-directories.txt", "common.txt")
262
263 while "-content-type -content-type" in text:
264 text = text.replace("-content-type -content-type", "-content-type")
265
266 out = []
267 seen = set()
268
269 for line in text.splitlines():
270 key = line.split("=", 1)[0].strip() if "=" in line else ""
271
272 if key in fixed_lines:
273 if key not in seen:
274 out.append(fixed_lines[key])
275 seen.add(key)
276 continue
277
278 line = re.sub(r';\s*else\s+echo\s+[^;]+?\s+not found;\s*fi', '; fi', line)
279 line = re.sub(r'\s*\|\|\s*echo\s+[^,"\n]+?\s+not found(?:\s+-o\s+\S+)?(?=,|"|\n|$)', '', line)
280 out.append(line)
281
282 existing = {line.split("=", 1)[0].strip() for line in out if "=" in line}
283 for key, value in fixed_lines.items():
284 if key not in existing:
285 out.append(value)
286
287 conf.write_text("\n".join(out).rstrip() + "\n", encoding="utf-8")
288
289print("final Arch Legion action fixes applied")
290PARCHFINAL
291
292 python -m py_compile app/settings.py
293
294
295 python - <<'PARCHFIX'
296from pathlib import Path
297import ast
298import re
299
300# Controller runtime imports and scheduler approval behavior.
301p = Path("controller/controller.py")
302s = p.read_text()
303if "import PyQt6.QtCore as QtCore" not in s:
304 lines = s.splitlines()
305 insert_at = 0
306 while insert_at < len(lines) and (lines[insert_at].startswith("#!") or "coding" in lines[insert_at].lower()):
307 insert_at += 1
308 lines.insert(insert_at, "import PyQt6.QtCore as QtCore")
309 s = "\n".join(lines) + "\n"
310
311m = re.search(r"^from app\.auxiliary import (?P<names>[^\n]+)$", s, flags=re.M)
312if not m:
313 raise SystemExit("app.auxiliary import line not found")
314names = [item.strip() for item in m.group("names").split(",")]
315for extra in ["MyQProcess", "BrowserOpener"]:
316 if extra not in names:
317 names.append(extra)
318s = s[:m.start()] + "from app.auxiliary import " + ", ".join(names) + s[m.end():]
319
320tree = ast.parse(s)
321lines = s.splitlines(True)
322for node in ast.walk(tree):
323 if isinstance(node, ast.FunctionDef) and node.name == "_promptDangerousActionApproval":
324 indent = re.match(r"^(\s*)", lines[node.lineno - 1]).group(1)
325 new_func = "\n".join([
326 indent + 'def _promptDangerousActionApproval(self, decision, service, ip, port, protocol="tcp", command_template=""):',
327 indent + ' if not decision.requires_approval:',
328 indent + ' return SchedulerDecisionDisposition(action="execute")',
329 indent + ' approval_id = self._queueScheduledApproval(decision, service, ip, port, protocol, command_template)',
330 indent + ' update_pending_approval(',
331 indent + ' self.logic.activeProject.database,',
332 indent + ' approval_id,',
333 indent + ' status="approved",',
334 indent + ' decision_reason="auto-approved",',
335 indent + ' )',
336 indent + ' return SchedulerDecisionDisposition(action="execute", approval_id=approval_id, reason="auto-approved")',
337 ]) + "\n"
338 lines[node.lineno - 1:node.end_lineno] = [new_func]
339 s = "".join(lines)
340 break
341else:
342 raise SystemExit("_promptDangerousActionApproval not found")
343p.write_text(s)
344
345# QProcess must use a shell for compound scheduler commands.
346p = Path("app/auxiliary.py")
347s = p.read_text()
348pattern = r"def formatCommandQProcess\(inputCommand\):\n(?: .*\n)+? return program, arguments\n"
349replacement = "\n".join([
350 "def formatCommandQProcess(inputCommand):",
351 " if isinstance(inputCommand, (list, tuple)):",
352 " parts = [str(item) for item in inputCommand]",
353 " if not parts:",
354 " return \"\", []",
355 " return parts[0], parts[1:]",
356 "",
357 " command = str(inputCommand or \"\").strip()",
358 " if not command:",
359 " return \"\", []",
360 "",
361 " shell_tokens = (\"|\", \"&\", \";\", \"<\", \">\", \"(\", \")\", \"`\", \"$\", \"\\\\n\")",
362 " if any(token in command for token in shell_tokens):",
363 " return \"/usr/bin/env\", [\"bash\", \"-lc\", command]",
364 "",
365 " parts = shlex.split(command)",
366 " if not parts:",
367 " return \"\", []",
368 " return parts[0], parts[1:]",
369]) + "\n"
370s, count = re.subn(pattern, replacement, s, count=1)
371if count != 1:
372 raise SystemExit("formatCommandQProcess replacement failed")
373p.write_text(s)
374
375# Prevent repeated nikto -nointeractive accumulation during action migration.
376p = Path("app/settings.py")
377s = p.read_text()
378needle = ' normalized = re.sub(r"(?i)(?:^|\\s)-format\\s+\\S+", " ", normalized)\n'
379insert = needle + ' normalized = re.sub(r"(?i)(?:^|\\s)-nointeractive(?=\\s|$)", " ", normalized)\n'
380if needle in s and insert not in s:
381 s = s.replace(needle, insert, 1)
382p.write_text(s)
383PARCHFIX
384
385 python -m py_compile app/auxiliary.py app/settings.py controller/controller.py
386
387
388
389
390
391
392
393
394}
395
396build() {
397 cd "$srcdir/eyewitness"
398 python -m venv eyewitness-venv
399 eyewitness-venv/bin/pip install -U pip wheel setuptools
400 eyewitness-venv/bin/pip install -r setup/requirements.txt
401}
402
403package() {
404 cd "$srcdir/legion"
405
406 install -d "$pkgdir/usr/share/legion"
407 cp -a app controller db images parsers scripts ui utilities wordlists "$pkgdir/usr/share/legion/"
408 install -m644 CHANGELOG.txt "$pkgdir/usr/share/legion/CHANGELOG.txt"
409 install -m644 LICENSE "$pkgdir/usr/share/legion/LICENSE"
410 install -m644 legion.py "$pkgdir/usr/share/legion/legion.py"
411 if test -f nmap.xsl; then
412 install -m644 nmap.xsl "$pkgdir/usr/share/legion/nmap.xsl"
413 fi
414
415 install -Dm644 legion.conf "$pkgdir/etc/legion.conf"
416 ln -sf /etc/legion.conf "$pkgdir/usr/share/legion/legion.conf"
417
418 install -Dm755 "$srcdir/legion-gui-launcher" "$pkgdir/usr/bin/legion-gui"
419 install -Dm644 "$srcdir/legion-gui.desktop" "$pkgdir/usr/share/applications/legion-gui.desktop"
420 install -Dm644 images/icons/Legion-N_128x128.svg "$pkgdir/usr/share/icons/hicolor/scalable/apps/legion-gui.svg"
421
422 install -d "$pkgdir/usr/share/legion/eyewitness"
423 cp -a "$srcdir/eyewitness/Python" "$pkgdir/usr/share/legion/eyewitness/"
424 cp -a "$srcdir/eyewitness/setup" "$pkgdir/usr/share/legion/eyewitness/"
425 cp -a "$srcdir/eyewitness/eyewitness-venv" "$pkgdir/usr/share/legion/eyewitness/"
426 if test -f "$srcdir/eyewitness/LICENSE"; then
427 install -m644 "$srcdir/eyewitness/LICENSE" "$pkgdir/usr/share/legion/eyewitness/LICENSE"
428 fi
429 if test -f "$pkgdir/usr/share/legion/eyewitness/eyewitness-venv/pyvenv.cfg"; then
430 sed -i "s|$srcdir/eyewitness|/usr/share/legion/eyewitness|g" "$pkgdir/usr/share/legion/eyewitness/eyewitness-venv/pyvenv.cfg" 2>/dev/null || true
431 fi
432 find "$pkgdir/usr/share/legion/eyewitness/eyewitness-venv/bin" -maxdepth 1 -type f ! -name "python" ! -name "python3" ! -name "python3.*" -delete 2>/dev/null || true
433 find "$pkgdir/usr/share/legion/eyewitness/eyewitness-venv/bin" -maxdepth 1 -type l -name "*thon" ! -name "python" ! -name "python3*" -delete 2>/dev/null || true
434
435 install -d "$pkgdir/usr/bin"
436 cat > "$pkgdir/usr/bin/eyewitness" <<'WRAP'
437#!/usr/bin/env bash
438set -euo pipefail
439cd /usr/share/legion/eyewitness
440export PATH="/usr/share/legion/eyewitness/eyewitness-venv/bin:$PATH"
441exec /usr/share/legion/eyewitness/eyewitness-venv/bin/python /usr/share/legion/eyewitness/Python/EyeWitness.py "$@"
442WRAP
443 chmod 755 "$pkgdir/usr/bin/eyewitness"
444
445 chmod 755 "$pkgdir/usr/share/legion/scripts/"* 2>/dev/null || true
446 find "$pkgdir/usr/share/legion" -type d -name "__pycache__" -prune -exec rm -rf {} + 2>/dev/null || true
447 find "$pkgdir/usr/share/legion" -type f -name "*.pyc" -delete 2>/dev/null || true
448}
449

Scan history

Scanned at (UTC)SeverityRules
2026-08-03 00:08:14 LOW 2
2026-08-02 00:16:08 LOW 2
2026-08-01 00:11:18 LOW 2
2026-07-31 00:14:10 LOW 2
2026-07-30 00:17:23 LOW 2
2026-07-29 00:25:53 LOW 2
2026-07-28 00:07:28 LOW 2
2026-07-27 00:24:32 LOW 2
2026-07-26 00:07:32 LOW 2
2026-07-25 00:13:44 LOW 2
2026-07-24 00:02:28 LOW 2
2026-07-23 00:14:47 LOW 2
2026-07-22 00:29:32 LOW 2
2026-07-21 00:24:15 LOW 2
2026-07-20 00:19:49 LOW 2
2026-07-19 00:17:08 LOW 2
2026-07-18 00:14:48 LOW 2
2026-07-17 00:06:16 LOW 2
2026-07-16 00:05:41 LOW 2
2026-07-15 00:09:25 LOW 2

Report a package

Reports go to the AURWatch maintainer (one person) and are read by hand. No login required.

0 / 4000
Your suggestion