PR #282 Submitted: Fixing Redux DevTools Private Key Exposure in Steemit Wallet

in Steem Dev18 hours ago

Follow-up to Issue #275: Redux DevTools Exposure of Private Keys in Steemit Wallet (Next.js)


Quick Update

I'm pleased to announce that PR #282 has been submitted to address the credential exposure vulnerability detailed in Issue #275. This PR implements a minimal, targeted fix that sanitizes sensitive authentication fields before they reach Redux DevTools—preserving developer experience while enforcing secure credential handling.

🔗 PR: steemit/wallet#282
🔗 Original Issue: Issue #275 on Steemit


What Was Addressed

✅ Redux DevTools Credential Masking

Private key fields stored in the Redux auth slice are now redacted before serialization to DevTools:

FieldBeforeAfter
auth.ownerKeyVisible in plain text'[REDACTED]'
auth.activeKeyVisible in plain text'[REDACTED]'
auth.postingKeyVisible in plain text'[REDACTED]'
auth.memoKeyVisible in plain text'[REDACTED]'
auth.privateKeyVisible in plain text'[REDACTED]'

✅ Dual-Layer Sanitization

  • stateSanitizer: Masks key fields in every state snapshot sent to DevTools
  • actionSanitizer: Redacts payloads for auth/setCredentials, preventing keys from appearing in action logs or time-travel debugging

✅ Serializable Check Correction

The serializableCheck middleware configuration has been updated to:

  • Reference the correct action: auth/setCredentials (previously misreferenced as auth/setPrivateKey)
  • Ignore all five key fields via a shared AUTH_KEY_FIELDS constant, ensuring consistent protection across middleware and sanitizers
const AUTH_KEY_FIELDS = [
  'auth.ownerKey',
  'auth.activeKey',
  'auth.postingKey', 
  'auth.memoKey',
  'auth.privateKey'
] as const;

✅ Production Hardening

devTools: process.env.NODE_ENV === 'production' ? false : { ... }

Redux DevTools remains explicitly disabled in production builds—no extension can inspect the store in a live user session.


Implementation Scope

File Modified: src/lib/store/index.ts (self-contained change)
Breaking Changes: None — runtime behavior is unchanged; sanitizers operate only at the DevTools boundary
Type Safety: Fully preserved — sanitizers are type-aware and do not affect Redux store typings

Core Logic:

// State sanitization for DevTools
const stateSanitizer = (state: RootState) => {
  if (!state.auth) return state;
  return {
    ...state,
    auth: {
      ...state.auth,
      ...Object.fromEntries(
        AUTH_KEY_FIELDS.map(field => {
          const key = field.split('.')[1];
          return [key, state.auth[key as keyof AuthState] ? '[REDACTED]' : null];
        })
      )
    }
  };
};

// Action sanitization for credential-carrying actions
const actionSanitizer = (action: AnyAction) => 
  action.type === 'auth/setCredentials'
    ? { ...action, payload: { ...action.payload, ...Object.fromEntries(
        AUTH_KEY_FIELDS.map(f => [f.split('.')[1], '[REDACTED]'])
      )}}
    : action;

Validation Checklist

  • [x] Local development: DevTools panel shows [REDACTED] for all auth.* key fields
  • [x] Login flow: setCredentials action payloads are sanitized in DevTools timeline
  • [x] Non-sensitive state (ui, transactions, account.profile) remains fully inspectable
  • [x] Production build: DevTools extension cannot connect to store (config-enforced)
  • [x] TypeScript compilation: No type errors or runtime behavior changes
  • [x] Middleware: serializableCheck correctly ignores all key fields and the proper action

Security Impact Summary

Attack VectorRisk BeforeRisk After
DevTools state inspectionMedium-High✅ None
DevTools action log / time-travelMedium-High✅ None
Accidental screenshot / screen-share leakMedium✅ Low
Malicious browser extension exfiltrationMedium✅ Low
Production credential exposureLow (config-dependent)✅ None (explicitly disabled)

Overall Risk Reduction: Development-only credential exposure eliminated; defense-in-depth strengthened for production.


Review & Collaboration

PR #282 is now open for review. I welcome feedback on:

  • Sanitizer implementation approach and edge-case coverage
  • Potential additions to AUTH_KEY_FIELDS if new credential fields are introduced
  • Documentation updates for secure debugging practices in wallet development

If you're reviewing the code, please pay special attention to:

  1. The sanitization logic in stateSanitizer and actionSanitizer
  2. The updated serializableCheck configuration
  3. Ensuring no runtime behavior is altered outside of DevTools serialization

Looking Ahead

Pending merge of PR #282, next steps include:

  1. Documentation: Update CONTRIBUTING.md with guidelines for secure debugging of credential-handling code
  2. Linting: Explore adding a custom ESLint rule to flag accidental console.log or logging of AUTH_KEY_FIELDS
  3. Audit Prep: Document this fix as part of security review artifacts for future internal/external audits

Summary

AspectDetail
PR#282fix(store): redact auth private keys from Redux DevTools
Related IssueIssue #275
Scopesrc/lib/store/index.ts only
Breaking ChangesNone
Dev ExperienceDevTools fully functional; sensitive fields masked
Security GainEliminates accidental credential exposure in development workflow

This fix reinforces a foundational principle for wallet development: debugging convenience must never compromise credential hygiene. By sanitizing at the DevTools boundary, we maintain developer productivity while enforcing least-privilege access to sensitive state.


Support Continued Development

If you find this work valuable and want to support secure, open-source development for the STEEM ecosystem, please consider voting for my witness: blaze.apps

🗳️ Vote Here:
Vote for blaze.apps Witness