Security Model
FitFileViewer implements multiple security layers following Electron security best practices.
Security Overviewβ
Core Security Featuresβ
Context Isolationβ
Renderer JavaScript runs in an isolated context:
// main.js
const mainWindow = new BrowserWindow({
webPreferences: {
contextIsolation: true, // Separate contexts
nodeIntegration: false, // No Node in renderer
sandbox: true, // OS sandbox
preload: path.join(__dirname, 'preload.js')
}
});
Why Context Isolation?β
| Without | With |
|---|---|
| Renderer can access Node | Renderer isolated |
| Window object exposed | Window protected |
| Easy to exploit | Secure by default |
IPC Securityβ
Validated Channelsβ
Only specific, validated operations are exposed:
// preload.js
const validChannels = [
'dialog:open-fit-file',
'file:read',
'app:get-version'
];
contextBridge.exposeInMainWorld('electronAPI', {
openFile: () => ipcRenderer.invoke('dialog:open-fit-file'),
getVersion: () => ipcRenderer.invoke('app:get-version'),
// No arbitrary channel access
});
Input Validationβ
All inputs validated before processing:
// main.js
ipcMain.handle('file:read', async (event, filePath) => {
// Validate file path
if (!isValidFilePath(filePath)) {
throw new Error('Invalid file path');
}
// Validate file extension
if (!filePath.endsWith('.fit')) {
throw new Error('Invalid file type');
}
// Safe to proceed
return fs.promises.readFile(filePath);
});
File System Securityβ
Path Validationβ
function isValidFilePath(filePath) {
// Normalize path
const normalized = path.normalize(filePath);
// Prevent directory traversal
if (normalized.includes('..')) {
return false;
}
// Check file exists
if (!fs.existsSync(normalized)) {
return false;
}
return true;
}
File Type Restrictionsβ
Only FIT files are processed:
const allowedExtensions = ['.fit'];
function validateFileType(filePath) {
const ext = path.extname(filePath).toLowerCase();
return allowedExtensions.includes(ext);
}
Content Security Policyβ
CSP Headersβ
// Restrict content sources
const csp = [
"default-src 'self'",
"script-src 'self'",
"style-src 'self' 'unsafe-inline'",
"img-src 'self' data: https://*.tile.openstreetmap.org",
"connect-src 'self' https://*.tile.openstreetmap.org"
].join('; ');
What This Preventsβ
- β Inline script injection
- β External script loading
- β Unauthorized network requests
Navigation Securityβ
Prevent External Navigationβ
// main.js
mainWindow.webContents.on('will-navigate', (event, url) => {
// Only allow same-origin navigation
if (!url.startsWith('file://')) {
event.preventDefault();
}
});
mainWindow.webContents.setWindowOpenHandler(() => {
// Prevent new windows
return { action: 'deny' };
});
Data Privacyβ
Local Data Onlyβ
FitFileViewer processes all data locally:
- β FIT files stay on your computer
- β No data uploaded to servers
- β No telemetry or tracking
- β Map tiles cached locally
What's Storedβ
| Data | Location | Purpose |
|---|---|---|
| Recent files | User data dir | Quick access |
| Preferences | User data dir | Settings |
| Theme | Local storage | UI preference |
What's NOT Storedβ
- β FIT file contents
- β GPS coordinates
- β Personal information
Security Best Practicesβ
For Usersβ
-
Download from official sources
- GitHub releases only
- Verify file hashes
-
Keep updated
- Security patches in updates
- Enable auto-update
-
Be cautious with files
- Only open trusted FIT files
- Don't open files from unknown sources
For Developersβ
- Never disable security features
- Validate all inputs
- Use allowlists, not blocklists
- Keep dependencies updated
Reporting Security Issuesβ
Found a vulnerability? Please report responsibly:
- Don't open a public issue
- Do email:
20943337+Nick2bad4u@users.noreply.github.com - Include:
- Description of vulnerability
- Steps to reproduce
- Potential impact
Related: Architecture Overview