Skip to content

fix: comprehensive security hardening (audit findings)#98

Merged
a-bonus merged 2 commits intoa-bonus:mainfrom
Mawox:fix/security-audit
Mar 27, 2026
Merged

fix: comprehensive security hardening (audit findings)#98
a-bonus merged 2 commits intoa-bonus:mainfrom
Mawox:fix/security-audit

Conversation

@Mawox
Copy link
Copy Markdown

@Mawox Mawox commented Mar 27, 2026

Summary

Comprehensive security hardening based on a full codebase audit. Fixes 1 critical, 6 high, 7 medium, and 6 low severity issues. All changes are backward compatible.

Critical

  • Drive API query injection -- User input interpolated directly into Drive query strings without escaping. Added escapeDriveQuery() utility (escapes \ then ' per Google API docs) applied across searchGoogleDocs, listGoogleDocs, listFolderContents.

High

  • Redirect URI too permissive -- allowedRedirectUriPatterns changed from https://* to ${BASE_URL}/*
  • AsyncLocalStorage confused deputy -- In remote mode, client getters now throw instead of falling back to the server's own singleton credentials
  • Landing page XSS -- </script> breakout in inline JSON escaped with \u003c
  • Path traversal -- downloadFile and insertImage now validate paths resolve within cwd; API-derived filenames stripped with path.basename()
  • Silent public sharing -- uploadImageToDrive default changed to skipPublicSharing: true
  • Token file permissions -- Written with 0o600/0o700; client_secret removed from persisted payload

Medium

  • Userinfo fetch errors -- checkDomain now has try/catch + res.ok check
  • Env var validation -- Required vars checked at startup with clear error
  • Wrapper guards -- Double-wrap prevention, canAccess composition, SHA-256 hashed token cache keys
  • OAuth state + timeout -- Added CSRF state parameter and 5-minute timeout to local auth server
  • linkUrl scheme -- Restricted to http:// and https:// only
  • Error logging -- Sanitized API error responses (only message + code, not full response data)
  • Write size limits -- Added .max() constraints on batch writes, spreadsheet values, table data, markdown content

Low

  • Dockerfile -- Non-root USER node, added .dockerignore
  • npm audit -- Resolved all 11 vulnerabilities (0 remaining)
  • Profile path validation -- GOOGLE_MCP_PROFILE validated against ^[\w-]+$
  • parseRange fix -- Split on first ! only (handles sheet names containing !)

New: Persistent token storage

  • Added FirestoreTokenStorage implementing FastMCP's TokenStorage interface
  • Enabled via TOKEN_STORE=firestore env var for remote deployments
  • Tokens survive container restarts and redeployments
  • Configurable JWT_SIGNING_KEY and REFRESH_TOKEN_TTL env vars for production persistence

Test plan

  • npm run build -- clean compilation
  • npm test -- all 172 tests pass
  • npm run format:check -- Prettier clean
  • npm audit -- 0 vulnerabilities
  • Deployed to Cloud Run, tested end-to-end (read, write, delete operations confirmed)
  • OAuth re-auth works after deploy with Firestore token persistence
  • stdio mode unchanged (backward compatible)

@a-bonus a-bonus merged commit 1010fb8 into a-bonus:main Mar 27, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants