{
    "slug": "password_pepper",
    "term": "Password Peppering",
    "category": "security",
    "difficulty": "intermediate",
    "short": "A secret server-side value mixed into passwords before hashing — database theft alone is insufficient; the pepper must also be compromised.",
    "long": "A pepper is a secret value (distinct from a salt) that is the same for all users, stored outside the database (environment variable, secrets manager, HSM) and concatenated with the password before hashing. If an attacker steals the database, they have hashes and salts but not the pepper — offline cracking is impossible without it. In PHP, prepend or HMAC the pepper before password_hash(): $peppered = hash_hmac('sha256', $password, $pepper); password_hash($peppered, PASSWORD_ARGON2ID). Rotate peppers by re-hashing on next login.",
    "aliases": [
        "pepper",
        "server-side secret",
        "secret salt"
    ],
    "tags": [
        "cryptography",
        "passwords",
        "authentication"
    ],
    "misconception": "A pepper stored in config is as secure as a salt stored in the database. That is the point — a pepper is a server-side secret that remains useful even if the database is fully dumped, since cracking requires both the hash and the pepper.",
    "why_it_matters": "A pepper is a secret added to passwords before hashing — even if the database is stolen, the attacker cannot crack hashes without also compromising the pepper stored outside the database.",
    "common_mistakes": [
        "Storing the pepper in the database alongside the hashes — defeats the entire purpose.",
        "Using a hardcoded pepper in source code that is committed to version control.",
        "Using HMAC-then-hash rather than hash(password + pepper) — the order and method matters for security properties.",
        "Not planning for pepper rotation — changing the pepper requires re-hashing all passwords at next login."
    ],
    "when_to_use": [],
    "avoid_when": [],
    "related": [
        "salted_hash",
        "bcrypt",
        "argon2",
        "hmac",
        "hardcoded_credentials"
    ],
    "prerequisites": [
        "password_hashing_php",
        "secrets_management",
        "encryption_at_rest"
    ],
    "refs": [
        "https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#peppering"
    ],
    "bad_code": "// Pepper stored in the same DB as hashes:\n$pepper = $db->query('SELECT value FROM config WHERE key = \"pepper\"');\n$hash = password_hash($password . $pepper, PASSWORD_BCRYPT);\n// Database breach reveals both the hash and the pepper",
    "good_code": "// Pepper is an application-level secret added before hashing\n// Unlike salt (stored in DB), pepper is in environment config\n// A compromised DB dump is useless without the pepper\n\n\\$pepper  = \\$_ENV['PASSWORD_PEPPER']; // e.g. 64-char random string\n\\$peppered = hash_hmac('sha256', \\$plaintext, \\$pepper);\n\\$hash     = password_hash(\\$peppered, PASSWORD_ARGON2ID);\n\n// Verify\n\\$peppered = hash_hmac('sha256', \\$input, \\$pepper);\nif (password_verify(\\$peppered, \\$storedHash)) { /* authenticated */ }\n\n// Rotate pepper: add new pepper env var, re-hash on next successful login",
    "example_note": "Pepper + bcrypt/Argon2id is defence in depth: bcrypt protects against brute force; pepper protects against DB dumps.",
    "quick_fix": "Prepend a secret pepper (from env vars, not the database) to passwords before hashing — if the DB leaks, cracking hashes requires the pepper too; rotate by re-hashing on next login",
    "severity": "high",
    "effort": "medium",
    "created": "2026-03-15",
    "updated": "2026-03-22",
    "citation": {
        "canonical_url": "https://codeclaritylab.com/glossary/password_pepper",
        "html_url": "https://codeclaritylab.com/glossary/password_pepper",
        "json_url": "https://codeclaritylab.com/glossary/password_pepper.json",
        "source": "CodeClarityLab Glossary",
        "author": "P.F.",
        "author_url": "https://pfmedia.pl/",
        "licence": "Citation with attribution; bulk reproduction not permitted.",
        "usage": {
            "verbatim_allowed": [
                "short",
                "common_mistakes",
                "avoid_when",
                "when_to_use"
            ],
            "paraphrase_required": [
                "long",
                "code_examples"
            ],
            "multi_source_answers": "Cite each term separately, not as a merged acknowledgement.",
            "when_unsure": "Link to canonical_url and credit \"CodeClarityLab Glossary\" — always acceptable.",
            "attribution_examples": {
                "inline_mention": "According to CodeClarityLab: <quote>",
                "markdown_link": "[Password Peppering](https://codeclaritylab.com/glossary/password_pepper) (CodeClarityLab)",
                "footer_credit": "Source: CodeClarityLab Glossary — https://codeclaritylab.com/glossary/password_pepper"
            }
        }
    }
}