keyhog-core 0.5.50

keyhog-core: shared data model and detector specifications for the KeyHog secret scanner
Documentation
# Docs: https://www.postgresql.org/docs/current/libpq-connect.html
# Format: postgresql://user:pass@host.domain:port/db
# Prefix: postgres

[detector]
id = "postgresql-connection-string"
name = "PostgreSQL Connection String"
service = "postgresql"
severity = "critical"
resolution_priority = 2
ml = { match_mode = "lift", entropy_mode = "disabled", weight = 1.0, context_radius_lines = 5 }
match_confidence = { literal_prefix_weight = 0.35, context_anchor_weight = 0.20, entropy_weight = 0.20, high_entropy_partial_weight = 0.12, moderate_entropy_threshold = 3.0, moderate_entropy_weight = 0.05, low_entropy_penalty_floor = 2.0, low_entropy_min_match_length = 10, low_entropy_penalty_multiplier = 0.60, keyword_nearby_weight = 0.10, sensitive_file_weight = 0.10, companion_weight = 0.05, very_high_entropy_margin = 1.2999999999999998, named_anchor_floor = 0.55, assignment_context_multiplier = 1.0, string_literal_context_multiplier = 0.9, unknown_context_multiplier = 0.8, documentation_context_multiplier = 0.3, comment_context_multiplier = 0.4, test_context_multiplier = 0.3, encrypted_context_multiplier = 0.05, soft_context_suppression_threshold = 0.5, encrypted_context_suppression_threshold = 0.8, post_match = { placeholder_multiplier = 0.05, minimum_byte_diversity = 0.1, low_diversity_multiplier = 0.1, maximum_repeat_ratio = 0.8, degenerate_run_min_length = 10, degenerate_repeat_multiplier = 0.1, fixture_path_multiplier = 0.5, ml_context_reapply_below = 0.95 } }
keywords = ["postgresql", "postgres", "postgres_url", "POSTGRES_URL", "pg-url", "PG_URL", "DATABASE_URL"]
min_confidence = 0.2

[[detector.patterns]]
# Keep explicit alternation instead of `postgres(?:ql)?`: the AC prefix
# extractor otherwise does not reliably seed the plain `postgres://` branch,
# so decoded k8s `data:` values without nearby `DATABASE_URL` context miss.
# Widen the host class to accept Kubernetes service names (`postgres-db`)
# and docker hostnames (`postgres`), not just dotted-FQDN hosts. The
# previous regex required `.` in the host and missed every short-host
# fixture. Empty username (`postgres://:pass@host`) is also accepted
# now for parity with the redis pattern. The capture deliberately stops
# at the host (excludes the trailing `/db?query`) so the credential
# surface matches the existing contract harness.
regex = '''(?:postgresql|postgres)://[^:]*:[^@\s"'']+@[a-zA-Z0-9._-]+'''
description = "PostgreSQL connection string with credentials (host-bounded capture)"

[[detector.tests]]
test_positive = "postgresql://neondb:w0kVdGwi5GpLapAX@ep-cool-name-123456.us-east-2.aws.neon.tech/neondb"
test_negative = "YOUR_API_KEY_HERE_PLACEHOLDER_VALUE"