keyhog-core 0.5.73

keyhog-core: shared data model and detector specifications for the KeyHog secret scanner
Documentation
# Tier-B data: cross-file credential correlation policy.
#
# `keyhog scan --correlate` runs a join over the findings a scan already
# reported and publishes the groups as a separate `correlations` array. It never
# adds, drops, or edits a finding, so this file can only change the correlation
# section of a report.
#
# Two joins are defined:
#
#   value reuse      Identical credential digest observed at more than one file
#                    path, across detector boundaries. Per-detector dedup
#                    already folds repeats of ONE detector into
#                    `additional_locations`; it never crosses detectors, so a
#                    value matched as `adobe-api-key` in one file and
#                    `spotify-client-credentials` in another stays two unrelated
#                    findings without this join. Needs no service knowledge and
#                    is therefore configured purely by `[settings]`.
#
#   split composite  A provider credential whose halves are separate detectors
#                    (an id and its matching secret) planted in DIFFERENT files.
#                    A detector's own `[[detector.companions]]` regex only
#                    reaches a few lines inside one file, so a key in `main.tf`
#                    and its secret in `.env` are two medium-confidence
#                    singletons today. Every service named by this join lives in
#                    a `[[composite]]` row below, never in a Rust match arm:
#                    adding a provider is a data edit reviewable in one diff.
#
# Precision contract for `[[composite]]`: a group is emitted only when the
# directory holds EXACTLY ONE candidate credential for each required part, and
# no single file holds every required part. Two access keys and three secrets
# sharing a directory is an ambiguous pairing, so nothing is emitted rather than
# a guess.

[settings]
# Distinct file paths one credential digest must occupy before value reuse is
# reported. Two is the smallest genuinely cross-file set; raising it reports
# only widely copy-pasted credentials.
reuse_min_files = 2

# Confidence added to the strongest member of a value-reuse group. A secret
# present verbatim in several unrelated files is far less likely to be a
# placeholder or a random high-entropy blob than the same string seen once.
reuse_confidence_bonus = 0.15

# Ceiling for any correlated confidence. Correlation is corroborating evidence,
# not verification, so it never claims 1.0 on its own; a member that already
# scored 1.0 keeps 1.0 through the clamp.
max_confidence = 0.99

# Operator-facing meaning of a value-reuse group. Prose lives here for the same
# reason the service rows do: a reviewer sees a wording change in the data diff
# instead of buried in a reporter.
reuse_impact = "One credential value is present in several files, so rotating it means editing every listed location; every copy stays live until the value is revoked at the provider."

# ---------------------------------------------------------------------------
# Composite credentials. `required` parts must all be present and unambiguous;
# `optional` parts join the group when present and never gate it.
# ---------------------------------------------------------------------------

[[composite]]
id = "aws-iam-user"
service = "aws"
name = "AWS IAM user access key and secret access key"
severity = "critical"
required = ["aws-access-key", "aws-secret-access-key"]
optional = ["aws-session-token"]
confidence_bonus = 0.30
impact = "Both halves of an AWS SigV4 credential are present; together they authenticate to every API the IAM principal is allowed to call."

[[composite]]
id = "twilio-api-credentials"
service = "twilio"
name = "Twilio API key and account auth token"
severity = "critical"
required = ["twilio-api-key", "twilio-auth-token"]
confidence_bonus = 0.25
impact = "The auth token authenticates the account the API key belongs to, so the pair can place calls, send messages, and read message bodies."

[[composite]]
id = "github-oauth-app"
service = "github"
name = "GitHub OAuth app client secret and access token"
severity = "critical"
required = ["github-oauth-access-token", "github-oauth-secret"]
confidence_bonus = 0.25
impact = "The client secret lets an attacker mint further tokens for the same OAuth app rather than only replaying the one leaked access token."

[[composite]]
id = "github-app"
service = "github"
name = "GitHub App private key and installation token"
severity = "critical"
required = ["github-app-private-key", "github-app-installation-token"]
confidence_bonus = 0.25
impact = "The private key signs new installation tokens indefinitely; revoking the leaked installation token alone does not close the access."

[[composite]]
id = "slack-app"
service = "slack"
name = "Slack app client secret and bot token"
severity = "high"
required = ["slack-bot-token", "slack-oauth-secret"]
confidence_bonus = 0.20
impact = "The client secret allows the OAuth exchange to be repeated for the same app, re-issuing bot tokens after the leaked one is revoked."

[[composite]]
id = "stripe-account"
service = "stripe"
name = "Stripe secret key and webhook signing secret"
severity = "critical"
required = ["stripe-secret-key", "stripe-webhook-signing-secret"]
confidence_bonus = 0.20
impact = "The secret key moves money and the signing secret forges webhook callbacks, so fraudulent charges can be made to look confirmed."

[[composite]]
id = "sendgrid-account"
service = "sendgrid"
name = "SendGrid API key and webhook signing secret"
severity = "high"
required = ["sendgrid-api-key", "sendgrid-webhook-signing-secret"]
confidence_bonus = 0.20
impact = "Mail can be sent from the verified domain while forged event callbacks hide the delivery evidence."

[[composite]]
id = "mailgun-account"
service = "mailgun"
name = "Mailgun API key and webhook signing key"
severity = "high"
required = ["mailgun-api-key", "mailgun-webhook-signing-key"]
confidence_bonus = 0.20
impact = "Mail can be sent from the verified domain while forged event callbacks hide the delivery evidence."

[[composite]]
id = "shopify-store"
service = "shopify"
name = "Shopify admin API token and webhook secret"
severity = "high"
required = ["shopify-admin-api-token", "shopify-webhook-secret"]
confidence_bonus = 0.20
impact = "The admin token reads orders and customer records while the webhook secret forges order and payment notifications."

[[composite]]
id = "gitlab-runner"
service = "gitlab"
name = "GitLab runner registration and authentication tokens"
severity = "high"
required = [
    "gitlab-runner-registration-token",
    "gitlab-runner-authentication-token",
]
confidence_bonus = 0.20
impact = "A rogue runner can be registered and then claim CI jobs, exposing every masked variable those pipelines inject."