SheetLink takes security and privacy seriously. This document outlines our security measures, reporting procedures, and best practices.
| Version | Supported |
|---|---|
| Latest | ✅ |
| < Latest | ❌ |
We only support the latest version. Please always use the most recent release.
All uploaded files are validated against known Excel file signatures:
- XLSX:
50 4B 03 04(ZIP/PK format) - XLS:
D0 CF 11 E0 A1 B1 1A E1(OLE2 format)
Files with invalid signatures are rejected immediately.
// Example validation in LinkExtractorService.cs:40-86
private void ValidateExcelFile(Stream fileStream)
{
// Magic bytes check prevents malicious file uploads
// Even if renamed, non-Excel files are detected
}- Default Maximum: 10MB
- Configurable: via
appsettings.json - Prevents: DoS attacks via large file uploads
Empty files (0 bytes) are rejected with clear error messages.
Protection Against: DoS attacks, brute force, abuse
Implementation: ASP.NET Core RateLimiter middleware
Default Configuration:
- 100 requests per minute per IP address
- Algorithm: Fixed Window
- Response: HTTP 429 (Too Many Requests)
Configuration:
{
"ExcelProcessing": {
"RateLimitPerMinute": 100
}
}Location: Program.cs:25-40
All HTTP responses include comprehensive security headers:
Content-Security-Policy:
default-src 'self';
script-src 'self' 'unsafe-inline' 'unsafe-eval'; // Blazor requirement
style-src 'self' 'unsafe-inline'; // Blazor requirement
img-src 'self' data:;
font-src 'self';
connect-src 'self' wss: ws:; // SignalR WebSocket
frame-ancestors 'none'; // Prevent clickjacking
base-uri 'self';
form-action 'self';
Note: unsafe-eval and unsafe-inline are required for Blazor Server to function. This is a framework requirement, not a security weakness.
X-Content-Type-Options: nosniff // Prevent MIME sniffing
X-Frame-Options: DENY // Prevent clickjacking
X-XSS-Protection: 1; mode=block // Enable XSS protection
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: geolocation=(), microphone=(), camera=()
Location: Program.cs:46-68
All URLs extracted or merged are validated and sanitized:
- Protocol Enforcement: Only
http,https,mailtoallowed - Length Limit: 2000 characters (Excel limit)
- Format Validation: Must be valid URI
- Automatic Protocol: Adds
https://if missing
// Location: LinkExtractorService.cs:881-918
private static string? SanitizeUrl(string? url)
{
// Prevents XSS, injection attacks via malicious URLs
}Rejected URLs:
javascript:alert('xss')file:///etc/passwddata:text/html,<script>...</script>- URLs > 2000 characters
Production: Only sheetlink.hyunjo.uk is allowed
{
"AllowedHosts": "sheetlink.hyunjo.uk"
}Purpose: Prevents host header injection attacks
- All processing happens in-memory
- Files are NEVER saved to disk
- MemoryStreams are disposed after processing
- No temporary files created
- No cookies (except Blazor session)
- No analytics tracking
- No user accounts
- No IP logging (except rate limiting)
- Open Source: GitHub Repository
- Transparent: All code is public and auditable
- Review
LinkExtractorService.csfor proof of in-memory processing
| Library | Version | License | Security |
|---|---|---|---|
| DocumentFormat.OpenXml | 3.2.0 | MIT | ✅ Official Microsoft |
| ASP.NET Core | 10.0 | MIT | ✅ Microsoft-maintained |
Update Policy: Dependencies are kept up-to-date for security patches.
No Known Vulnerabilities: All dependencies are scanned regularly.
- Column Names: Validated against expected patterns
- Cell Values: String sanitization
- Hyperlink Relationships: Validated before creation
- No Macros: DocumentFormat.OpenXml does not execute macros
- File Upload: Limited to 10MB, validated file types
- Form Data: Blazor's built-in validation
- Antiforgery: Enabled by default (
app.UseAntiforgery())
No Information Disclosure:
- Generic error messages shown to users
- Detailed errors logged server-side only
- Stack traces never exposed
catch (Exception ex)
{
_logger.LogError(ex, "Unexpected error"); // Server-side only
result.ErrorMessage = "Error processing file: {ex.Message}"; // Generic message
}Production Deployment:
- Cloudflare Tunnel: Automatic TLS termination
- HSTS: Enabled in production (
app.UseHsts()) - TLS 1.2+: Minimum version enforced
-
Only upload trusted Excel files
- This tool processes Excel files server-side
- Malicious files are rejected, but be cautious
-
Use HTTPS
- Always access via
https://sheetlink.hyunjo.uk - Never ignore SSL certificate warnings
- Always access via
-
Sensitive Data
- Files are processed in-memory and immediately discarded
- Still, avoid uploading files with sensitive personal data
-
Verify the Site
- Check the URL is exactly
sheetlink.hyunjo.uk - Look for the padlock icon (HTTPS)
- Check the URL is exactly
-
Update Regularly
git pull dotnet publish -c Release systemctl restart excellinkextractor
-
Configure Firewall
- Only expose necessary ports
- Use Cloudflare Tunnel or reverse proxy
-
Set Strong AllowedHosts
{ "AllowedHosts": "your-domain.com" } -
Monitor Logs
- Check for unusual activity
- Watch for failed validations
- Review rate limit hits
-
Adjust Rate Limits
{ "ExcelProcessing": { "RateLimitPerMinute": 50 // Lower if needed } }
If you discover a security vulnerability, please report it responsibly:
- DO NOT open a public GitHub issue
- DO email the maintainer directly: [Create a security advisory on GitHub]
- Include:
- Description of the vulnerability
- Steps to reproduce
- Potential impact
- Suggested fix (if any)
- Initial Response: Within 48 hours
- Status Update: Within 7 days
- Fix Timeline: Depends on severity
- Critical: 24-72 hours
- High: 1-2 weeks
- Medium: 2-4 weeks
- Low: Next release
- We will acknowledge your report within 48 hours
- We will provide an estimated fix timeline
- We will notify you when the fix is deployed
- We will credit you in the release notes (if desired)
- Coordinated Disclosure: Please wait for our fix before public disclosure
- HTTPS enabled (Cloudflare Tunnel or similar)
- AllowedHosts configured correctly
- Rate limiting configured appropriately
- Logs monitored regularly
- Dependencies updated monthly
- Security headers verified (
curl -I) - File size limits appropriate for your use case
- Backups configured (if needed)
- All inputs validated
- Exceptions properly caught
- No sensitive data in logs
- SQL injection N/A (no database)
- XSS prevention (URL sanitization)
- CSRF protection (Antiforgery enabled)
- All dependencies up-to-date
- Unit tests passing
- Code reviewed before each release
- Security headers validated
- Dependencies scanned for vulnerabilities
- Open source (community review)
- Lighthouse security audit: Best Practices 78/100
⚠️ AdSense cookies (user choice, not our code)- ✅ HTTPS, CSP, security headers
-
Blazor Server Limitations
- Requires
unsafe-evalin CSP (Blazor framework requirement) - Persistent SignalR connection (can be targeted for DoS)
- Requires
-
In-Memory Processing
- Files limited by available RAM
- Large files (>10MB) rejected by default
-
Single-Server Deployment
- No distributed rate limiting
- Server restart clears rate limit counters
- ✅ No personal data collected
- ✅ No cookies (except session)
- ✅ Files immediately discarded
- ✅ Privacy policy in FAQ
- Files: 0 seconds (processed in-memory)
- Logs: Server logs rotated per systemd configuration
- User Data: None collected
- GitHub Issues: https://github.com/HyunjoJung/sheetlink/issues
- Security Advisories: https://github.com/HyunjoJung/sheetlink/security/advisories