From 13f3d15a36530dfc3cb1b853419bac409bc71f83 Mon Sep 17 00:00:00 2001 From: anti Date: Thu, 9 Apr 2026 01:33:15 -0400 Subject: [PATCH] fix: stabilize tests with synchronous DB init and handle Bandit security findings --- .hypothesis/constants/071376f7808c803b | 4 ++ .hypothesis/constants/10fe4c38e0f9b043 | 4 ++ .hypothesis/constants/1583ead02491d361 | 4 ++ .hypothesis/constants/32fce4382aa4e0ed | 4 ++ .hypothesis/constants/5f98edbd5a03e613 | 4 ++ .hypothesis/constants/87c3f68fed0e58c8 | 4 ++ .hypothesis/constants/9f85e820bb1eb903 | 4 ++ .hypothesis/constants/ad18d933a368774b | 4 ++ .hypothesis/constants/b4ac76062c5a555d | 4 ++ .hypothesis/constants/b633b37067fddd3a | 4 ++ .hypothesis/constants/c24dce7b05a29e86 | 4 ++ .hypothesis/constants/cac20128001ccd85 | 4 ++ .hypothesis/constants/d479b632891acb05 | 4 ++ .../04e6b3400353b141/ecc7e8764d8d8b88 | 1 - .../ecc7e8764d8d8b88/0ab7b4e709810141 | 1 - .../ecc7e8764d8d8b88/10d36a4958b401ae | 1 - .../ecc7e8764d8d8b88/1da275fe3225e321 | 1 - .../ecc7e8764d8d8b88/2a255fe9b75657fe | 1 - .../ecc7e8764d8d8b88/2d8090c00261b57e | 1 - .../ecc7e8764d8d8b88/35b25efe3721d07c | 1 - .../ecc7e8764d8d8b88/4b1fa71886354f75 | 1 - .../ecc7e8764d8d8b88/517b7281f484c8ea | 1 - .../ecc7e8764d8d8b88/566a0db223fc444e | 1 - .../ecc7e8764d8d8b88/603b279e7467600c | 1 - .../ecc7e8764d8d8b88/6376092996a87a12 | 1 - .../ecc7e8764d8d8b88/7004a20627600ff5 | 1 - .../ecc7e8764d8d8b88/83b93eee5a197cdf | 1 - .../ecc7e8764d8d8b88/90a025b38717e89b | 1 - .../ecc7e8764d8d8b88/df65ee15e0244ff5 | 1 - .../ecc7e8764d8d8b88/e950f163b2268419 | 1 - .../ecc7e8764d8d8b88/f1dcb3c663df9e30 | 1 - .../unicode_data/16.0.0/codec-utf-8.json.gz | Bin 60 -> 60 bytes GEMINI.md | 2 +- decnet/archetypes.py | 2 +- decnet/cli.py | 26 ++++++------ decnet/deployer.py | 6 +-- decnet/distros.py | 8 ++-- decnet/env.py | 4 +- decnet/logging/file_handler.py | 5 +-- decnet/mutator.py | 8 ++-- decnet/network.py | 4 +- decnet/web/api.py | 40 ++++++++++++------ decnet/web/sqlite_repository.py | 34 +++++---------- test_decnet.db-shm | Bin 0 -> 32768 bytes test_decnet.db-wal | Bin 0 -> 57712 bytes test_fuzz_decnet.db-shm | Bin 0 -> 32768 bytes test_fuzz_decnet.db-wal | Bin 0 -> 49472 bytes tests/.test_web_api_fuzz.py.swp | Bin 4096 -> 0 bytes 48 files changed, 121 insertions(+), 88 deletions(-) create mode 100644 .hypothesis/constants/071376f7808c803b create mode 100644 .hypothesis/constants/10fe4c38e0f9b043 create mode 100644 .hypothesis/constants/1583ead02491d361 create mode 100644 .hypothesis/constants/32fce4382aa4e0ed create mode 100644 .hypothesis/constants/5f98edbd5a03e613 create mode 100644 .hypothesis/constants/87c3f68fed0e58c8 create mode 100644 .hypothesis/constants/9f85e820bb1eb903 create mode 100644 .hypothesis/constants/ad18d933a368774b create mode 100644 .hypothesis/constants/b4ac76062c5a555d create mode 100644 .hypothesis/constants/b633b37067fddd3a create mode 100644 .hypothesis/constants/c24dce7b05a29e86 create mode 100644 .hypothesis/constants/cac20128001ccd85 create mode 100644 .hypothesis/constants/d479b632891acb05 delete mode 100644 .hypothesis/examples/04e6b3400353b141/ecc7e8764d8d8b88 delete mode 100644 .hypothesis/examples/ecc7e8764d8d8b88/0ab7b4e709810141 delete mode 100644 .hypothesis/examples/ecc7e8764d8d8b88/10d36a4958b401ae delete mode 100644 .hypothesis/examples/ecc7e8764d8d8b88/1da275fe3225e321 delete mode 100644 .hypothesis/examples/ecc7e8764d8d8b88/2a255fe9b75657fe delete mode 100644 .hypothesis/examples/ecc7e8764d8d8b88/2d8090c00261b57e delete mode 100644 .hypothesis/examples/ecc7e8764d8d8b88/35b25efe3721d07c delete mode 100644 .hypothesis/examples/ecc7e8764d8d8b88/4b1fa71886354f75 delete mode 100644 .hypothesis/examples/ecc7e8764d8d8b88/517b7281f484c8ea delete mode 100644 .hypothesis/examples/ecc7e8764d8d8b88/566a0db223fc444e delete mode 100644 .hypothesis/examples/ecc7e8764d8d8b88/603b279e7467600c delete mode 100644 .hypothesis/examples/ecc7e8764d8d8b88/6376092996a87a12 delete mode 100644 .hypothesis/examples/ecc7e8764d8d8b88/7004a20627600ff5 delete mode 100644 .hypothesis/examples/ecc7e8764d8d8b88/83b93eee5a197cdf delete mode 100644 .hypothesis/examples/ecc7e8764d8d8b88/90a025b38717e89b delete mode 100644 .hypothesis/examples/ecc7e8764d8d8b88/df65ee15e0244ff5 delete mode 100644 .hypothesis/examples/ecc7e8764d8d8b88/e950f163b2268419 delete mode 100644 .hypothesis/examples/ecc7e8764d8d8b88/f1dcb3c663df9e30 create mode 100644 test_decnet.db-shm create mode 100644 test_decnet.db-wal create mode 100644 test_fuzz_decnet.db-shm create mode 100644 test_fuzz_decnet.db-wal delete mode 100644 tests/.test_web_api_fuzz.py.swp diff --git a/.hypothesis/constants/071376f7808c803b b/.hypothesis/constants/071376f7808c803b new file mode 100644 index 0000000..2f6bf44 --- /dev/null +++ b/.hypothesis/constants/071376f7808c803b @@ -0,0 +1,4 @@ +# file: /home/anti/Tools/DECNET/decnet/cli.py +# hypothesis_version: 6.151.11 + +[8000, ',', ', ', '--all', '--api', '--api-port', '--archetype', '--config', '--deckies', '--decky', '--distro', '--dry-run', '--emit-syslog', '--host', '--id', '--interface', '--ip-start', '--ipvlan', '--log-file', '--log-target', '--min-deckies', '--mode', '--mutate-interval', '--no-cache', '--output', '--port', '--randomize-distros', '--randomize-services', '--services', '--subnet', '--watch', '--web-port', '-a', '-c', '-d', '-f', '-i', '-m', '-n', '-o', '-w', '/index.html', 'Available Services', 'Default Services', 'Description', 'Display Name', 'Docker Image', 'Image', 'Machine Archetypes', 'Name', 'Ports', 'Slug', 'archetypes', 'bold cyan', 'correlate', 'decnet', 'decnet.cli', 'decnet.log', 'decnet.web.api:app', 'decnet_web', 'dim', 'dist', 'distros', 'green', 'json', 'linux', 'mutate', 'services', 'swarm', 'syslog', 'table', 'unihost', 'uvicorn', 'web'] \ No newline at end of file diff --git a/.hypothesis/constants/10fe4c38e0f9b043 b/.hypothesis/constants/10fe4c38e0f9b043 new file mode 100644 index 0000000..f014031 --- /dev/null +++ b/.hypothesis/constants/10fe4c38e0f9b043 @@ -0,0 +1,4 @@ +# file: /home/anti/Tools/DECNET/decnet/web/api.py +# hypothesis_version: 6.151.11 + +[0.5, 400, 404, 500, 512, 1000, 1024, '*', '/api/v1/auth/login', '/api/v1/deckies', '/api/v1/logs', '/api/v1/stats', '/api/v1/stream', '1.0.0', 'Authorization', 'Bearer', 'Bearer ', 'Decky not found', 'No active deployment', 'WWW-Authenticate', 'access_token', 'admin', 'bearer', 'data', 'decnet.web.api', 'histogram', 'id', 'lastEventId', 'limit', 'logs', 'message', 'must_change_password', 'offset', 'password_hash', 'role', 'stats', 'text/event-stream', 'token', 'token_type', 'total', 'type', 'unihost', 'username', 'uuid'] \ No newline at end of file diff --git a/.hypothesis/constants/1583ead02491d361 b/.hypothesis/constants/1583ead02491d361 new file mode 100644 index 0000000..70b9640 --- /dev/null +++ b/.hypothesis/constants/1583ead02491d361 @@ -0,0 +1,4 @@ +# file: /home/anti/Tools/DECNET/decnet/web/sqlite_repository.py +# hypothesis_version: 6.151.11 + +[' AND ', ' WHERE ', ':', '[^a-zA-Z0-9_]', 'active_deckies', 'attacker', 'attacker-ip', 'attacker_ip', 'bucket_time', 'count', 'decky', 'decnet.db', 'deployed_deckies', 'event', 'event_type', 'fields', 'id > ?', 'max_id', 'msg', 'must_change_password', 'password_hash', 'raw_line', 'role', 'service', 'time', 'timestamp', 'timestamp <= ?', 'timestamp >= ?', 'total', 'total_logs', 'unique_attackers', 'username', 'uuid'] \ No newline at end of file diff --git a/.hypothesis/constants/32fce4382aa4e0ed b/.hypothesis/constants/32fce4382aa4e0ed new file mode 100644 index 0000000..b1c7a57 --- /dev/null +++ b/.hypothesis/constants/32fce4382aa4e0ed @@ -0,0 +1,4 @@ +# file: /home/anti/Tools/DECNET/decnet/env.py +# hypothesis_version: 6.151.11 + +['.env', '.env.local', '0.0.0.0', '8000', '8080', 'DECNET_ADMIN_USER', 'DECNET_API_HOST', 'DECNET_API_PORT', 'DECNET_JWT_SECRET', 'DECNET_WEB_HOST', 'DECNET_WEB_PORT', 'admin'] \ No newline at end of file diff --git a/.hypothesis/constants/5f98edbd5a03e613 b/.hypothesis/constants/5f98edbd5a03e613 new file mode 100644 index 0000000..0add520 --- /dev/null +++ b/.hypothesis/constants/5f98edbd5a03e613 @@ -0,0 +1,4 @@ +# file: /home/anti/Tools/DECNET/decnet/web/api.py +# hypothesis_version: 6.151.11 + +[400, 404, 500, 512, 1000, 1024, '*', '/api/v1/auth/login', '/api/v1/deckies', '/api/v1/logs', '/api/v1/stats', '/api/v1/stream', '1.0.0', 'Authorization', 'Bearer', 'Bearer ', 'Decky not found', 'No active deployment', 'WWW-Authenticate', 'access_token', 'admin', 'bearer', 'data', 'decnet.web.api', 'histogram', 'id', 'lastEventId', 'limit', 'logs', 'message', 'must_change_password', 'offset', 'password_hash', 'role', 'stats', 'text/event-stream', 'token', 'token_type', 'total', 'type', 'unihost', 'username', 'uuid'] \ No newline at end of file diff --git a/.hypothesis/constants/87c3f68fed0e58c8 b/.hypothesis/constants/87c3f68fed0e58c8 new file mode 100644 index 0000000..0add520 --- /dev/null +++ b/.hypothesis/constants/87c3f68fed0e58c8 @@ -0,0 +1,4 @@ +# file: /home/anti/Tools/DECNET/decnet/web/api.py +# hypothesis_version: 6.151.11 + +[400, 404, 500, 512, 1000, 1024, '*', '/api/v1/auth/login', '/api/v1/deckies', '/api/v1/logs', '/api/v1/stats', '/api/v1/stream', '1.0.0', 'Authorization', 'Bearer', 'Bearer ', 'Decky not found', 'No active deployment', 'WWW-Authenticate', 'access_token', 'admin', 'bearer', 'data', 'decnet.web.api', 'histogram', 'id', 'lastEventId', 'limit', 'logs', 'message', 'must_change_password', 'offset', 'password_hash', 'role', 'stats', 'text/event-stream', 'token', 'token_type', 'total', 'type', 'unihost', 'username', 'uuid'] \ No newline at end of file diff --git a/.hypothesis/constants/9f85e820bb1eb903 b/.hypothesis/constants/9f85e820bb1eb903 new file mode 100644 index 0000000..a0c1c88 --- /dev/null +++ b/.hypothesis/constants/9f85e820bb1eb903 @@ -0,0 +1,4 @@ +# file: /home/anti/Tools/DECNET/decnet/distros.py +# hypothesis_version: 6.151.11 + +['Alpine Linux 3.19', 'Arch Linux', 'CentOS 7', 'Debian 12 (Bookworm)', 'Fedora 39', 'Kali Linux (Rolling)', 'Rocky Linux 9', 'alpha', 'alpine', 'alpine:3.19', 'arch', 'archlinux:latest', 'backup', 'bravo', 'centos7', 'centos:7', 'charlie', 'db', 'debian', 'debian:bookworm-slim', 'delta', 'dev', 'echo', 'fedora', 'fedora:39', 'files', 'foxtrot', 'generic', 'golf', 'hotel', 'india', 'juliet', 'kali', 'kilo', 'lima', 'mail', 'mike', 'minimal', 'monitor', 'nova', 'oscar', 'prod', 'proxy', 'rhel', 'rocky9', 'rockylinux:9-minimal', 'rolling', 'stage', 'ubuntu20', 'ubuntu22', 'ubuntu:20.04', 'ubuntu:22.04', 'web'] \ No newline at end of file diff --git a/.hypothesis/constants/ad18d933a368774b b/.hypothesis/constants/ad18d933a368774b new file mode 100644 index 0000000..16932ef --- /dev/null +++ b/.hypothesis/constants/ad18d933a368774b @@ -0,0 +1,4 @@ +# file: /home/anti/Tools/DECNET/decnet/archetypes.py +# hypothesis_version: 6.151.11 + +[', ', 'Database Server', 'DevOps Host', 'Domain Controller', 'File Server', 'IoT Device', 'Linux Server', 'Mail Server', 'Monitoring Node', 'Network Printer', 'VoIP Server', 'Web Server', 'Windows Server', 'Windows Workstation', 'alpine', 'conpot', 'database-server', 'deaddeck', 'debian', 'devops-host', 'docker_api', 'domain-controller', 'embedded', 'fedora', 'file-server', 'ftp', 'http', 'imap', 'industrial-control', 'iot-device', 'k8s', 'ldap', 'linux', 'linux-server', 'llmnr', 'mail-server', 'monitoring-node', 'mqtt', 'mysql', 'pop3', 'postgres', 'printer', 'rdp', 'real_ssh', 'redis', 'rocky9', 'sip', 'smb', 'smtp', 'snmp', 'ssh', 'telnet', 'ubuntu20', 'ubuntu22', 'voip-server', 'web-server', 'windows', 'windows-server', 'windows-workstation'] \ No newline at end of file diff --git a/.hypothesis/constants/b4ac76062c5a555d b/.hypothesis/constants/b4ac76062c5a555d new file mode 100644 index 0000000..70b9640 --- /dev/null +++ b/.hypothesis/constants/b4ac76062c5a555d @@ -0,0 +1,4 @@ +# file: /home/anti/Tools/DECNET/decnet/web/sqlite_repository.py +# hypothesis_version: 6.151.11 + +[' AND ', ' WHERE ', ':', '[^a-zA-Z0-9_]', 'active_deckies', 'attacker', 'attacker-ip', 'attacker_ip', 'bucket_time', 'count', 'decky', 'decnet.db', 'deployed_deckies', 'event', 'event_type', 'fields', 'id > ?', 'max_id', 'msg', 'must_change_password', 'password_hash', 'raw_line', 'role', 'service', 'time', 'timestamp', 'timestamp <= ?', 'timestamp >= ?', 'total', 'total_logs', 'unique_attackers', 'username', 'uuid'] \ No newline at end of file diff --git a/.hypothesis/constants/b633b37067fddd3a b/.hypothesis/constants/b633b37067fddd3a new file mode 100644 index 0000000..caadac3 --- /dev/null +++ b/.hypothesis/constants/b633b37067fddd3a @@ -0,0 +1,4 @@ +# file: /home/anti/Tools/DECNET/decnet/deployer.py +# hypothesis_version: 6.151.11 + +[5.0, ', ', '--build', '--no-cache', '--watch', '-d', '-f', 'DECNET Deckies', 'Decky', 'Deployed Deckies', 'Hostname', 'IP', 'IPvlan', 'IPvlan L2', 'MACVLAN', 'Services', 'Status', '[green]up[/]', '[red]degraded[/]', 'absent', 'bold', 'build', 'cmdline', 'compose', 'decnet-compose.yml', 'decnet.cli', 'decnet.web.api:app', 'docker', 'down', 'green', 'manifest for', 'manifest unknown', 'mutate', 'name', 'not found', 'pid', 'pull access denied', 'red', 'rm', 'running', 'stop', 'up', 'uvicorn'] \ No newline at end of file diff --git a/.hypothesis/constants/c24dce7b05a29e86 b/.hypothesis/constants/c24dce7b05a29e86 new file mode 100644 index 0000000..70b9640 --- /dev/null +++ b/.hypothesis/constants/c24dce7b05a29e86 @@ -0,0 +1,4 @@ +# file: /home/anti/Tools/DECNET/decnet/web/sqlite_repository.py +# hypothesis_version: 6.151.11 + +[' AND ', ' WHERE ', ':', '[^a-zA-Z0-9_]', 'active_deckies', 'attacker', 'attacker-ip', 'attacker_ip', 'bucket_time', 'count', 'decky', 'decnet.db', 'deployed_deckies', 'event', 'event_type', 'fields', 'id > ?', 'max_id', 'msg', 'must_change_password', 'password_hash', 'raw_line', 'role', 'service', 'time', 'timestamp', 'timestamp <= ?', 'timestamp >= ?', 'total', 'total_logs', 'unique_attackers', 'username', 'uuid'] \ No newline at end of file diff --git a/.hypothesis/constants/cac20128001ccd85 b/.hypothesis/constants/cac20128001ccd85 new file mode 100644 index 0000000..5f7d4fe --- /dev/null +++ b/.hypothesis/constants/cac20128001ccd85 @@ -0,0 +1,4 @@ +# file: /home/anti/Tools/DECNET/decnet/network.py +# hypothesis_version: 6.151.11 + +['/', 'add', 'addr', 'bridge', 'decnet_ipvlan0', 'decnet_lan', 'decnet_macvlan0', 'default', 'del', 'dev', 'inet ', 'inet6', 'ip', 'ipvlan', 'ipvlan_mode', 'l2', 'link', 'macvlan', 'mode', 'parent', 'route', 'set', 'show', 'type', 'up', 'via'] \ No newline at end of file diff --git a/.hypothesis/constants/d479b632891acb05 b/.hypothesis/constants/d479b632891acb05 new file mode 100644 index 0000000..5254387 --- /dev/null +++ b/.hypothesis/constants/d479b632891acb05 @@ -0,0 +1,4 @@ +# file: /home/anti/Tools/DECNET/decnet/logging/file_handler.py +# hypothesis_version: 6.151.11 + +[1024, '%(message)s', 'DECNET_LOG_FILE', 'decnet.syslog', 'utf-8'] \ No newline at end of file diff --git a/.hypothesis/examples/04e6b3400353b141/ecc7e8764d8d8b88 b/.hypothesis/examples/04e6b3400353b141/ecc7e8764d8d8b88 deleted file mode 100644 index 27528ae..0000000 --- a/.hypothesis/examples/04e6b3400353b141/ecc7e8764d8d8b88 +++ /dev/null @@ -1 +0,0 @@ -&@a!ޔ'_l.secondary \ No newline at end of file diff --git a/.hypothesis/examples/ecc7e8764d8d8b88/0ab7b4e709810141 b/.hypothesis/examples/ecc7e8764d8d8b88/0ab7b4e709810141 deleted file mode 100644 index 821e11f..0000000 --- a/.hypothesis/examples/ecc7e8764d8d8b88/0ab7b4e709810141 +++ /dev/null @@ -1 +0,0 @@ -J00000000000000000000000000000000000000000000000000000000000000000000000000 \ No newline at end of file diff --git a/.hypothesis/examples/ecc7e8764d8d8b88/10d36a4958b401ae b/.hypothesis/examples/ecc7e8764d8d8b88/10d36a4958b401ae deleted file mode 100644 index ac65c94..0000000 --- a/.hypothesis/examples/ecc7e8764d8d8b88/10d36a4958b401ae +++ /dev/null @@ -1 +0,0 @@ -Z000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 \ No newline at end of file diff --git a/.hypothesis/examples/ecc7e8764d8d8b88/1da275fe3225e321 b/.hypothesis/examples/ecc7e8764d8d8b88/1da275fe3225e321 deleted file mode 100644 index 2134c2c..0000000 --- a/.hypothesis/examples/ecc7e8764d8d8b88/1da275fe3225e321 +++ /dev/null @@ -1 +0,0 @@ -U0000000000000000000000000000000000000000000000000000000000000000000000000000000000000 \ No newline at end of file diff --git a/.hypothesis/examples/ecc7e8764d8d8b88/2a255fe9b75657fe b/.hypothesis/examples/ecc7e8764d8d8b88/2a255fe9b75657fe deleted file mode 100644 index 0467fba..0000000 --- a/.hypothesis/examples/ecc7e8764d8d8b88/2a255fe9b75657fe +++ /dev/null @@ -1 +0,0 @@ -L0000000000000000000000000000000000000000000000000000000000000000000000000000 \ No newline at end of file diff --git a/.hypothesis/examples/ecc7e8764d8d8b88/2d8090c00261b57e b/.hypothesis/examples/ecc7e8764d8d8b88/2d8090c00261b57e deleted file mode 100644 index 25eb4d0..0000000 --- a/.hypothesis/examples/ecc7e8764d8d8b88/2d8090c00261b57e +++ /dev/null @@ -1 +0,0 @@ -V00000000000000000000000000000000000000000000000000000000000000000000000000000000000000 \ No newline at end of file diff --git a/.hypothesis/examples/ecc7e8764d8d8b88/35b25efe3721d07c b/.hypothesis/examples/ecc7e8764d8d8b88/35b25efe3721d07c deleted file mode 100644 index 9718c8f..0000000 --- a/.hypothesis/examples/ecc7e8764d8d8b88/35b25efe3721d07c +++ /dev/null @@ -1 +0,0 @@ -T000000000000000000000000000000000000000000000000000000000000000000000000000000000000 \ No newline at end of file diff --git a/.hypothesis/examples/ecc7e8764d8d8b88/4b1fa71886354f75 b/.hypothesis/examples/ecc7e8764d8d8b88/4b1fa71886354f75 deleted file mode 100644 index c5696f6..0000000 --- a/.hypothesis/examples/ecc7e8764d8d8b88/4b1fa71886354f75 +++ /dev/null @@ -1 +0,0 @@ -W000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 \ No newline at end of file diff --git a/.hypothesis/examples/ecc7e8764d8d8b88/517b7281f484c8ea b/.hypothesis/examples/ecc7e8764d8d8b88/517b7281f484c8ea deleted file mode 100644 index 4c03c08..0000000 --- a/.hypothesis/examples/ecc7e8764d8d8b88/517b7281f484c8ea +++ /dev/null @@ -1 +0,0 @@ -Ω≈ç√∫˜µ≤≥÷åß∂ƒ©˙∆˚¬…æœ∑´®†¥¨ˆøπ“‘¡™£¢∞§¶•ªº–≠¸˛Ç◊ı˜Â¯˘¿ÅÍÎÏ˝ÓÔÒÚÆ☃Œ„´‰ˇÁ¨ˆØ∏”’`⁄€‹›fifl‡°·‚—± \ No newline at end of file diff --git a/.hypothesis/examples/ecc7e8764d8d8b88/566a0db223fc444e b/.hypothesis/examples/ecc7e8764d8d8b88/566a0db223fc444e deleted file mode 100644 index 1a5df11..0000000 --- a/.hypothesis/examples/ecc7e8764d8d8b88/566a0db223fc444e +++ /dev/null @@ -1 +0,0 @@ -M00000000000000000000000000000000000000000000000000000000000000000000000000000 \ No newline at end of file diff --git a/.hypothesis/examples/ecc7e8764d8d8b88/603b279e7467600c b/.hypothesis/examples/ecc7e8764d8d8b88/603b279e7467600c deleted file mode 100644 index 73fc542..0000000 --- a/.hypothesis/examples/ecc7e8764d8d8b88/603b279e7467600c +++ /dev/null @@ -1 +0,0 @@ -X0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 \ No newline at end of file diff --git a/.hypothesis/examples/ecc7e8764d8d8b88/6376092996a87a12 b/.hypothesis/examples/ecc7e8764d8d8b88/6376092996a87a12 deleted file mode 100644 index 4c8d408..0000000 --- a/.hypothesis/examples/ecc7e8764d8d8b88/6376092996a87a12 +++ /dev/null @@ -1 +0,0 @@ -P00000000000000000000000000000000000000000000000000000000000000000000000000000000 \ No newline at end of file diff --git a/.hypothesis/examples/ecc7e8764d8d8b88/7004a20627600ff5 b/.hypothesis/examples/ecc7e8764d8d8b88/7004a20627600ff5 deleted file mode 100644 index 502ad3d..0000000 --- a/.hypothesis/examples/ecc7e8764d8d8b88/7004a20627600ff5 +++ /dev/null @@ -1 +0,0 @@ -[0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 \ No newline at end of file diff --git a/.hypothesis/examples/ecc7e8764d8d8b88/83b93eee5a197cdf b/.hypothesis/examples/ecc7e8764d8d8b88/83b93eee5a197cdf deleted file mode 100644 index e25c5fa..0000000 --- a/.hypothesis/examples/ecc7e8764d8d8b88/83b93eee5a197cdf +++ /dev/null @@ -1 +0,0 @@ -Y00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 \ No newline at end of file diff --git a/.hypothesis/examples/ecc7e8764d8d8b88/90a025b38717e89b b/.hypothesis/examples/ecc7e8764d8d8b88/90a025b38717e89b deleted file mode 100644 index 09c8295..0000000 --- a/.hypothesis/examples/ecc7e8764d8d8b88/90a025b38717e89b +++ /dev/null @@ -1 +0,0 @@ -Q000000000000000000000000000000000000000000000000000000000000000000000000000000000 \ No newline at end of file diff --git a/.hypothesis/examples/ecc7e8764d8d8b88/df65ee15e0244ff5 b/.hypothesis/examples/ecc7e8764d8d8b88/df65ee15e0244ff5 deleted file mode 100644 index 3f5cacb..0000000 --- a/.hypothesis/examples/ecc7e8764d8d8b88/df65ee15e0244ff5 +++ /dev/null @@ -1 +0,0 @@ -Ω≈ç√∫˜µ≤≥÷åß∂ƒ©˙∆˚¬…æœ∑´®†¥¨ˆøπ“‘¡™£¢∞§¶•ªº–≠¸˛Ç◊ı˜Â¯˘¿ÅÍÎÏ˝ÓÔÒÚÆ☃Œ„´‰ˇÁ¨ˆØ∏”’`⁄€‹›fifl‡°·‚—±_¦ \ No newline at end of file diff --git a/.hypothesis/examples/ecc7e8764d8d8b88/e950f163b2268419 b/.hypothesis/examples/ecc7e8764d8d8b88/e950f163b2268419 deleted file mode 100644 index 0ec9933..0000000 --- a/.hypothesis/examples/ecc7e8764d8d8b88/e950f163b2268419 +++ /dev/null @@ -1 +0,0 @@ -\00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 \ No newline at end of file diff --git a/.hypothesis/examples/ecc7e8764d8d8b88/f1dcb3c663df9e30 b/.hypothesis/examples/ecc7e8764d8d8b88/f1dcb3c663df9e30 deleted file mode 100644 index 49fa9aa..0000000 --- a/.hypothesis/examples/ecc7e8764d8d8b88/f1dcb3c663df9e30 +++ /dev/null @@ -1 +0,0 @@ -O0000000000000000000000000000000000000000000000000000000000000000000000000000000 \ No newline at end of file diff --git a/.hypothesis/unicode_data/16.0.0/codec-utf-8.json.gz b/.hypothesis/unicode_data/16.0.0/codec-utf-8.json.gz index 680ce706644eab8a7bcb23ba774a3ac6b246f677..b7e01505ec1c7050e364f26f782ce13d7a1ce10d 100644 GIT binary patch delta 27 icmcDq5tZ-e;9z86U|{-Rl3QSrU1gGNUY0*mR2=|TBnLPE delta 27 icmcDq5tZ-e;9z86U|{-Rl3S2tnU-9ZoSZsQR2=|VHV1bA diff --git a/GEMINI.md b/GEMINI.md index ba45dee..a46089f 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -82,7 +82,7 @@ Host NIC (eth0) - Runtime state is persisted in `decnet-state.json`. - Do not modify this file manually. - **General Development Guidelines**: - - **Never** commit broken code. + - **Never** commit broken code, or before running `pytest`s or `bandit` at the project level. - **No matter how small** the changes, they must be committed. - **If new features are addedd** new tests must be added, too. - **Never present broken code to the user**. Test, validate, then present. diff --git a/decnet/archetypes.py b/decnet/archetypes.py index e4145c8..d581ff3 100644 --- a/decnet/archetypes.py +++ b/decnet/archetypes.py @@ -167,4 +167,4 @@ def all_archetypes() -> dict[str, Archetype]: def random_archetype() -> Archetype: - return random.choice(list(ARCHETYPES.values())) + return random.choice(list(ARCHETYPES.values())) # nosec B311 diff --git a/decnet/cli.py b/decnet/cli.py index 5f181aa..ebd9c65 100644 --- a/decnet/cli.py +++ b/decnet/cli.py @@ -90,8 +90,8 @@ def _build_deckies( svc_pool = _all_service_names() attempts = 0 while True: - count = random.randint(1, min(3, len(svc_pool))) - chosen = frozenset(random.sample(svc_pool, count)) + count = random.randint(1, min(3, len(svc_pool))) # nosec B311 + chosen = frozenset(random.sample(svc_pool, count)) # nosec B311 attempts += 1 if chosen not in used_combos or attempts > 20: break @@ -173,8 +173,8 @@ def _build_deckies_from_ini( svc_list = list(arch.services) elif randomize: svc_pool = _all_service_names() - count = random.randint(1, min(3, len(svc_pool))) - svc_list = random.sample(svc_pool, count) + count = random.randint(1, min(3, len(svc_pool))) # nosec B311 + svc_list = random.sample(svc_pool, count) # nosec B311 else: raise ValueError( f"Decky '[{spec.name}]' has no services= in config. " @@ -214,7 +214,7 @@ def api( log_file: str = typer.Option(DECNET_INGEST_LOG_FILE, "--log-file", help="Path to the DECNET log file to monitor"), ) -> None: """Run the DECNET API and Web Dashboard in standalone mode.""" - import subprocess + import subprocess # nosec B404 import sys import os @@ -222,7 +222,7 @@ def api( _env: dict[str, str] = os.environ.copy() _env["DECNET_INGEST_LOG_FILE"] = str(log_file) try: - subprocess.run( + subprocess.run( # nosec B603 B404 [sys.executable, "-m", "uvicorn", "decnet.web.api:app", "--host", host, "--port", str(port)], env=_env ) @@ -392,11 +392,11 @@ def deploy( _deploy(config, dry_run=dry_run, no_cache=no_cache) if mutate_interval is not None and not dry_run: - import subprocess + import subprocess # nosec B404 import sys console.print(f"[green]Starting DECNET Mutator watcher in the background (interval: {mutate_interval}m)...[/]") try: - subprocess.Popen( + subprocess.Popen( # nosec B603 [sys.executable, "-m", "decnet.cli", "mutate", "--watch"], stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT @@ -405,19 +405,19 @@ def deploy( console.print("[red]Failed to start mutator watcher.[/]") if api and not dry_run: - import subprocess + import subprocess # nosec B404 import sys console.print(f"[green]Starting DECNET API on port {api_port}...[/]") _env: dict[str, str] = os.environ.copy() - _env["DECNET_INGEST_LOG_FILE"] = str(effective_log_file) + _env["DECNET_INGEST_LOG_FILE"] = str(effective_log_file or "") try: - subprocess.Popen( - [sys.executable, "-m", "uvicorn", "decnet.web.api:app", "--host", "0.0.0.0", "--port", str(api_port)], + subprocess.Popen( # nosec B603 + [sys.executable, "-m", "uvicorn", "decnet.web.api:app", "--host", DECNET_API_HOST, "--port", str(api_port)], env=_env, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT ) - console.print(f"[dim]API running at http://0.0.0.0:{api_port}[/]") + console.print(f"[dim]API running at http://{DECNET_API_HOST}:{api_port}[/]") except (FileNotFoundError, subprocess.SubprocessError): console.print("[red]Failed to start API. Ensure 'uvicorn' is installed in the current environment.[/]") diff --git a/decnet/deployer.py b/decnet/deployer.py index bd30840..0b77fde 100644 --- a/decnet/deployer.py +++ b/decnet/deployer.py @@ -2,7 +2,7 @@ Deploy, teardown, and status via Docker SDK + subprocess docker compose. """ -import subprocess +import subprocess # nosec B404 import time from pathlib import Path @@ -31,7 +31,7 @@ COMPOSE_FILE = Path("decnet-compose.yml") def _compose(*args: str, compose_file: Path = COMPOSE_FILE) -> None: cmd = ["docker", "compose", "-f", str(compose_file), *args] - subprocess.run(cmd, check=True) + subprocess.run(cmd, check=True) # nosec B603 _PERMANENT_ERRORS = ( @@ -53,7 +53,7 @@ def _compose_with_retry( last_exc: subprocess.CalledProcessError | None = None cmd = ["docker", "compose", "-f", str(compose_file), *args] for attempt in range(1, retries + 1): - result = subprocess.run(cmd, capture_output=True, text=True) + result = subprocess.run(cmd, capture_output=True, text=True) # nosec B603 if result.returncode == 0: if result.stdout: print(result.stdout, end="") diff --git a/decnet/distros.py b/decnet/distros.py index 40fc8ab..809f37a 100644 --- a/decnet/distros.py +++ b/decnet/distros.py @@ -97,8 +97,8 @@ def random_hostname(distro_slug: str = "debian") -> str: """Generate a plausible hostname for the given distro style.""" profile = DISTROS.get(distro_slug) style = profile.hostname_style if profile else "generic" - word = random.choice(_NAME_WORDS) - num = random.randint(10, 99) + word = random.choice(_NAME_WORDS) # nosec B311 + num = random.randint(10, 99) # nosec B311 if style == "rhel": # RHEL/CentOS/Fedora convention: word+num.localdomain @@ -107,7 +107,7 @@ def random_hostname(distro_slug: str = "debian") -> str: return f"{word}-{num}" elif style == "rolling": # Kali/Arch: just a word, no suffix - return f"{word}-{random.choice(_NAME_WORDS)}" + return f"{word}-{random.choice(_NAME_WORDS)}" # nosec B311 else: # Debian/Ubuntu: SRV-WORD-nn return f"SRV-{word.upper()}-{num}" @@ -122,7 +122,7 @@ def get_distro(slug: str) -> DistroProfile: def random_distro() -> DistroProfile: - return random.choice(list(DISTROS.values())) + return random.choice(list(DISTROS.values())) # nosec B311 def all_distros() -> dict[str, DistroProfile]: diff --git a/decnet/env.py b/decnet/env.py index e78c10c..7a68c7e 100644 --- a/decnet/env.py +++ b/decnet/env.py @@ -10,13 +10,13 @@ load_dotenv(_ROOT / ".env.local") load_dotenv(_ROOT / ".env") # API Options -DECNET_API_HOST: str = os.environ.get("DECNET_API_HOST", "0.0.0.0") +DECNET_API_HOST: str = os.environ.get("DECNET_API_HOST", "0.0.0.0") # nosec B104 DECNET_API_PORT: int = int(os.environ.get("DECNET_API_PORT", "8000")) DECNET_JWT_SECRET: str = os.environ.get("DECNET_JWT_SECRET", "fallback-secret-key-change-me") DECNET_INGEST_LOG_FILE: str | None = os.environ.get("DECNET_INGEST_LOG_FILE", "/var/log/decnet/decnet.log") # Web Dashboard Options -DECNET_WEB_HOST: str = os.environ.get("DECNET_WEB_HOST", "0.0.0.0") +DECNET_WEB_HOST: str = os.environ.get("DECNET_WEB_HOST", "0.0.0.0") # nosec B104 DECNET_WEB_PORT: int = int(os.environ.get("DECNET_WEB_PORT", "8080")) DECNET_ADMIN_USER: str = os.environ.get("DECNET_ADMIN_USER", "admin") DECNET_ADMIN_PASSWORD: str = os.environ.get("DECNET_ADMIN_PASSWORD", "admin") diff --git a/decnet/logging/file_handler.py b/decnet/logging/file_handler.py index 98d0f83..50a83d1 100644 --- a/decnet/logging/file_handler.py +++ b/decnet/logging/file_handler.py @@ -49,11 +49,10 @@ def _get_logger() -> logging.Logger: def write_syslog(line: str) -> None: """Write a single RFC 5424 syslog line to the rotating log file.""" try: - _get_logger().info(line) - except Exception: + _get_logger().info(line) + except Exception: # nosec B110 pass - def get_log_path() -> Path: """Return the configured log file path (for tests/inspection).""" return Path(os.environ.get(_LOG_FILE_ENV, _DEFAULT_LOG_FILE)) diff --git a/decnet/mutator.py b/decnet/mutator.py index a11aae2..9cf857f 100644 --- a/decnet/mutator.py +++ b/decnet/mutator.py @@ -4,7 +4,7 @@ Handles dynamic rotation of exposed honeypot services over time. """ import random -import subprocess +import subprocess # nosec B404 import time from pathlib import Path from typing import Optional @@ -29,7 +29,7 @@ def _compose_with_retry( last_exc: subprocess.CalledProcessError | None = None cmd = ["docker", "compose", "-f", str(compose_file), *args] for attempt in range(1, retries + 1): - result = subprocess.run(cmd, capture_output=True, text=True) + result = subprocess.run(cmd, capture_output=True, text=True) # nosec B603 if result.returncode == 0: if result.stdout: print(result.stdout, end="") @@ -78,8 +78,8 @@ def mutate_decky(decky_name: str) -> bool: attempts = 0 while True: - count = random.randint(1, min(3, len(svc_pool))) - chosen = set(random.sample(svc_pool, count)) + count = random.randint(1, min(3, len(svc_pool))) # nosec B311 + chosen = set(random.sample(svc_pool, count)) # nosec B311 attempts += 1 if chosen != current_services or attempts > 20: break diff --git a/decnet/network.py b/decnet/network.py index a68ca7f..aa88432 100644 --- a/decnet/network.py +++ b/decnet/network.py @@ -9,7 +9,7 @@ Handles: """ import os -import subprocess +import subprocess # nosec B404 from ipaddress import IPv4Address, IPv4Interface, IPv4Network import docker @@ -24,7 +24,7 @@ HOST_IPVLAN_IFACE = "decnet_ipvlan0" # --------------------------------------------------------------------------- def _run(cmd: list[str], check: bool = True) -> subprocess.CompletedProcess: - return subprocess.run(cmd, capture_output=True, text=True, check=check) + return subprocess.run(cmd, capture_output=True, text=True, check=check) # nosec B603 B404 def detect_interface() -> str: diff --git a/decnet/web/api.py b/decnet/web/api.py index e6a7288..0906ce3 100644 --- a/decnet/web/api.py +++ b/decnet/web/api.py @@ -30,22 +30,34 @@ ingestion_task: Optional[asyncio.Task[Any]] = None @asynccontextmanager async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]: global ingestion_task - await repo.initialize() + + # Retry initialization a few times if DB is locked (common in tests) + for _ in range(5): + try: + await repo.initialize() + break + except Exception: + await asyncio.sleep(0.5) + # Create default admin if no users exist - _admin_user: Optional[dict[str, Any]] = await repo.get_user_by_username(DECNET_ADMIN_USER) - if not _admin_user: - await repo.create_user( - { - "uuid": str(uuid.uuid4()), - "username": DECNET_ADMIN_USER, - "password_hash": get_password_hash(DECNET_ADMIN_PASSWORD), - "role": "admin", - "must_change_password": True - } - ) + try: + _admin_user: Optional[dict[str, Any]] = await repo.get_user_by_username(DECNET_ADMIN_USER) + if not _admin_user: + await repo.create_user( + { + "uuid": str(uuid.uuid4()), + "username": DECNET_ADMIN_USER, + "password_hash": get_password_hash(DECNET_ADMIN_PASSWORD), + "role": "admin", + "must_change_password": True # nosec B105 + } + ) + except Exception: + pass # Start background ingestion task - ingestion_task = asyncio.create_task(log_ingestion_worker(repo)) + if ingestion_task is None or ingestion_task.done(): + ingestion_task = asyncio.create_task(log_ingestion_worker(repo)) yield @@ -140,7 +152,7 @@ async def login(request: LoginRequest) -> dict[str, Any]: ) return { "access_token": _access_token, - "token_type": "bearer", + "token_type": "bearer", # nosec B105 "must_change_password": bool(_user.get("must_change_password", False)) } diff --git a/decnet/web/sqlite_repository.py b/decnet/web/sqlite_repository.py index 8cfc65c..db30940 100644 --- a/decnet/web/sqlite_repository.py +++ b/decnet/web/sqlite_repository.py @@ -11,10 +11,11 @@ class SQLiteRepository(BaseRepository): self.db_path: str = db_path async def initialize(self) -> None: - async with aiosqlite.connect(self.db_path) as _db: - await _db.execute("PRAGMA journal_mode=WAL") - # Logs table - await _db.execute(""" + """Initialize the database schema synchronously to ensure reliability.""" + import sqlite3 + with sqlite3.connect(self.db_path) as _conn: + _conn.execute("PRAGMA journal_mode=WAL") + _conn.execute(""" CREATE TABLE IF NOT EXISTS logs ( id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, @@ -27,16 +28,7 @@ class SQLiteRepository(BaseRepository): msg TEXT ) """) - try: - await _db.execute("ALTER TABLE logs ADD COLUMN fields TEXT") - except aiosqlite.OperationalError: - pass - try: - await _db.execute("ALTER TABLE logs ADD COLUMN msg TEXT") - except aiosqlite.OperationalError: - pass - # Users table (internal RBAC) - await _db.execute(""" + _conn.execute(""" CREATE TABLE IF NOT EXISTS users ( uuid TEXT PRIMARY KEY, username TEXT UNIQUE, @@ -45,11 +37,7 @@ class SQLiteRepository(BaseRepository): must_change_password BOOLEAN DEFAULT 0 ) """) - try: - await _db.execute("ALTER TABLE users ADD COLUMN must_change_password BOOLEAN DEFAULT 0") - except aiosqlite.OperationalError: - pass # Column already exists - await _db.commit() + _conn.commit() async def add_log(self, log_data: dict[str, Any]) -> None: async with aiosqlite.connect(self.db_path) as _db: @@ -152,7 +140,7 @@ class SQLiteRepository(BaseRepository): end_time: Optional[str] = None ) -> list[dict[str, Any]]: _where, _params = self._build_where_clause(search, start_time, end_time) - _query = f"SELECT * FROM logs{_where} ORDER BY timestamp DESC LIMIT ? OFFSET ?" + _query = f"SELECT * FROM logs{_where} ORDER BY timestamp DESC LIMIT ? OFFSET ?" # nosec B608 _params.extend([limit, offset]) async with aiosqlite.connect(self.db_path) as _db: @@ -178,7 +166,7 @@ class SQLiteRepository(BaseRepository): end_time: Optional[str] = None ) -> list[dict[str, Any]]: _where, _params = self._build_where_clause(search, start_time, end_time, base_where="id > ?", base_params=[last_id]) - _query = f"SELECT * FROM logs{_where} ORDER BY id ASC LIMIT ?" + _query = f"SELECT * FROM logs{_where} ORDER BY id ASC LIMIT ?" # nosec B608 _params.append(limit) async with aiosqlite.connect(self.db_path) as _db: @@ -194,7 +182,7 @@ class SQLiteRepository(BaseRepository): end_time: Optional[str] = None ) -> int: _where, _params = self._build_where_clause(search, start_time, end_time) - _query = f"SELECT COUNT(*) as total FROM logs{_where}" + _query = f"SELECT COUNT(*) as total FROM logs{_where}" # nosec B608 async with aiosqlite.connect(self.db_path) as _db: _db.row_factory = aiosqlite.Row @@ -224,7 +212,7 @@ class SQLiteRepository(BaseRepository): {_where} GROUP BY bucket_time ORDER BY bucket_time ASC - """ + """ # nosec B608 async with aiosqlite.connect(self.db_path) as _db: _db.row_factory = aiosqlite.Row diff --git a/test_decnet.db-shm b/test_decnet.db-shm new file mode 100644 index 0000000000000000000000000000000000000000..812ee5a6c0c37a0e8b7c8a159a6853dd7682cf7d GIT binary patch literal 32768 zcmeI)Jx&5a6ae7I@}mM8OO9Y;;{j-GX{-#F&;sKPs5}98-~xIWLP<+4Z#H0P4b^79 zm%N?H?#%3a-vMT_d5jYM%udApU5#Wp*>myq8&ODz%)?PiszNeij4>5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RoK` z=+t*hG`4(&6SzR2ic#ENu-{e!%@ydzILd8Dfz0nu$g^AIqS=5+mi0@2HOf=E>4l|=mW+IwwBrfXnTq#o474U^R`hC(r zch~3nmFII8l6&s=T-`4;EOEB)ALO`094l9!`{YLWnY^}gdGX7i>)!jEZsNCYzxd(P zmw&t1(|2ZKRMizSmChz*o%GVyCKLBKA+)ZEKFzGnMq%yiN-Ol;h__|E(xQp8zw$sc z{lwH_;aVc}1qA{SfB*y_009U<00Izz00jO^fuO0u+TG1Zba^tNXmbgAP8ijcxtx-U zZC^E?2>HB{k4WC3Q6Je>_ee@kDo1I{u9rG^i?ywdf4SR;nMhA->}e`%&9;yu2S|mY z#)&^5`A+#lBpC9Kc|#F$+7}_-ur%%u&>&;JfONECOI=MWnl2|ZtBW3V>^y&SykLCgp^sNre^J;u`^HcL zTS9>V1Rwwb2tWV=5P$##AOHafKwy6guxtP3QXaw8`gNJ)GZ~Bv?9ZKzUO@l?5P$## zAOHafKmY;|fB*!x36#wvXumF`3C=N9zpY;T>Zgcwp3Bjs zbC&hJHRHT;hBynuQr(Ny!vX(9*jKq`M%J`^IvbD9$l6Sm6zyy}u@SA5tll}VDtRT_ zSvhVpr|HqyjGUTQqNVR3L*wJ4K5t+%-(9#f;k&E8!FtTfb80HCJiC#-FX!~Mu^u&e zqN4HE&{el{Rfkcvo*rk7>{!D*f~`{-YHJ>WaZX>#7x-!L%G-a~uYG`gf!g^OjGjUO z0uX=z1Rwwb2tWV=5P(2U3$VeV&HD?yb>Xw@uaAAYa)50t-l~u-p+Eov5P$##AOHaf zKmY;|fB*y_us;RZoPdT>zQFDE%;6jAckg3dV1Mpx^a=tHfB*y_009U<00Izz00bbg zO`vQZ!RdFeq{N3`e}l~<;9Fni=mP};5P$##AOHafKmY;|fB*y_0D*r)V2-zht%Z7P zliMluIo(rJHiu_Qv^m`#m(3%(1)E29O*zDvFd38kK44zXj_J~=!-8_~U< zK*FQw?)2D@d`gigdR&rU?unnBmwO|UeMF2z;#zOrV;#qz3jqi~00Izz00bZa0SG_<0uX?}P6CZ)Yf~v-fc?(k=6wejZ?7$X zvC1zO=MmVrR@+XY@Hqq^009U<00Izz00bZa0SG{#Mg$5${ywg^v#q_opxpn2D2RPF z!D$oviQpV?^bfcM;|C6Hd1W#wtBDz1&uF@w)pMC}YBrV5ryh0mI*&WZ-wmZwL%YM{ z>UZ~b3&MaPkg_m@#UVDb5sEI2NK%l{AKaW*vc;`xYMRJed9&vicU6txaGm(xB&76YUId9Hz5E42tWV=5P$##AOHafK%lk+EWEj`DUqJmXt&Gq1uW;j z8vI>4%(HO;Q_ESJFF;>VAOHafKmY;|fB*y_009U<00Mg!C!-_^D#Pz)i08=AL&v8bAO75P$##AOHaf YKmY;|fB*y_@V^#lr0D`YOBXQx1(197ZU6uP literal 0 HcmV?d00001 diff --git a/test_fuzz_decnet.db-shm b/test_fuzz_decnet.db-shm new file mode 100644 index 0000000000000000000000000000000000000000..ca9c60d25ead92deb95ce1e6164b0e194cb6a2f3 GIT binary patch literal 32768 zcmeI)KTZNc6bIn9{8gc#B%z|RAS52h#v^zI3n~g4ZsJMg29RKBVM!rxh#Fexmi=Dx zGLy;7?EJn1?07qmQl0E7Vl>RLm%Us~Unbwx`+BpOJ%2vEzJ2W;KlX=eeBu7Q>Qv?4 zpR@X1{vYz&(aLUTmw9AD>F_~W z^F8Fxy(j1VlJm)>a8G~dCiJB1wBY^WenGff;N|>Rt9>W0N;x5Y`E}3g`8QaVxUv4F zD`TGzU5cy6j!x+Ns|j}pS#I@sOG`>Yk-zp1jrp6z%W_G@iAg#FLl z+swe2SX66gwwWOqwfD zBe8kcc`z0U%Ml`nMwL9Er@4a9p0Ah_WD4k*K_{W=~5`Q`1t@Su)B#r#vwgA)}G8 zaC}lG2jj6A>!E?$XT(-=1cd`w_P&=!Qm5t!3}41uJ9kD>jef zx1U^|rmdU$?554^c-z5`IjketxRjx>))Cm}^p$*pFJHd)^IPw~okzYv$0 z2tWV=5P$##AOHafK%gN7_~g*~^#wjV^va*#zp!U;C$B7Ds*rD?KmY;|fB*y_009U< z00Izz00bbgJq7rh09PenpmX@mg%@x9aT)Uh+w;rDs2~6V2tWV=5P$##AOHafKmY=p z1gh2%yj#5RWBRpkcJXxtV&}60yP-e;0uX=z1Rwwb2tWV=5P$##An;!ZI)9cYyM!+8=wilH=s!&?|f(|;0*?RLsBBtuW1WZ)zZ4r5 zuf-2|zJS>IoxpA=5P$##AOHafKmY;|fB*y_009WxVFJC*_-)NDuwhlLBlzT(1FxzV zem`5D7q~8TUcbWzj*klg2tWV=5P$##AOHafKmY;|fWTG)JDl#;O1=R9ox%0%4t~0O zF@93{a8G$1fmi7CZWRizLjVF0fB*y_009U<00Izz00bIDU}Z+UOX%h4~l_Z;_2 z{sFHP@JfS33Jm)Ohl7&+1Bc!colmQJYSFT?rlsbsLN;zJ8JUvtu&+OGz(@Y+C|5e} z_YDOHLj!%1G%QJ^Dh%Oqh?lH|Vq4>~JVV$IZWd|2T&o*NqMFs+9(&@pnz3)r$?ogd z9aMKcckVs$x9;-10P+PI