Skip to content

Conversation

@voodoohop
Copy link
Member

@voodoohop voodoohop commented Jul 3, 2025

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

  • Added new subdomains table with migration script
  • Implemented database functions for CRUD operations on subdomains

API Endpoints

  • Added new endpoints for subdomain management:
    • /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 repository

MCP Tools

  • Added MCP tools for AI-assisted subdomain management:
    • githubListSubdomains - List user's subdomains
    • githubRegisterSubdomain - Register a new subdomain
    • githubUpdateSubdomain - Update subdomain settings
    • githubDeleteSubdomain - Delete a subdomain
    • githubGetSubdomainStatus - Get subdomain status

Implementation 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:

  1. Stores subdomain registrations in the database
  2. Validates subdomain names and GitHub repository connections
  3. Provides a self-service API for users to manage their subdomains
  4. Includes MCP tools for AI-assisted management

Security & Validation

Addressed Review Feedback:

  • Fixed subdomain validation regex - Now properly handles 2-character subdomains and includes length validation
  • Added reserved subdomain protection - Prevents registration of reserved names (auth, api, www, etc.)
  • GitHub repository validation - Validates that repositories exist and are public before registration
  • Rate limiting for public endpoints - Added enumeration protection to the resolve endpoint
  • Enhanced error handling - Improved validation and error messages throughout

Testing

The implementation includes validation for:

  • Subdomain name format (alphanumeric with hyphens, 2-63 characters)
  • Reserved subdomain protection
  • GitHub repository existence and accessibility
  • Required fields for different source types
  • Authentication and authorization for all endpoints
  • Proper error handling and response formatting

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.

@netlify
Copy link

netlify bot commented Jul 3, 2025

Deploy Preview for pollinations canceled.

Name Link
🔨 Latest commit 114e37c
🔍 Latest deploy log https://app.netlify.com/projects/pollinations/deploys/6865f4afbb3f5f00088ac565

@netlify
Copy link

netlify bot commented Jul 3, 2025

Deploy Preview for pollinations-react-hooks-docs canceled.

Name Link
🔨 Latest commit 114e37c
🔍 Latest deploy log https://app.netlify.com/projects/pollinations-react-hooks-docs/deploys/6865f4afbb3f5f00088ac569

@mentatbot
Copy link
Contributor

mentatbot bot commented Jul 3, 2025

I'm getting to work. See my steps and track my cost here.

  • Wake on any new activity.
    I always see new activity while actively working. When paused, I'll only respond when tagged unless this box is checked. Learn more about triggers.

Copy link
Member Author

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.

Copy link
Contributor

@mentatbot mentatbot bot left a 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

  1. Module System Mismatch: The MCP tools use CommonJS syntax but the package is configured as ES modules, causing runtime errors
  2. Subdomain Validation Bug: The regex incorrectly rejects valid 2-character subdomains like "ab" while accepting single characters

Security Concerns

  1. Missing Reserved Subdomain Protection: No validation against existing service subdomains (auth, image, text, etc.)
  2. No Repository Validation: Missing validation that GitHub repositories actually exist and are accessible
  3. 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.

Comment on lines 278 to 280
// 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);
Copy link
Contributor

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.

Suggested change
// 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');
Copy link
Contributor

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.

Suggested change
const { fetchWithAuth } = require('../utils/auth-utils');
import { fetchWithAuth } from '../utils/auth-utils.js';

}

// Export all tools
module.exports = {
Copy link
Contributor

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.

Suggested change
module.exports = {
export {

Comment on lines +9 to +15
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;
}
Copy link
Contributor

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.

Suggested change
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 = {
Copy link
Contributor

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.

Suggested change
module.exports = {
export {

Comment on lines +86 to +89
// 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);
}
Copy link
Contributor

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.

Comment on lines 237 to 241
/**
* Handle resolving a subdomain to its GitHub Pages repository
* This endpoint is public and doesn't require authentication
*/
export async function handleResolveSubdomain(
Copy link
Contributor

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
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.

Create User Subdomain Management System for Pollinations

3 participants