# Hard gate: credential leak detection. level: hard => BLOCKS the action.
#
# Correct action: DENY any tool call that would emit a real secret.
# Evidence: a known secret prefix OR an assignment of a secret-shaped value to a
#           public surface (command line, file write, stdout, web call).
# Logic: a leaked credential is irreversible — you cannot un-publish it. The only
#        safe secret is one that never entered the call. Fail CLOSED: if we can't
#        be sure it's safe, we block. A guard that fails open on secrets is no guard.

name: "no_credential_leak"
prompt: "Did I expose any credential in this call?"
enforcement:
  level: "hard"
behavior:
  kind: "guard"
  correct_action: "BLOCK the tool call; return a deny with reason naming the matched pattern."
  evidence:
    - "Command/params contain a known secret prefix (sk-, AIza, xoxb-, xoxp-, AKIA, ghp_, gho_, glpat-, -----BEGIN PRIVATE KEY-----)."
    - "An assignment of a secret-shaped value to a public surface: *_key=, *_secret=, password=, token=, api_key=, apikey=, client_secret= with a non-empty RHS."
    - "require_assignment: true ensures 'read api_key from vault' does NOT block (reference, not emission); 'api_key=sk-...' DOES block (emission)."
  logic: "Exposure is irreversible and the blast radius is unbounded (token reuse, key compromise). Blocking a false positive costs one retry; leaking costs a rotation + breach. The asymmetry mandates fail-closed."
  steps:
    - check: "block_secret_leak"
      patterns:
        - "sk-"
        - "sk_"
        - "AIza"
        - "xoxb-"
        - "xoxp-"
        - "AKIA"
        - "ghp_"
        - "gho_"
        - "glpat-"
        - "-----BEGIN PRIVATE KEY-----"
        - "client_secret="
        - "api_key="
        - "apikey="
        - "password="
        - "secret="
        - "token="
      require_assignment: true
