mirror of
https://github.com/agessaman/meshcore-bot.git
synced 2026-10-23 06:12:19 +00:00
fix: remove cross-branch security test classes from radio-reliability PR
This commit is contained in:
1 parent
fd0875611d
commit
b56fa83fe3
1 file changed
-160
@@ -2920,166 +2920,6 @@ class TestDbPathResolutionFromConfigDir:
|
||||
)
|
||||
|
||||
|
||||
# ===========================================================================
|
||||
# Security: Restore endpoint path traversal prevention (GAP W1)
|
||||
# ===========================================================================
|
||||
|
||||
|
||||
class TestRestoreEndpointSecurity:
|
||||
"""POST /api/maintenance/restore must reject path traversal attacks.
|
||||
|
||||
Covers GAP W1: validate_safe_path() added before shutil.copy2().
|
||||
Dangerous system directories and traversal patterns must return 400.
|
||||
"""
|
||||
|
||||
def test_etc_passwd_path_rejected(self, client):
|
||||
"""/etc/passwd supplied as db_file must be blocked."""
|
||||
resp = client.post(
|
||||
"/api/maintenance/restore",
|
||||
json={"db_file": "/etc/passwd"},
|
||||
content_type="application/json",
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
data = resp.get_json()
|
||||
assert "error" in data
|
||||
|
||||
def test_etc_shadow_path_rejected(self, client):
|
||||
"""/etc/shadow must be blocked (credential file)."""
|
||||
resp = client.post(
|
||||
"/api/maintenance/restore",
|
||||
json={"db_file": "/etc/shadow"},
|
||||
content_type="application/json",
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
|
||||
def test_proc_self_environ_rejected(self, client):
|
||||
"""/proc/self/environ must be blocked (process secrets)."""
|
||||
resp = client.post(
|
||||
"/api/maintenance/restore",
|
||||
json={"db_file": "/proc/self/environ"},
|
||||
content_type="application/json",
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
|
||||
def test_empty_db_file_rejected(self, client):
|
||||
"""Empty db_file must return 400."""
|
||||
resp = client.post(
|
||||
"/api/maintenance/restore",
|
||||
json={"db_file": ""},
|
||||
content_type="application/json",
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
|
||||
def test_missing_db_file_key_rejected(self, client):
|
||||
"""Missing db_file key must return 400."""
|
||||
resp = client.post(
|
||||
"/api/maintenance/restore",
|
||||
json={},
|
||||
content_type="application/json",
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
|
||||
def test_validate_safe_path_called_for_restore(self, client):
|
||||
"""validate_safe_path is invoked — not bypassed — in the restore handler."""
|
||||
with patch("modules.web_viewer.app.validate_safe_path", return_value=None) as mock_vsp:
|
||||
resp = client.post(
|
||||
"/api/maintenance/restore",
|
||||
json={"db_file": "/tmp/test.db"},
|
||||
content_type="application/json",
|
||||
)
|
||||
mock_vsp.assert_called_once()
|
||||
assert resp.status_code == 400 # None returned → path rejected
|
||||
|
||||
|
||||
# ===========================================================================
|
||||
# Security: Feed preview/test SSRF prevention (GAP W2)
|
||||
# ===========================================================================
|
||||
|
||||
|
||||
class TestFeedPreviewSecurity:
|
||||
"""POST /api/feeds/preview and /api/feeds/test must reject SSRF-able URLs.
|
||||
|
||||
Covers GAP W2: validate_external_url() added before any outbound fetch.
|
||||
Private IPs, loopback, and file:// schemes must return 400.
|
||||
"""
|
||||
|
||||
def test_metadata_endpoint_blocked_in_preview(self, client):
|
||||
"""169.254.169.254 (cloud metadata) must be blocked in feed preview."""
|
||||
resp = client.post(
|
||||
"/api/feeds/preview",
|
||||
json={"feed_url": "http://169.254.169.254/latest/meta-data/", "feed_type": "rss"},
|
||||
content_type="application/json",
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
data = resp.get_json()
|
||||
assert "error" in data
|
||||
|
||||
def test_loopback_blocked_in_preview(self, client):
|
||||
"""127.0.0.1 loopback must be blocked in feed preview."""
|
||||
resp = client.post(
|
||||
"/api/feeds/preview",
|
||||
json={"feed_url": "http://127.0.0.1/internal", "feed_type": "rss"},
|
||||
content_type="application/json",
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
|
||||
def test_file_scheme_blocked_in_preview(self, client):
|
||||
"""file:// scheme must be blocked in feed preview."""
|
||||
resp = client.post(
|
||||
"/api/feeds/preview",
|
||||
json={"feed_url": "file:///etc/passwd", "feed_type": "rss"},
|
||||
content_type="application/json",
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
|
||||
def test_private_network_blocked_in_preview(self, client):
|
||||
"""10.x.x.x (private RFC1918) must be blocked in feed preview."""
|
||||
resp = client.post(
|
||||
"/api/feeds/preview",
|
||||
json={"feed_url": "http://10.0.0.1/feed.xml", "feed_type": "rss"},
|
||||
content_type="application/json",
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
|
||||
def test_missing_feed_url_rejected(self, client):
|
||||
"""Missing feed_url key must return 400."""
|
||||
resp = client.post(
|
||||
"/api/feeds/preview",
|
||||
json={"feed_type": "rss"},
|
||||
content_type="application/json",
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
|
||||
def test_metadata_endpoint_blocked_in_test_route(self, client):
|
||||
"""169.254.169.254 must be blocked in /api/feeds/test as well."""
|
||||
resp = client.post(
|
||||
"/api/feeds/test",
|
||||
json={"url": "http://169.254.169.254/metadata"},
|
||||
content_type="application/json",
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
|
||||
def test_loopback_blocked_in_test_route(self, client):
|
||||
"""127.0.0.1 must be blocked in /api/feeds/test."""
|
||||
resp = client.post(
|
||||
"/api/feeds/test",
|
||||
json={"url": "http://127.0.0.1/internal"},
|
||||
content_type="application/json",
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
|
||||
def test_validate_external_url_called_for_preview(self, client):
|
||||
"""validate_external_url is invoked — not bypassed — in the preview handler."""
|
||||
with patch("modules.web_viewer.app.validate_external_url", return_value=False) as mock_veu:
|
||||
resp = client.post(
|
||||
"/api/feeds/preview",
|
||||
json={"feed_url": "http://192.168.1.1/feed.rss", "feed_type": "rss"},
|
||||
content_type="application/json",
|
||||
)
|
||||
mock_veu.assert_called()
|
||||
assert resp.status_code == 400
|
||||
|
||||
|
||||
class TestRadioDebugConfig:
|
||||
"""Tests for GET/POST /api/config/radio-debug endpoints."""
|
||||
|
||||
|
||||
Reference in new issue
Block a user