Skip to content

Missing Authentication on GraphQL Subscriptions onConnect Handler#2

Open
kolega-ai-dev wants to merge 1 commit intomainfrom
v11-finding_62
Open

Missing Authentication on GraphQL Subscriptions onConnect Handler#2
kolega-ai-dev wants to merge 1 commit intomainfrom
v11-finding_62

Conversation

@kolega-ai-dev
Copy link
Copy Markdown
Owner

Vulnerability identified and fix provided by Kolega.dev

Missing Authentication on GraphQL Subscriptions onConnect Handler

Location

server/core/servers.js:127-129

Description

The GraphQL subscriptions onConnect handler is empty and does not validate or authenticate connection parameters. This means any client can establish a subscription connection without credentials.

The onConnect handler at line 127-129 in servers.js is empty, meaning WebSocket connections for GraphQL subscriptions are established without any authentication. The @auth directive used elsewhere (e.g., LoggingQuery requires manage:system) only protects Query/Mutation resolvers via field resolution wrapping — it does NOT apply to Subscription resolvers. The loggingLiveTrail subscription in logging.js directly returns WIKI.GQLEmitter.asyncIterator('livetrail') without any auth check. The schema at logging.graphql line 14 shows loggingLiveTrail: LoggerTrailLine has no @auth directive.

This means any client can:

  1. Establish a WebSocket connection to /graphql-subscriptions
  2. Subscribe to loggingLiveTrail
  3. Receive all application logs in real-time including debug-level output

This is unauthenticated access to sensitive operational logs that may contain file paths, database errors, configuration details, and other sensitive information.

Fix Applied

Implemented JWT authentication in the onConnect handler to validate WebSocket connections. The handler extracts the JWT token from connectionParams.token (sent by the client) or falls back to the jwt cookie from the WebSocket upgrade request headers. It verifies the token using the same RS256 credentials (WIKI.config.certs.public, audience, issuer) used by the existing passport JWT strategy, and requires the manage:system permission — consistent with how LoggingQuery and LoggingMutation are protected via @auth(requires: ["manage:system"]). Updated the client-side WebSocket link to pass the JWT token via connectionParams.

Tests/Linters Ran

  • ESLint (npx eslint --format codeframe server/core/servers.js client/client-app.js): Passed with no errors
  • Jest (npx jest --passWithNoTests): server/test/helpers/page.test.js passed (3/3 tests). Cypress spec failures are pre-existing (require browser environment)
  • Node syntax check (node -c server/core/servers.js): Passed
  • Module verification: Confirmed jsonwebtoken (direct dependency) and cookie (transitive via cookie-parser) are available and working

Contribution Notes

  • Follows the project's conventional commit style as seen in recent commits (e.g., fix:, feat:)
  • No new direct dependencies added — jsonwebtoken is already a direct dependency, and cookie is available as a transitive dependency of cookie-parser
  • Matches existing code style (2-space indentation, single quotes, Standard JS conventions)
  • Per CONTRIBUTING.md, the description explains what the code does and the purpose of the change

The onConnect handler for GraphQL subscriptions was empty, allowing any
client to establish a WebSocket connection and subscribe to loggingLiveTrail
without authentication. Added JWT verification in onConnect using the same
RS256 credentials and permission checks (manage:system) used elsewhere.
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