Skip to content

Commit 218be9c

Browse files
committed
malcious detection
1 parent 65ebcd4 commit 218be9c

File tree

3 files changed

+121
-1
lines changed

3 files changed

+121
-1
lines changed

frontend/static/js/settings_forms.js

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1156,6 +1156,42 @@ const SettingsForms = {
11561156
</div>
11571157
<p class="setting-help">Time to wait between Swaparr processing cycles (default: 900 seconds / 15 minutes)</p>
11581158
</div>
1159+
1160+
<div class="setting-item">
1161+
<label for="swaparr_malicious_detection">
1162+
<a href="https://plexguide.github.io/Huntarr.io/apps/swaparr.html#malicious-file-detection" class="info-icon" title="Enable malicious file detection" target="_blank" rel="noopener">
1163+
<i class="fas fa-info-circle"></i>
1164+
</a>
1165+
Malicious File Detection:
1166+
</label>
1167+
<label class="toggle-switch" style="width:40px; height:20px; display:inline-block; position:relative;">
1168+
<input type="checkbox" id="swaparr_malicious_detection" ${settings.malicious_file_detection === true ? 'checked' : ''}>
1169+
<span class="toggle-slider" style="position:absolute; cursor:pointer; top:0; left:0; right:0; bottom:0; background-color:#3d4353; border-radius:20px; transition:0.4s;"></span>
1170+
</label>
1171+
<p class="setting-help">Automatically detect and immediately remove downloads with malicious file types</p>
1172+
</div>
1173+
1174+
<div class="setting-item">
1175+
<label for="swaparr_malicious_extensions">
1176+
<a href="https://plexguide.github.io/Huntarr.io/apps/swaparr.html#malicious-extensions" class="info-icon" title="File extensions to consider malicious" target="_blank" rel="noopener">
1177+
<i class="fas fa-info-circle"></i>
1178+
</a>
1179+
Malicious File Extensions:
1180+
</label>
1181+
<textarea id="swaparr_malicious_extensions" rows="3" placeholder="Enter file extensions separated by commas...">${(settings.malicious_extensions || ['.lnk', '.exe', '.bat', '.cmd', '.scr', '.zipx', '.jar', '.vbs']).join(', ')}</textarea>
1182+
<p class="setting-help">File extensions to block (comma-separated). Examples: .lnk, .exe, .bat, .zipx</p>
1183+
</div>
1184+
1185+
<div class="setting-item">
1186+
<label for="swaparr_suspicious_patterns">
1187+
<a href="https://plexguide.github.io/Huntarr.io/apps/swaparr.html#suspicious-patterns" class="info-icon" title="Suspicious filename patterns" target="_blank" rel="noopener">
1188+
<i class="fas fa-info-circle"></i>
1189+
</a>
1190+
Suspicious Patterns:
1191+
</label>
1192+
<textarea id="swaparr_suspicious_patterns" rows="3" placeholder="Enter suspicious patterns separated by commas...">${(settings.suspicious_patterns || ['password.txt', 'readme.txt', 'install.exe', 'keygen', 'crack']).join(', ')}</textarea>
1193+
<p class="setting-help">Filename patterns to block (comma-separated). Examples: password.txt, keygen, crack</p>
1194+
</div>
11591195
</div>
11601196
11611197
@@ -1571,6 +1607,23 @@ const SettingsForms = {
15711607
settings.remove_from_client = getInputValue('#swaparr_remove_from_client', true);
15721608
settings.dry_run = getInputValue('#swaparr_dry_run', false);
15731609
settings.sleep_duration = getInputValue('#swaparr_sleep_duration', 900);
1610+
1611+
// Malicious file detection settings
1612+
settings.malicious_file_detection = getInputValue('#swaparr_malicious_detection', false);
1613+
1614+
// Parse malicious extensions (comma-separated)
1615+
const extensionsText = document.getElementById('swaparr_malicious_extensions')?.value || '';
1616+
settings.malicious_extensions = extensionsText
1617+
.split(',')
1618+
.map(ext => ext.trim())
1619+
.filter(ext => ext.length > 0);
1620+
1621+
// Parse suspicious patterns (comma-separated)
1622+
const patternsText = document.getElementById('swaparr_suspicious_patterns')?.value || '';
1623+
settings.suspicious_patterns = patternsText
1624+
.split(',')
1625+
.map(pattern => pattern.trim())
1626+
.filter(pattern => pattern.length > 0);
15741627
}
15751628
}
15761629

src/primary/apps/swaparr/handler.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
'total_processed': 0,
3535
'strikes_added': 0,
3636
'downloads_removed': 0,
37+
'malicious_removed': 0,
3738
'items_ignored': 0,
3839
'api_calls_made': 0,
3940
'errors_encountered': 0,
@@ -49,6 +50,7 @@ def reset_session_stats():
4950
'total_processed': 0,
5051
'strikes_added': 0,
5152
'downloads_removed': 0,
53+
'malicious_removed': 0,
5254
'items_ignored': 0,
5355
'api_calls_made': 0,
5456
'errors_encountered': 0,
@@ -133,6 +135,39 @@ def generate_item_hash(item):
133135
hash_input = f"{item['name']}_{item['size']}"
134136
return hashlib.md5(hash_input.encode('utf-8')).hexdigest()
135137

138+
def check_for_malicious_files(item, settings):
139+
"""Check if download contains malicious file types"""
140+
if not settings.get('malicious_file_detection', False):
141+
return False, None
142+
143+
# Use user-defined malicious extensions from settings
144+
malicious_extensions = settings.get('malicious_extensions', [
145+
'.lnk', '.exe', '.bat', '.cmd', '.scr', '.pif', '.com',
146+
'.zipx', '.jar', '.vbs', '.js', '.jse', '.wsf', '.wsh'
147+
])
148+
149+
# Use user-defined suspicious patterns from settings
150+
suspicious_patterns = settings.get('suspicious_patterns', [
151+
'password.txt', 'readme.txt', 'install.exe', 'setup.exe',
152+
'keygen', 'crack', 'patch.exe', 'activator'
153+
])
154+
155+
item_name = item.get('name', '').lower()
156+
157+
# Check for malicious extensions in the title/name
158+
for ext in malicious_extensions:
159+
if ext.lower() in item_name:
160+
swaparr_logger.warning(f"Malicious file detected in '{item_name}': contains {ext}")
161+
return True, f"Contains malicious file type: {ext}"
162+
163+
# Check for suspicious patterns
164+
for pattern in suspicious_patterns:
165+
if pattern.lower() in item_name:
166+
swaparr_logger.warning(f"Suspicious content detected in '{item_name}': contains {pattern}")
167+
return True, f"Contains suspicious content: {pattern}"
168+
169+
return False, None
170+
136171
def parse_time_string_to_seconds(time_string):
137172
"""Parse a time string like '2h', '30m', '1d' to seconds"""
138173
if not time_string:
@@ -444,6 +479,35 @@ def process_stalled_downloads(app_name, instance_name, instance_data, settings):
444479
item_state = "Monitoring (Queued)"
445480
continue
446481

482+
# Check for malicious files FIRST - immediate removal without strikes
483+
is_malicious, malicious_reason = check_for_malicious_files(item, settings)
484+
if is_malicious:
485+
swaparr_logger.error(f"MALICIOUS CONTENT DETECTED: {item['name']} - {malicious_reason}")
486+
487+
if not settings.get("dry_run", False):
488+
if delete_download(app_name, instance_data["api_url"], instance_data["api_key"], item["id"], True):
489+
swaparr_logger.info(f"Successfully removed malicious download: {item['name']}")
490+
491+
# Mark as removed to prevent reappearance
492+
removed_items[item_hash] = {
493+
"name": item["name"],
494+
"removed_time": datetime.utcnow().isoformat(),
495+
"reason": f"Malicious: {malicious_reason}",
496+
"size": item["size"]
497+
}
498+
save_removed_items(app_name, removed_items)
499+
500+
item_state = f"REMOVED (Malicious: {malicious_reason})"
501+
502+
# Track malicious removal statistics
503+
SWAPARR_STATS['malicious_removed'] = SWAPARR_STATS.get('malicious_removed', 0) + 1
504+
increment_swaparr_stat("malicious_removals", 1)
505+
else:
506+
swaparr_logger.info(f"DRY RUN: Would remove malicious download: {item['name']} - {malicious_reason}")
507+
item_state = f"Would Remove (Malicious: {malicious_reason})"
508+
509+
continue # Skip to next item - don't process further
510+
447511
# Initialize strike count if not already in strike data
448512
if item_id not in strike_data:
449513
strike_data[item_id] = {

src/primary/default_configs/swaparr.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,8 @@
55
"ignore_above_size": "25GB",
66
"remove_from_client": true,
77
"dry_run": false,
8-
"sleep_duration": 900
8+
"sleep_duration": 900,
9+
"malicious_file_detection": false,
10+
"malicious_extensions": [".lnk", ".exe", ".bat", ".cmd", ".scr", ".pif", ".com", ".zipx", ".jar", ".vbs", ".js", ".jse", ".wsf", ".wsh"],
11+
"suspicious_patterns": ["password.txt", "readme.txt", "install.exe", "setup.exe", "keygen", "crack", "patch.exe", "activator"]
912
}

0 commit comments

Comments
 (0)