Skip to main content

Overview

The secrets scanner is ZenVeil’s most comprehensive detector. It runs on scan repo and scan github targets and covers two categories:
  1. Credential patterns — actual secrets that should never appear in source code
  2. Repository risk patterns — OWASP anti-patterns that create security debt

Credential patterns

These findings are always CRITICAL or HIGH severity. They indicate live credentials committed to source.
PatternSeverityConfidenceDescription
AWS access keyCRITICAL95%AKIA + 16 alphanumeric characters
GitHub tokenCRITICAL95%ghp_, gho_, ghu_, ghs_, ghr_ prefix
Private key blockCRITICAL98%-----BEGIN ... PRIVATE KEY-----
Hardcoded API keyHIGH80%api_key = "...", access_token = "..."
Hardcoded passwordHIGH75%password = "...", passwd = "..."
JWT tokenHIGH85%Three base64url segments separated by .
Slack tokenHIGH90%xoxb-, xoxa-, xoxp-, xoxr-, xoxs-

Example finding

ID:          ZG-A1B2C3
Severity:    CRITICAL
Title:       AWS access key
Scanner:     secrets
Category:    secrets
OWASP:       A02:2021 — Cryptographic Failures
Location:    src/config.js:14:23
Evidence:    AWS access key pattern matched; secret value redacted.
Confidence:  95%
Remediation: Revoke the AWS key, remove it from the repository, and
             load it from a secret manager or environment variable.

Repository risk patterns

These findings surface OWASP anti-patterns that are common in AI-generated code. Severity ranges from MEDIUM to CRITICAL.

Authentication & session management

PatternSeverityOWASP
Predictable JWT signing secret (changeme, secret, etc.)CRITICALA02:2021
JWT signed inline with predictable secretCRITICALA02:2021
Token stored in localStorage or sessionStorageHIGHA02:2021, A07:2021
Client-written cookie with token dataHIGHA02:2021
Long-lived session token (365d, never, 0)MEDIUMA07:2021
Client-side-only logoutMEDIUMA07:2021

Authorization

PatternSeverityOWASP
Client-side admin gate (isAdmin, role === 'admin')MEDIUMA01:2021
Sensitive route without visible auth middlewareHIGHA01:2021
Object lookup by request-controlled ID (possible IDOR)MEDIUMA01:2021

Frontend exposure

PatternSeverityOWASP
Secret in VITE_, NEXT_PUBLIC_, REACT_APP_ env varHIGHA02:2021
Open redirect using request parametersHIGHA01:2021

Infrastructure

PatternSeverityOWASP
Debug mode enabled (DEBUG=True, NODE_ENV=development)MEDIUMA05:2021
USER root in DockerfileHIGHA05:2021
Public database bind addressHIGHA05:2021
Weak password hashing (MD5, SHA1)HIGHA02:2021
Low bcrypt cost factor (≤10)MEDIUMA02:2021

Dependencies

PatternSeverityOWASP
Install-time script in package.jsonMEDIUMA06:2021
Unpinned Python dependency in requirements.txtLOWA06:2021

Environment file hygiene

The secrets scanner also checks:
  • .env file committed (HIGH, 97% confidence) — any .env, .env.local, .env.production, etc. found in the repo
  • .env not in .gitignore (MEDIUM, 93% confidence) — the .gitignore doesn’t contain an .env exclusion pattern
# Fix both with:
git rm --cached .env
echo ".env*" >> .gitignore
git commit -m "Remove .env from tracking and add to gitignore"

Files scanned

The scanner traverses all files in the repository except:
  • node_modules/, .venv/, __pycache__/, .git/
  • Binary files (images, archives, compiled artifacts)
  • Files > 1MB (unlikely to contain useful patterns)

Context-aware severity

Test, fixture, mock, and example files are scanned by default — because real credentials are routinely committed there. Instead of ignoring these files and creating blind spots, ZenVeil detects findings in all files but adjusts severity based on file context.

How it works

When a secret is found outside of production code, ZenVeil:
  1. Detects it with the same confidence as a production finding
  2. Downgrades the severity by one or two tiers
  3. Appends (test file), (fixture file), or (example file) to the title
  4. Labels the finding with a context badge in the output

Severity downgrade table

Original severityIn test/fixture/example file
CRITICAL→ MEDIUM
HIGH→ LOW
MEDIUM→ LOW
LOW→ LOW

Context classification

Files are classified by their path:
ContextMatched paths
productionEverything not matched below — full severity
testtests/, test/, spec/, __tests__/, e2e/, integration/, unit/, *.test.*, *.spec.*, test_*.py
fixturefixtures/, mocks/, stubs/, fakes/, seeds/, factory/, testdata/
exampleexamples/, demos/, samples/

Example

# Production file → CRITICAL
ZG-A1B2  CRITICAL  prod     secrets   AWS access key           src/config.py:14

# Test file → downgraded to MEDIUM
ZG-C3D4  MEDIUM    test     secrets   AWS access key (test file)   tests/test_auth.py:8
To skip non-production files entirely, use the --exclude-tests flag:
zenveil scan github owner/repo --exclude-tests
This is not recommended as the default — credentials in test history are still in your git history and still exploitable. See Context-aware scanning for the full rationale.

Avoiding false positives

All secret values in findings are redacted — ZenVeil never logs, stores, or transmits actual credential values. To suppress a confirmed false positive:
zenveil ignore ZG-A1B2C3 --reason "Test fixture — not a real key"
To record it for the feedback loop:
zenveil feedback ZG-A1B2C3 false_positive