Security Best Practices

Protect your API keys and data when using WebLinq.

API Key Security

Never expose API keys in client-side code, logs, or public repositories

Environment Variables

Store API keys securely:
# .env file
WEBLINQ_API_KEY=your_api_key_here
// Always use environment variables
const response = await fetch('https://api.weblinq.dev/v1/web/markdown', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.WEBLINQ_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ url }),
});
Add .env to your .gitignore file

Key Rotation

Regularly rotate your API keys:
  1. Generate new key in dashboard
  2. Update your applications
  3. Test thoroughly
  4. Delete old key

Request Validation

URL Validation

Always validate URLs before making requests:
function validateUrl(url) {
  try {
    const parsed = new URL(url);

    // Only allow HTTP/HTTPS
    if (!['http:', 'https:'].includes(parsed.protocol)) {
      throw new Error('Invalid protocol');
    }

    // Block private networks
    const hostname = parsed.hostname;
    if (
      hostname === 'localhost' ||
      hostname.startsWith('127.') ||
      hostname.startsWith('192.168.') ||
      hostname.startsWith('10.') ||
      hostname.startsWith('172.')
    ) {
      throw new Error('Private networks not allowed');
    }

    return true;
  } catch (error) {
    throw new Error(`Invalid URL: ${error.message}`);
  }
}

Input Sanitization

Sanitize user inputs before processing:
function sanitizeInput(input) {
  // Remove potentially harmful characters
  return input
    .replace(/[<>]/g, '') // Remove HTML brackets
    .replace(/javascript:/gi, '') // Remove javascript: protocol
    .replace(/data:/gi, '') // Remove data: protocol
    .trim()
    .substring(0, 2000); // Limit length
}

Response Handling

Secure Content Processing

Validate API responses before using them:
function validateResponse(response) {
  // Check response structure
  if (!response.success) {
    throw new Error(response.error?.message || 'API request failed');
  }

  // Validate data exists
  if (!response.data) {
    throw new Error('No data in response');
  }

  return response.data;
}

// Usage
const response = await makeAPIRequest(url);
const safeData = validateResponse(response);

Content Filtering

Filter potentially malicious content:
function filterContent(content) {
  const suspiciousPatterns = [
    /<script[^>]*>/gi,
    /javascript:/gi,
    /on\w+\s*=/gi, // Event handlers like onclick=
    /<iframe[^>]*>/gi,
  ];

  for (const pattern of suspiciousPatterns) {
    if (pattern.test(content)) {
      console.warn('Suspicious content detected');
      content = content.replace(pattern, '');
    }
  }

  return content;
}

Error Handling

Never expose sensitive information in error messages:
async function safeAPICall(url) {
  try {
    validateUrl(url);

    const response = await fetch('https://api.weblinq.dev/v1/web/markdown', {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${process.env.WEBLINQ_API_KEY}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ url }),
    });

    const data = await response.json();
    return validateResponse(data);
  } catch (error) {
    // Log detailed error for debugging
    console.error('API call failed:', error);

    // Return safe error message to user
    throw new Error('Failed to process request');
  }
}

Access Control

Server-Side Proxy

Never call WebLinq API directly from client-side code:
// ❌ NEVER do this in client-side code
// fetch('https://api.weblinq.dev/v1/web/markdown', {
//   headers: { 'Authorization': 'Bearer ' + API_KEY }
// });

// ✅ Create a server-side proxy instead
app.post('/api/extract-content', async (req, res) => {
  const { url } = req.body;

  try {
    validateUrl(url);
    const result = await callWebLinqAPI(url);
    res.json(result);
  } catch (error) {
    res.status(500).json({ error: 'Processing failed' });
  }
});

Rate Limiting

Implement request rate limiting in your application:
const rateLimit = require('express-rate-limit');

const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 10, // limit each IP to 10 requests per windowMs
  message: 'Too many requests from this IP',
});

app.use('/api/extract-content', limiter);

Security Checklist

1

Secure API Keys

Store in environment variables, never in code
2

Validate Inputs

Check URLs and sanitize all user inputs
3

Use Server-Side Proxy

Never expose API keys to client-side code
4

Implement Rate Limiting

Protect your endpoints from abuse
5

Monitor Usage

Track API usage and watch for anomalies
6

Regular Key Rotation

Rotate API keys periodically