Skip to content

Feat: improve db efficiency - #305

Merged
Lore09 merged 10 commits into
devfrom
feat-improve-db-efficiency
Sep 1, 2026
Merged

Feat: improve db efficiency#305
Lore09 merged 10 commits into
devfrom
feat-improve-db-efficiency

Conversation

@Lore09

@Lore09 Lore09 commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator

This pull request introduces several improvements and optimizations to Krawl's database maintenance, metrics tracking, and Helm chart configuration. The most significant changes include the introduction of a PostgreSQL statistics maintenance module, migration of unique-path tracking to HyperLogLog for efficiency, and enhanced configurability and resource tuning for PostgreSQL and Redis in Kubernetes deployments.

Database maintenance and metrics improvements:

  • Introduced a new database/maintenance.py module that ensures PostgreSQL planner statistics are collected at critical times (on first boot and after retention purges), preventing poor query plans and performance regressions after restarts or bulk deletes. This includes the bootstrap_analyze and analyze_tables functions. [1] [2]
  • Added a DatabaseManager.engine property for direct access to the SQLAlchemy engine, enabling operations like ANALYZE that require connection-level control.
  • Updated metrics distinctness tracking: replaced the unbounded Redis SET for unique paths with a fixed-size HyperLogLog estimator, drastically reducing memory usage while maintaining approximate counts. Includes migration logic for legacy sets. [1] [2] [3] [4] [5]

Helm chart and Kubernetes resource/configuration enhancements:

  • PostgreSQL: Added support for custom server settings via postgres.config, increased default memory limits and requests, introduced postgres.shmSize for tuning /dev/shm (critical for parallel vacuum), and documented recommended settings for busy sensors. [1] [2] [3] [4] [5] [6]
  • Redis: Added configuration options for maxmemory and maxmemoryPolicy to prevent OOM kills and control eviction behavior, and increased default memory limits. [1] [2] [3]
  • Updated scheduled maintenance task times to later in the morning to avoid early-morning load.
  • Bumped Helm chart and app version to 2.3.4.

Dashboard cache optimization:

  • Added new functions to cache large lists in Redis as LISTs of JSON items (instead of a single blob), allowing efficient paginated retrieval and reducing memory and network overhead for large aggregates.

These changes improve Krawl's performance, scalability, and maintainability, especially in large-scale or Kubernetes environments.

Lore09 and others added 10 commits September 1, 2026 12:05
The rationale for shared_buffers, work_mem and the /dev/shm sizing belongs
in helm/README.md, which already carries it. A values file is read to find
a knob, not to learn why the knob exists, and thirty lines of prose between
two settings makes it harder to do that.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The seen-paths distinctness set had reached 2.9M members and ~94MB in
Redis -- essentially the whole instance -- to produce a single dashboard
integer. It could never stop growing: the set is keyed on request paths,
and Krawl generates random link paths, so the key space has no ceiling.
The standalone backend already capped itself at 100k entries for exactly
this reason; scalable mode inherited the risk without the mitigation.

PFADD/PFCOUNT hold that in a fixed ~12KB with 0.81% standard error.
Measured at 50k members: 2.58MB -> 14.1KB, 188x smaller.

unique_paths is no longer event-incremented in scalable mode. PFADD
reports whether the registers changed, not whether the member was new,
and it does return 1 for members already present -- incrementing on that
drifts the counter upward with no bound between reconciles. The counter
is instead realigned wholesale from PFCOUNT on the metrics flush, which
is O(1) since Redis caches the cardinality in the HLL header.

migrate_legacy_sets() folds any existing set into the estimator and
UNLINKs it, so deployments reclaim the memory on their next start. It
runs outside the needs_seed() gate deliberately: installs old enough to
have the legacy set already hold the seed marker, so a gated migration
would never fire on the ones that need it.

get_all() had to learn the new prefix as well -- it scans krawl:counter:*
and calls int() on every value, which a HyperLogLog blob would have
broken, taking the /metrics scrape down with it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Redis shipped with maxmemory unset and the default noeviction policy, so
it grew unbounded and then failed writes rather than shedding load -- the
same OOM shape the bundled PostgreSQL had. A live instance was sitting at
94MB with a 129MB peak against a 128Mi container limit.

volatile-lru is the policy that matches how the keyspace is used: every
krawl:cache:* entry is written with an expiry and is recomputable, while
the krawl:counter:* metrics are written without one and are not. Evicting
only keys that carry a TTL sheds cache under pressure and can never drop
a counter. allkeys-lru would silently corrupt the metrics.

The command block was previously emitted only when a password was set, so
password-less deployments had no way to receive server flags at all.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The aggregate caches were stored as one JSON blob and sliced in Python,
so serving any ten-row page pulled the entire aggregate over the wire and
parsed it: agg:map_ips holds up to 50k IP rows, agg:attackers and
agg:top_paths are sized at limit=100_000.

Storing them as Redis LISTs lets LRANGE fetch just the requested window.
Measured on a realistic 50k-row agg:map_ips (7.3MB): 391ms -> 12.4ms per
request, 32x faster.

Writes stage under a temporary key and RENAME into place, so a reader
during a warmup refresh sees the previous list rather than a partially
populated one.

Standalone keeps the plain in-memory list -- there is no serialization
boundary to cross there, so slicing it directly was already optimal.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@Lore09
Lore09 requested a review from BlessedRebuS September 1, 2026 10:34
@Lore09 Lore09 self-assigned this Sep 1, 2026
@Lore09 Lore09 added the infra Changes to the infra side of Krawl label Sep 1, 2026
@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Ruff — lint & security issues

No issues found.

@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Bandit — security issues

No HIGH severity issues found.

Code scanned:
	Total lines of code: 12965
	Total lines skipped (#nosec): 0
	Total potential issues skipped due to specifically being disabled (e.g., #nosec BXXX): 0

Run metrics:
	Total issues (by severity):
		Undefined: 0
		Low: 53
		Medium: 1
		High: 0
	Total issues (by confidence):
		Undefined: 0
		Low: 0
		Medium: 6
		High: 48
Files skipped (0):
View full report
Working... ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 0:00:00
Run started:2026-09-01 10:36:17.505144+00:00

Test results:
>> Issue: [B105:hardcoded_password_string] Possible hardcoded password: ''
   Severity: Low   Confidence: Medium
   CWE: CWE-259 (https://cwe.mitre.org/data/definitions/259.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b105_hardcoded_password_string.html
   Location: src/app.py:215:20
214	
215	    password_line = ""
216	    if config.dashboard_password_generated:

--------------------------------------------------
>> Issue: [B105:hardcoded_password_string] Possible hardcoded password: ''
   Severity: Low   Confidence: Medium
   CWE: CWE-259 (https://cwe.mitre.org/data/definitions/259.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b105_hardcoded_password_string.html
   Location: src/database/credentials.py:160:54
159	                .filter(CredentialAttempt.password.isnot(None))
160	                .filter(CredentialAttempt.password != "")
161	                .all()

--------------------------------------------------
>> Issue: [B104:hardcoded_bind_all_interfaces] Possible binding to all interfaces.
   Severity: Medium   Confidence: Medium
   CWE: CWE-605 (https://cwe.mitre.org/data/definitions/605.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b104_hardcoded_bind_all_interfaces.html
   Location: src/dependencies.py:90:11
89	
90	    return "0.0.0.0"  # noqa: S104 — sentinel for unknown client, not a socket bind
91	

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: src/generators.py:19:11
18	    wl = get_wordlists()
19	    return random.choice(wl.username_prefixes) + random.choice(wl.username_suffixes)
20	

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: src/generators.py:19:49
18	    wl = get_wordlists()
19	    return random.choice(wl.username_prefixes) + random.choice(wl.username_suffixes)
20	

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: src/generators.py:26:24
25	    templates = [
26	        lambda: "".join(random.choices(string.ascii_letters + string.digits, k=12)),
27	        lambda: f"{random.choice(wl.password_prefixes)}{random.randint(100, 999)}!",

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: src/generators.py:27:19
26	        lambda: "".join(random.choices(string.ascii_letters + string.digits, k=12)),
27	        lambda: f"{random.choice(wl.password_prefixes)}{random.randint(100, 999)}!",
28	        lambda: f"{random.choice(wl.simple_passwords)}{random.randint(1000, 9999)}",

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: src/generators.py:27:56
26	        lambda: "".join(random.choices(string.ascii_letters + string.digits, k=12)),
27	        lambda: f"{random.choice(wl.password_prefixes)}{random.randint(100, 999)}!",
28	        lambda: f"{random.choice(wl.simple_passwords)}{random.randint(1000, 9999)}",

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: src/generators.py:28:19
27	        lambda: f"{random.choice(wl.password_prefixes)}{random.randint(100, 999)}!",
28	        lambda: f"{random.choice(wl.simple_passwords)}{random.randint(1000, 9999)}",
29	        lambda: "".join(random.choices(string.ascii_lowercase, k=8)),

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: src/generators.py:28:55
27	        lambda: f"{random.choice(wl.password_prefixes)}{random.randint(100, 999)}!",
28	        lambda: f"{random.choice(wl.simple_passwords)}{random.randint(1000, 9999)}",
29	        lambda: "".join(random.choices(string.ascii_lowercase, k=8)),

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: src/generators.py:29:24
28	        lambda: f"{random.choice(wl.simple_passwords)}{random.randint(1000, 9999)}",
29	        lambda: "".join(random.choices(string.ascii_lowercase, k=8)),
30	    ]

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: src/generators.py:31:11
30	    ]
31	    return random.choice(templates)()
32	

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: src/generators.py:39:25
38	        username = random_username()
39	    return f"{username}@{random.choice(wl.email_domains)}"
40	

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: src/generators.py:48:11
47	    wl = get_wordlists()
48	    return random.choice(wl.server_headers)
49	

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: src/generators.py:54:18
53	    wl = get_wordlists()
54	    key = "".join(random.choices(string.ascii_letters + string.digits, k=32))
55	    return random.choice(wl.api_key_prefixes) + key

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: src/generators.py:55:11
54	    key = "".join(random.choices(string.ascii_letters + string.digits, k=32))
55	    return random.choice(wl.api_key_prefixes) + key
56	

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: src/generators.py:61:11
60	    wl = get_wordlists()
61	    return random.choice(wl.database_names)
62	

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: src/generators.py:67:20
66	    content = "# Production Credentials\n\n"
67	    for _i in range(random.randint(3, 7)):
68	        username = random_username()

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: src/generators.py:81:20
80	    content += "User Passwords:\n"
81	    for _i in range(random.randint(5, 10)):
82	        username = random_username()

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: src/generators.py:92:19
91	    users = []
92	    for i in range(random.randint(3, 8)):
93	        username = random_username()

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: src/generators.py:100:24
99	                "password": random_password(),
100	                "role": random.choice(wl.user_roles),
101	                "api_token": random_api_key(),

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: src/generators.py:112:22
111	            "public_key": "pk_live_"
112	            + "".join(random.choices(string.ascii_letters + string.digits, k=24)),
113	            "secret_key": random_api_key(),

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: src/generators.py:117:22
116	            "access_key_id": "AKIA"
117	            + "".join(random.choices(string.ascii_uppercase + string.digits, k=16)),
118	            "secret_access_key": "".join(

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: src/generators.py:119:16
118	            "secret_access_key": "".join(
119	                random.choices(string.ascii_letters + string.digits + "+/", k=40)
120	            ),

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: src/generators.py:124:22
123	            "api_key": "SG."
124	            + "".join(random.choices(string.ascii_letters + string.digits, k=48))
125	        },

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: src/generators.py:128:22
127	            "account_sid": "AC"
128	            + "".join(random.choices(string.ascii_lowercase + string.digits, k=32)),
129	            "auth_token": "".join(

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: src/generators.py:130:16
129	            "auth_token": "".join(
130	                random.choices(string.ascii_lowercase + string.digits, k=32)
131	            ),

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: src/generators.py:150:28
149	                    "email": random_email(username),
150	                    "role": random.choice(wl.user_roles),
151	                }

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: src/generators.py:158:38
157	            {
158	                "users": random_users(random.randint(2, 5)),
159	                "total": random.randint(50, 500),

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: src/generators.py:159:25
158	                "users": random_users(random.randint(2, 5)),
159	                "total": random.randint(50, 500),
160	            },

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: src/generators.py:168:30
167	                    {
168	                        "id": random.randint(1, 100),
169	                        "name": random_username(),

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: src/generators.py:179:28
178	                "database": {
179	                    "host": random.choice(wl.database_hosts),
180	                    "username": random_username(),

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: src/generators.py:188:24
187	                    + "".join(
188	                        random.choices(string.ascii_uppercase + string.digits, k=16)
189	                    ),

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: src/generators.py:196:28
195	            {
196	                "app_name": random.choice(wl.application_names),
197	                "debug": random.choice([True, False]),

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: src/generators.py:197:25
196	                "app_name": random.choice(wl.application_names),
197	                "debug": random.choice([True, False]),
198	                "secret_key": random_api_key(),

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: src/generators.py:203:31
202	        ),
203	        "/.env": f"""APP_NAME={random.choice(wl.application_names)}
204	DEBUG={random.choice(['true', 'false'])}

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: src/generators.py:204:7
203	        "/.env": f"""APP_NAME={random.choice(wl.application_names)}
204	DEBUG={random.choice(['true', 'false'])}
205	APP_KEY=base64:{''.join(random.choices(string.ascii_letters + string.digits, k=32))}=

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: src/generators.py:205:24
204	DEBUG={random.choice(['true', 'false'])}
205	APP_KEY=base64:{''.join(random.choices(string.ascii_letters + string.digits, k=32))}=
206	DB_CONNECTION=mysql

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: src/generators.py:212:31
211	DB_PASSWORD={random_password()}
212	AWS_ACCESS_KEY_ID=AKIA{''.join(random.choices(string.ascii_uppercase + string.digits, k=16))}
213	AWS_SECRET_ACCESS_KEY={''.join(random.choices(string.ascii_letters + string.digits + '+/', k=40))}

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: src/generators.py:213:31
212	AWS_ACCESS_KEY_ID=AKIA{''.join(random.choices(string.ascii_uppercase + string.digits, k=16))}
213	AWS_SECRET_ACCESS_KEY={''.join(random.choices(string.ascii_letters + string.digits + '+/', k=40))}
214	STRIPE_SECRET={random_api_key()}

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: src/generators.py:228:12
227	    selected_files = [
228	        (f, random.randint(1024, 1024 * 1024))
229	        for f in random.sample(files, min(6, len(files)))

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: src/generators.py:229:17
228	        (f, random.randint(1024, 1024 * 1024))
229	        for f in random.sample(files, min(6, len(files)))
230	    ]

--------------------------------------------------
>> Issue: [B105:hardcoded_password_string] Possible hardcoded password: ''
   Severity: Low   Confidence: Medium
   CWE: CWE-259 (https://cwe.mitre.org/data/definitions/259.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b105_hardcoded_password_string.html
   Location: src/routes/api.py:1580:8
1579	        "account_id": "",
1580	        "auth_token": "",
1581	        "list_id": None,
1582	    }
1583	    save_config(cfg)
1584	    return JSONResponse(content={"ok": True})
1585	
1586	

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: src/routes/honeypot.py:102:11
101	        return False
102	    return random.randint(1, 100) <= config.probability_error_codes
103	

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: src/routes/honeypot.py:110:11
109	        error_codes = [400, 401, 403, 404, 500, 502, 503]
110	    return random.choice(error_codes)
111	

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: src/routes/honeypot.py:597:20
596	    """Generate random word salad to confuse AI training data scrapers."""
597	    return " ".join(random.choice(_TARPIT_WORDS) for _ in range(n_words))
598	

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: src/routes/honeypot.py:623:16
622	
623	    num_pages = random.randint(*config.links_per_page_range)
624	    content = ""

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: src/routes/honeypot.py:638:20
637	                [
638	                    random.choice(config.char_space)
639	                    for _ in range(random.randint(*config.links_length_range))

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: src/routes/honeypot.py:639:35
638	                    random.choice(config.char_space)
639	                    for _ in range(random.randint(*config.links_length_range))
640	                ]

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: src/routes/honeypot.py:649:22
648	        for _ in range(num_pages):
649	            address = random.choice(webpages)
650	            content += f"""

--------------------------------------------------
>> Issue: [B404:blacklist] Consider possible security implications associated with the subprocess module.
   Severity: Low   Confidence: High
   CWE: CWE-78 (https://cwe.mitre.org/data/definitions/78.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_imports.html#b404-import-subprocess
   Location: src/tasks/db_dump.py:6:0
5	import sqlite3
6	import subprocess
7	

--------------------------------------------------
>> Issue: [B603:subprocess_without_shell_equals_true] subprocess call - check for execution of untrusted input.
   Severity: Low   Confidence: High
   CWE: CWE-78 (https://cwe.mitre.org/data/definitions/78.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b603_subprocess_without_shell_equals_true.html
   Location: src/tasks/db_dump.py:92:17
91	    try:
92	        result = subprocess.run(  # noqa: S603 — fixed pg_dump, list args, no shell
93	            cmd, env=env, capture_output=True, text=True, timeout=300
94	        )
95	        if result.returncode == 0:

--------------------------------------------------
>> Issue: [B105:hardcoded_password_string] Possible hardcoded password: ''
   Severity: Low   Confidence: Medium
   CWE: CWE-259 (https://cwe.mitre.org/data/definitions/259.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b105_hardcoded_password_string.html
   Location: src/webhooks.py:34:12
33	            "account_id": "",
34	            "auth_token": "",
35	            "list_id": None,
36	            "list_name": "krawl_banlist",
37	            "list_description": "IPs banned by Krawl honeypot",
38	            "sync_interval_minutes": 30,
39	            "categories": ["attacker"],
40	            "last_sync": None,
41	            "last_sync_status": None,
42	            "last_sync_error": None,
43	        }
44	    }
45	
46	
47	# CloudFlare credentials may come from the environment (k8s Secrets) instead of

--------------------------------------------------
>> Issue: [B105:hardcoded_password_string] Possible hardcoded password: 'KRAWL_CLOUDFLARE_AUTH_TOKEN'
   Severity: Low   Confidence: Medium
   CWE: CWE-259 (https://cwe.mitre.org/data/definitions/259.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b105_hardcoded_password_string.html
   Location: src/webhooks.py:51:4
50	    "account_id": "KRAWL_CLOUDFLARE_ACCOUNT_ID",
51	    "auth_token": "KRAWL_CLOUDFLARE_AUTH_TOKEN",
52	}
53	
54	
55	def _apply_cf_env(data: dict) -> dict:

--------------------------------------------------

Code scanned:
	Total lines of code: 12965
	Total lines skipped (#nosec): 0
	Total potential issues skipped due to specifically being disabled (e.g., #nosec BXXX): 0

Run metrics:
	Total issues (by severity):
		Undefined: 0
		Low: 53
		Medium: 1
		High: 0
	Total issues (by confidence):
		Undefined: 0
		Low: 0
		Medium: 6
		High: 48
Files skipped (0):

@Lore09
Lore09 merged commit 0575a33 into dev Sep 1, 2026
5 checks passed
@Lore09
Lore09 deleted the feat-improve-db-efficiency branch September 1, 2026 10:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

infra Changes to the infra side of Krawl

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants