Security Guide
Best practices for secure implementation
Introduction
ts-ascii-engine processes user input and generates HTML output, which requires careful handling to maintain security in your applications. This guide covers the security measures implemented in the library and best practices for secure integration.
Built-in Security Protections
Charset Sanitization
Custom charset strings are automatically sanitized to remove dangerous characters:
-
Characters removed:
<,>,',",&,` - Prevents XSS via charset injection
- Automatic, no user action required
// Dangerous characters automatically removed
const generator = new AsciiGenerator({
charset: '<script>alert("XSS")</script>'
});
// Resulting charset: 'scriptalert("XSS")/script'
Dimension Limits
Maximum limits enforced to prevent memory exhaustion (DoS attacks):
- Max width/height: 10,000 characters
- Max total characters: 25,000,000 (5000×5000)
- Throws error if exceeded
// Throws error - exceeds maximum
const generator = new AsciiGenerator({
width: 1000000
});
// Error: Width exceeds maximum allowed (10000)
HTML Escaping
All character output is properly HTML-escaped:
-
Escapes:
&,<,>,",',` - Prevents XSS in HTML output
- Automatic for all conversions
Text Input Validation
Text-to-ASCII conversion has strict limits:
- Max text length: 10,000 characters
- Max font size: 1,000 pixels
- Font parameters validated against whitelist
CORS Error Handling
Clear error messages for cross-origin image issues:
- Detects CORS security errors
- Provides actionable error messages
- Guides users to proper CORS configuration
Array Bounds Checking
All pixel data access is bounds-checked:
- Prevents out-of-bounds array access
- Handles edge cases gracefully
- No buffer overflows possible
Security Best Practices
1. Sanitize Custom Charsets
Never pass user-controlled data directly as custom charsets:
Unsafe
const userCharset = prompt("Enter charset:");
const generator = new AsciiGenerator({
charset: userCharset
});
Safe
function isValidCharset(charset) {
return /^[\w\s\.,-_]+$/.test(charset)
&& charset.length <= 20;
}
const userCharset = prompt("Enter charset:");
if (isValidCharset(userCharset)) {
const generator = new AsciiGenerator({
charset: userCharset
});
}
2. Limit Input Dimensions
Set application-specific limits:
// Recommended approach
function createGenerator(userWidth) {
const MAX_WIDTH = 300; // Your application's limit
const safeWidth = Math.min(userWidth, MAX_WIDTH);
return new AsciiGenerator({ width: safeWidth });
}
| Use Case | Recommended Width | Rationale |
|---|---|---|
| Mobile thumbnails | 40-60 | Fast processing, low memory |
| Desktop displays | 80-120 | Good balance of quality and performance |
| High-quality images | 150-200 | Maximum detail for static images |
| Real-time video | 60-80 | Maintains 30+ FPS |
3. Use Content Security Policy (CSP)
Implement CSP headers when displaying HTML output:
<!-- Recommended CSP headers -->
<meta http-equiv="Content-Security-Policy"
content="default-src 'self'; style-src 'unsafe-inline'">
'unsafe-inline' is needed for
inline styles if using colored mode. For stricter CSP, use plain
text output instead.
// Strictest security - use text output
const result = generator.convertImage(img);
document.getElementById('output').textContent = result.text;
4. Handle CORS Properly
Always set crossOrigin for external images:
// Correct approach
async function loadExternalImage(url) {
return new Promise((resolve, reject) => {
const img = new Image();
img.crossOrigin = 'anonymous'; // Important!
img.onload = () => resolve(img);
img.onerror = reject;
img.src = url;
});
}
// Usage
try {
const img = await loadExternalImage('https://example.com/image.jpg');
const result = generator.convertImage(img);
} catch (error) {
console.error('Failed to load image:', error);
}
5. Validate Text Inputs
// Safe text conversion
function convertUserText(text) {
const MAX_LENGTH = 100;
const safeText = text.substring(0, MAX_LENGTH);
return generator.convertText(safeText, {
fontSize: 48,
fontWeight: 'bold'
});
}
6. Whitelist Font Families
// Safe font selection
const ALLOWED_FONTS = [
'Arial',
'Helvetica',
'Times New Roman',
'Courier New'
];
function getSafeFont(userFont) {
return ALLOWED_FONTS.includes(userFont) ? userFont : 'Arial';
}
const result = generator.convertText('Hello', {
font: getSafeFont(userInput)
});
7. Implement Rate Limiting
// Debounce user input
import { debounce } from 'lodash';
const debouncedConvert = debounce((img) => {
const result = generator.convertImage(img);
updateDisplay(result.html);
}, 300);
inputElement.addEventListener('change', (e) => {
debouncedConvert(e.target.files[0]);
});
Complete Secure Implementation
Example: Secure ASCII Converter Class
import { AsciiGenerator, CharsetPreset } from 'ts-ascii-engine';
class SecureAsciiConverter {
private generator: AsciiGenerator;
private readonly MAX_WIDTH = 200;
private readonly MAX_TEXT_LENGTH = 500;
private readonly ALLOWED_FONTS = ['Arial', 'Courier New', 'Georgia'];
constructor() {
// Use preset, not user input
this.generator = new AsciiGenerator({
charset: CharsetPreset.STANDARD,
width: this.MAX_WIDTH,
colored: true
});
}
async convertImageSafely(imageUrl: string): Promise<string> {
// Validate URL
if (!this.isValidImageUrl(imageUrl)) {
throw new Error('Invalid image URL');
}
// Load with CORS
const img = await this.loadImageWithCORS(imageUrl);
// Convert
const result = this.generator.convertImage(img);
return result.html;
}
convertTextSafely(text: string, font: string = 'Arial'): string {
// Sanitize inputs
const safeText = text.substring(0, this.MAX_TEXT_LENGTH);
const safeFont = this.ALLOWED_FONTS.includes(font) ? font : 'Arial';
// Convert
const result = this.generator.convertText(safeText, {
font: safeFont,
fontSize: 48,
fontWeight: 'bold'
});
return result.html;
}
private async loadImageWithCORS(url: string): Promise<HTMLImageElement> {
return new Promise((resolve, reject) => {
const img = new Image();
img.crossOrigin = 'anonymous';
img.onload = () => resolve(img);
img.onerror = () => reject(new Error('Failed to load image'));
img.src = url;
});
}
private isValidImageUrl(url: string): boolean {
try {
const parsed = new URL(url);
return ['http:', 'https:'].includes(parsed.protocol);
} catch {
return false;
}
}
}
// Usage
const converter = new SecureAsciiConverter();
try {
const html = await converter.convertImageSafely(userProvidedUrl);
document.getElementById('output').innerHTML = html;
} catch (error) {
console.error('Conversion failed:', error);
}
Security Checklist
Before Deploying to Production
Threat Model
Protected Against
- XSS via charset injection
- DoS via memory exhaustion
- HTML injection
- Out-of-bounds array access
- CSS injection
Cannot Protect Against
- Server-side attacks (client-side library)
- Network attacks during image loading
- Social engineering
- Application-level logic flaws
Vulnerability Reporting
How to Report
- Do not open a public issue
- Email details to: [your-security-email@example.com]
-
Include:
- Description of the vulnerability
- Steps to reproduce
- Potential impact
- Suggested fix (if any)
- We will respond within 48 hours
Security Updates
# Check for updates
npm outdated ts-ascii-engine
# Update to latest version
npm update ts-ascii-engine
Consider using automated dependency management tools: