# Docs: RFC 7617 — The 'Basic' HTTP Authentication Scheme
# Format: `Authorization: Basic <base64(user:password)>`
# Verify: base64-decode the captured blob; a real credential decodes to `user:pass`.
#
# Recall lane (CredData-measured): the `Authorization: Basic <base64>` header has
# NO `keyword = value` assignment, so keyhog's generic keyword bridge never
# generated a candidate for it — all 643 labeled "Auth:Basic" positives were
# NEVER-CANDIDATE (decompose, 2026-06-21). The "Basic " scheme token is itself a
# strong HTTP structural anchor (RFC 7617), and the captured value is base64 of
# `user:password`. The miss_analysis `basic_auth` candidate measured 643 TP / 15
# FP (precision 0.977) on the labeled CredData files — keyhog's placeholder /
# shape / prose suppression further filters the residual non-credential matches.
# `Basic` (5 chars) is >= MIN_LITERAL_PREFIX_CHARS (3), so it is a first-class
# AC-literal / Hyperscan trigger — no fallback-only regression.
[detector]
id = "http-basic-auth"
name = "HTTP Basic Authorization Credential"
service = "http-basic-auth"
severity = "medium"
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 } }
# `Basic` is the RFC 7617 auth-scheme token that immediately precedes the
# base64(user:password) blob in every `Authorization: Basic …` header.
keywords = ["Basic"]
[[detector.patterns]]
# Capture ONLY the base64 blob (group 1) so the extracted credential matches the
# CredData value span (the base64, not the `Basic ` prefix). `{16,}` requires a
# blob long enough to encode a real `user:password` (>= ~12 decoded bytes),
# excluding the trivially-short decoy values.
regex = "Basic\\s+([A-Za-z0-9+/]{16,}={0,2})"
group = 1
description = "HTTP Authorization: Basic <base64(user:password)> credential blob"
[[detector.tests]]
test_positive = "Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQxMjM="
test_negative = "Authorization: Basic short"