-
-
Notifications
You must be signed in to change notification settings - Fork 417
Create User Subdomain Management System for Pollinations #2746
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
✅ Deploy Preview for pollinations canceled.
|
✅ Deploy Preview for pollinations-react-hooks-docs canceled.
|
|
I'm getting to work. See my steps and track my cost here.
|
|
This PR implements the User Subdomain Management System as described in Issue #1738. It allows users to register and manage their own Pollinations subdomains, connecting them directly to GitHub Pages repositories. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR implements a comprehensive subdomain management system, but there are several issues that need to be addressed:
Critical Issues
- Module System Mismatch: The MCP tools use CommonJS syntax but the package is configured as ES modules, causing runtime errors
- Subdomain Validation Bug: The regex incorrectly rejects valid 2-character subdomains like "ab" while accepting single characters
Security Concerns
- Missing Reserved Subdomain Protection: No validation against existing service subdomains (auth, image, text, etc.)
- No Repository Validation: Missing validation that GitHub repositories actually exist and are accessible
- Public Resolve Endpoint: Could enable subdomain enumeration attacks
Recommendations
- Fix the module system inconsistency by converting to ES modules
- Correct the subdomain validation regex and add reserved subdomain checks
- Add GitHub repository validation before allowing registration
- Consider adding rate limiting and authentication to the resolve endpoint
- Add more comprehensive error handling for GitHub API failures
The overall architecture and implementation approach is solid, but these issues should be resolved before merging.
| // Subdomain should be alphanumeric with hyphens, 3-63 characters | ||
| const subdomainRegex = /^[a-z0-9]([a-z0-9-]{1,61}[a-z0-9])?$/; | ||
| return subdomainRegex.test(subdomain); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a bug in this regex that incorrectly rejects valid 2-character subdomains. The optional group ([a-z0-9-]{1,61}[a-z0-9])? requires at least 3 characters total when present, so "ab" fails while "a" passes. Also missing protection against reserved subdomains.
| // Subdomain should be alphanumeric with hyphens, 3-63 characters | |
| const subdomainRegex = /^[a-z0-9]([a-z0-9-]{1,61}[a-z0-9])?$/; | |
| return subdomainRegex.test(subdomain); | |
| // Reserved subdomains that conflict with existing services | |
| const reservedSubdomains = new Set([ | |
| 'auth', 'image', 'text', 'api', 'www', 'app', 'admin', 'cdn', | |
| 'static', 'assets', 'blog', 'docs', 'help', 'support', 'status', | |
| 'mail', 'email', 'ftp', 'ssh', 'vpn', 'n8n', 'websim' | |
| ]); | |
| if (reservedSubdomains.has(subdomain.toLowerCase())) { | |
| return false; | |
| } | |
| // Subdomain should be alphanumeric with hyphens, 2-63 characters | |
| // Allow single chars or 2+ chars with proper start/end validation | |
| const subdomainRegex = /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/; | |
| return subdomainRegex.test(subdomain) && subdomain.length >= 2 && subdomain.length <= 63; |
| */ | ||
|
|
||
| // Import required modules | ||
| const { fetchWithAuth } = require('../utils/auth-utils'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file uses CommonJS syntax but the package.json has "type": "module", causing runtime errors.
| const { fetchWithAuth } = require('../utils/auth-utils'); | |
| import { fetchWithAuth } from '../utils/auth-utils.js'; |
| } | ||
|
|
||
| // Export all tools | ||
| module.exports = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to use ES module export syntax to match the package configuration.
| module.exports = { | |
| export { |
| let fetch; | ||
| try { | ||
| fetch = globalThis.fetch || require('node-fetch'); | ||
| } catch (e) { | ||
| // If node-fetch is not available, we'll use the global fetch | ||
| fetch = globalThis.fetch; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Convert to ES module import syntax.
| let fetch; | |
| try { | |
| fetch = globalThis.fetch || require('node-fetch'); | |
| } catch (e) { | |
| // If node-fetch is not available, we'll use the global fetch | |
| fetch = globalThis.fetch; | |
| } | |
| import fetch from 'node-fetch'; |
| } | ||
|
|
||
| // Export the utilities | ||
| module.exports = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Convert to ES module export syntax.
| module.exports = { | |
| export { |
| // For GitHub Pages source, repo is required | ||
| if (registration.source === 'github_pages' && !registration.repo) { | ||
| return createErrorResponse(400, 'GitHub repository is required for GitHub Pages source', corsHeaders); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing validation that the GitHub repository actually exists and is accessible. A malicious user could register subdomains pointing to non-existent or private repositories.
| /** | ||
| * Handle resolving a subdomain to its GitHub Pages repository | ||
| * This endpoint is public and doesn't require authentication | ||
| */ | ||
| export async function handleResolveSubdomain( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Making this endpoint public could enable subdomain enumeration attacks. Consider adding rate limiting or requiring some form of authentication/authorization.
- Fix subdomain validation regex to properly handle 2-character subdomains - Add reserved subdomain protection to prevent conflicts with existing services - Add GitHub repository validation to ensure repos exist and are accessible - Add basic rate limiting and enumeration protection to public resolve endpoint - Improve error handling and validation throughout the subdomain management system Addresses review comments: - Fixes regex bug that rejected valid 2-character subdomains - Prevents registration of reserved subdomains (auth, api, www, etc.) - Validates GitHub repositories exist and are public before registration - Adds delay and validation to resolve endpoint to prevent enumeration attacks
Overview
This PR implements a User Subdomain Management System for Pollinations as described in Issue #1738. The system allows users to register and manage their own Pollinations subdomains (e.g.,
myproject.pollinations.ai), connecting them directly to GitHub Pages repositories.Changes
Database
subdomainstable with migration scriptAPI Endpoints
/github/subdomains/list- List user's subdomains/github/subdomains/register- Register a new subdomain/github/subdomains/update/:name- Update subdomain settings/github/subdomains/delete/:name- Delete a subdomain/github/subdomains/status/:name- Get subdomain status/github/subdomains/resolve- Resolve subdomain to GitHub repositoryMCP Tools
githubListSubdomains- List user's subdomainsgithubRegisterSubdomain- Register a new subdomaingithubUpdateSubdomain- Update subdomain settingsgithubDeleteSubdomain- Delete a subdomaingithubGetSubdomainStatus- Get subdomain statusImplementation Details
The implementation follows the "thin proxy" design principle, where the Pollinations service acts as a lightweight intermediary between the user and GitHub Pages. The system:
Security & Validation
✅ Addressed Review Feedback:
Testing
The implementation includes validation for:
Related Issues
Closes #1738
This builds upon the GitHub authentication system developed in #1737, allowing users to manage their entire Pollinations presence in one place.