6 Commits

Author SHA1 Message Date
Axel Nicolas
4f03c5876f Merge pull request #44 from MasterAcnolo/sync
Sync
2026-07-26 15:15:52 +02:00
MasterAcnolo
a5f05f32af fix: readme missing items and [!TIP] 2026-07-26 11:21:23 +02:00
MasterAcnolo
0d1b1e4919 refactor: security.md 2026-07-26 09:37:39 +02:00
MasterAcnolo
0e77a94ec7 feat: enhance logger by displaying systeminfo at start of the app 2026-07-26 09:37:27 +02:00
MasterAcnolo
7f481d20b2 sync: update dependencies and this is ready for windows 2026-07-25 12:49:36 +02:00
MasterAcnolo
1ff32ca021 sync: to work on windows 2026-07-25 11:32:48 +02:00
8 changed files with 1642 additions and 940 deletions

View File

@@ -134,6 +134,7 @@ sudo apt install ./freedom-loader_1.x.x_amd64.deb
#### RPM (Fedora/RHEL/openSUSE, without Copr)
```bash
# Download the latest .rpm from the Releases page, then:
sudo dnf install ./freedom-loader-1.x.y.x86_64.rpm
```
@@ -162,7 +163,8 @@ freedom-loader
## Usage
> [!TIP] On Linux, you can start Freedom Loader using `freedom-loader` command
> [!TIP]
> On Linux, you can start Freedom Loader using `freedom-loader` command
### Basic Download

View File

@@ -2,15 +2,14 @@
## Supported Versions
We actively maintain and provide security updates for the following versions of Freedom Loader:
Freedom Loader follows a **latest-only** support model. Security fixes are applied to the current release only — no backports to older versions.
| Version | Supported |
|---------|--------------------|
| 1.4.x | :white_check_mark: |
| 1.3.x | :white_check_mark: |
| < 1.3.0 | :x: |
| ------------- | ------------------ |
| Latest stable | :white_check_mark: |
| Older versions | :x: |
**Note**: We recommend always using the latest version to benefit from the most recent security patches and features.
I recommend always running the latest version. The built-in auto-updater will notify you when a new release is available. Older versions will not receive security patches regardless of severity.
## Reporting a Vulnerability
@@ -32,37 +31,40 @@ Instead, please report security issues privately by:
### What to Expect
- **Acknowledgment**: We will acknowledge receipt of your report within 48 hours
- **Assessment**: We will assess the vulnerability and determine its severity
- **Updates**: We will keep you informed of our progress
- **Resolution**: We aim to release a fix within 7-14 days for critical vulnerabilities
- **Credit**: We will credit you in the release notes (unless you prefer to remain anonymous)
- **Acknowledgment**: I will acknowledge receipt of your report within 48 hours
- **Assessment**: I will assess the vulnerability and determine its severity
- **Updates**: I will keep you informed of our progress
- **Resolution**: I aim to release a fix within 7-14 days for critical vulnerabilities
- **Credit**: I will credit you in the release notes (unless you prefer to remain anonymous)
## Security Best Practices for Users
When using Freedom Loader, we recommend:
When using Freedom Loader, I recommend:
### General Security
- **Keep Updated**: Always use the latest version of Freedom Loader
- **Official Sources**: Download only from official releases on [GitHub](https://github.com/MasterAcnolo/Freedom-Loader/releases)
- **Verify Downloads**: Check that installers are properly signed (Windows SmartScreen may show warnings for new releases)
- **Keep Updated**: Always use the latest version of Freedom Loader — older versions receive no security patches
- **Official Sources**: Download only from official sources:
- [GitHub Releases](https://github.com/MasterAcnolo/Freedom-Loader/releases)
- [Fedora COPR](https://copr.fedorainfracloud.org/coprs/masteracnolo/freedom-loader/)
<!-- - [Snap Store](https://snapcraft.io/freedom-loader) -->
- **Verify Downloads**: Check that installers are from one of the above sources
- **Antivirus**: Keep your antivirus software up to date
### Configuration Security
- **Download Path**: Only set download paths within your user directory (`C:\Users\[USERNAME]\...`)
- **Cookies**: Be aware that Firefox cookies are used for authenticationkeep Firefox secure
- **Logs**: Logs may contain sensitive informationavoid sharing them publicly without review
- **Download Path**: Only set download paths within your user directory
- **Cookies**: Be aware that Firefox cookies are used for authenticationkeep Firefox secure
- **Logs**: Logs may contain sensitive information such as URLs or local paths — avoid sharing them publicly without review
### Privacy Considerations
Freedom Loader respects your privacy:
- **No Data Collection**: We don't collect, store, or transmit your personal data
- **No Data Collection**: I don't collect, store, or transmit your personal data
- **No Telemetry**: No usage tracking or analytics
- **Local Operation**: All downloads are processed locally on your machine
- **Optional Features**: Discord RPC is optional and can be disabled
- **Optional Features**: Discord RPC is optional and can be disabled in settings
## Known Security Considerations
@@ -71,16 +73,16 @@ Freedom Loader respects your privacy:
Freedom Loader accesses Firefox cookies to download protected content. This is:
- **By Design**: Required for age-restricted or member-only content
- **Local Only**: Cookies are read locally and never transmitted
- **User Controlled**: You can control what content you download
- **Local Only**: Cookies are read locally and never transmitted outside your machine
- **User Controlled**: You control what content you download
### Native Dependencies
Freedom Loader bundles native binaries:
Freedom Loader bundles the following official binaries:
- **yt-dlp**: Official builds from [yt-dlp/yt-dlp](https://github.com/yt-dlp/yt-dlp)
- **yt-dlp**: Official builds from [yt-dlp/yt-dlp](https://github.com/yt-dlp/yt-dlp) — auto-updated on each launch
- **FFmpeg**: Official builds from [FFmpeg.org](https://ffmpeg.org/)
- **Deno**: Official builds from [Deno.land](https://deno.land/)
- **Deno**: Official builds from [Deno.com](https://deno.com/)
These dependencies are verified and updated regularly.
@@ -91,13 +93,13 @@ New releases may trigger Windows Defender warnings because:
- The application is not yet widely distributed
- Code signing certificates are expensive for open-source projects
This is expected behavior for new releases. The warning will decrease as more users download the software.
This is expected behavior for new releases and will diminish as more users download the software.
## Vulnerability Disclosure Policy
### Our Commitment
We are committed to:
I am committed to:
- Responding promptly to security reports
- Working with security researchers to verify and address issues
@@ -107,9 +109,9 @@ We are committed to:
### Disclosure Timeline
1. **Day 0**: Vulnerability reported privately
2. **Day 1-2**: Acknowledgment sent to reporter
3. **Day 3-7**: Vulnerability assessed and fix developed
4. **Day 7-14**: Fix released (critical vulnerabilities prioritized)
2. **Day 12**: Acknowledgment sent to reporter
3. **Day 37**: Vulnerability assessed and fix developed
4. **Day 714**: Fix released (critical vulnerabilities prioritized)
5. **Day 14+**: Public disclosure (coordinated with reporter)
### Scope
@@ -129,16 +131,16 @@ The following are generally not considered security vulnerabilities:
- Issues requiring physical access to the user's machine
- Social engineering attacks
- Denial of service against third-party services
- Issues in third-party dependencies (report to upstream projects)
- Missing security headers on local HTTP server (no remote access)
- Issues in third-party dependencies (report to upstream projects directly)
- Missing security headers on the local HTTP server (not exposed remotely)
## Security Updates
Security updates are released as:
- **Patch Releases**: For critical security fixes (e.g., 1.4.1 1.4.2)
- **Patch Releases**: For critical security fixes (e.g., 1.6.0 → 1.6.1)
- **Automatic Updates**: Users are notified via the built-in update system
- **Release Notes**: Security fixes are clearly marked in changelog
- **Release Notes**: Security fixes are clearly marked in the changelog
## Additional Resources
@@ -150,6 +152,7 @@ Security updates are released as:
For security-related questions or concerns:
- **Email**: masteracnolo25@gmail.com
- **GitHub**: [@MasterAcnolo](https://github.com/MasterAcnolo)
---

View File

@@ -37,7 +37,7 @@ app.setAppUserModelId("com.masteracnolo.freedomloader");
/**
* Load the app dependencies for hardware choice
*/
const { logger, logSessionStart, logSessionEnd } = require("./server/logger");
const { logger, logSessionStart, logSessionEnd, logDir } = require("./server/logger");
const { configFeatures } = require("./config");
/**
@@ -79,7 +79,7 @@ const { updateYtDlp } = require("./app/ytDlpUpdater");
const { createMainWindow, getMainWindow } = require("./app/windowManager");
const { registerIpcHandlers } = require("./app/ipcHandlers");
const { createSplashWindow, closeSplashWindow, setSplashProgress } = require("./app/splashManager");
const { userThemesPath, initUserThemes, isWindows } = require("./server/helpers/path.helpers");
const { userThemesPath, initUserThemes, isWindows, validateBinaries, defaultDownloadFolder } = require("./server/helpers/path.helpers");
/**
@@ -99,7 +99,7 @@ app.on("second-instance", () => {
});
app.whenReady().then(async () => {
logSessionStart();
logSessionStart(logDir, defaultDownloadFolder);
createSplashWindow();
@@ -117,6 +117,8 @@ app.whenReady().then(async () => {
setSplashProgress(2); // Loading themes
validateBinaries();
initUserThemes();
await initThemes(userThemesPath);

2203
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -27,9 +27,9 @@
"winston-daily-rotate-file": "^5.0.0"
},
"devDependencies": {
"@electron/devtron": "^2.1.1",
"electron": "^41.2.0",
"electron-builder": "^26.8.1",
"@electron/devtron": "^2.1.1"
"electron-builder": "^25.1.8"
},
"build": {
"appId": "com.masteracnolo.freedomloader",
@@ -53,22 +53,52 @@
},
"asar": true,
"extraResources": [
{ "from": "theme", "to": "theme" },
{ "from": "build/confirm-icon.png", "to": "confirm-icon.png" },
{ "from": "build/banner.bmp", "to": "banner.bmp" },
{ "from": "build/banner.png", "to": "banner.png" },
{ "from": "build/error.png", "to": "error.png" },
{ "from": "config/config.default.json", "to": "config/config.default.json" }
{
"from": "theme",
"to": "theme"
},
{
"from": "build/confirm-icon.png",
"to": "confirm-icon.png"
},
{
"from": "build/banner.bmp",
"to": "banner.bmp"
},
{
"from": "build/banner.png",
"to": "banner.png"
},
{
"from": "build/error.png",
"to": "error.png"
},
{
"from": "config/config.default.json",
"to": "config/config.default.json"
}
],
"win": {
"target": "nsis",
"icon": "build/app-icon.ico",
"artifactName": "${productName}-Setup-${version}.${ext}",
"extraResources": [
{ "from": "resources/binaries/win-32/yt-dlp.exe", "to": "binaries/yt-dlp.exe" },
{ "from": "resources/binaries/win-32/ffmpeg.exe", "to": "binaries/ffmpeg.exe" },
{ "from": "resources/binaries/win-32/ffprobe.exe", "to": "binaries/ffprobe.exe" },
{ "from": "resources/binaries/win-32/deno.exe", "to": "binaries/deno.exe" }
{
"from": "resources/binaries/win-32/yt-dlp.exe",
"to": "binaries/yt-dlp.exe"
},
{
"from": "resources/binaries/win-32/ffmpeg.exe",
"to": "binaries/ffmpeg.exe"
},
{
"from": "resources/binaries/win-32/ffprobe.exe",
"to": "binaries/ffprobe.exe"
},
{
"from": "resources/binaries/win-32/deno.exe",
"to": "binaries/deno.exe"
}
]
},
"nsis": {
@@ -83,14 +113,31 @@
"shortcutName": "Freedom Loader"
},
"linux": {
"target": ["AppImage", "deb","rpm", "snap"],
"target": [
"AppImage",
"deb",
"rpm",
"snap"
],
"category": "Utility",
"icon": "build/app-icon.png",
"extraResources": [
{ "from": "resources/binaries/linux/yt-dlp", "to": "binaries/yt-dlp" },
{ "from": "resources/binaries/linux/ffmpeg", "to": "binaries/ffmpeg" },
{ "from": "resources/binaries/linux/ffprobe", "to": "binaries/ffprobe" },
{ "from": "resources/binaries/linux/deno", "to": "binaries/deno" }
{
"from": "resources/binaries/linux/yt-dlp",
"to": "binaries/yt-dlp"
},
{
"from": "resources/binaries/linux/ffmpeg",
"to": "binaries/ffmpeg"
},
{
"from": "resources/binaries/linux/ffprobe",
"to": "binaries/ffprobe"
},
{
"from": "resources/binaries/linux/deno",
"to": "binaries/deno"
}
]
},
"deb": {

View File

@@ -172,22 +172,32 @@ function initUserThemes() {
for (const theme of defaultThemes) {
const srcPath = path.join(defaultThemesSourcePath, theme);
const destPath = path.join(userThemesPath, theme);
const srcIsFile = !fs.statSync(srcPath).isDirectory();
if (fs.existsSync(destPath)) {
const destIsDir = fs.statSync(destPath).isDirectory();
if (srcIsFile && destIsDir) {
getLogger().warn(`Corrupted theme entry: ${theme}, fixing...`);
fs.rmSync(destPath, { recursive: true, force: true });
if (!fs.existsSync(destPath)) {
try {
if (fs.statSync(srcPath).isDirectory()) {
copyDirectory(srcPath, destPath);
fs.chmodSync(destPath, 0o777);
} else {
continue;
}
}
try {
if (srcIsFile) {
fs.copyFileSync(srcPath, destPath);
fs.chmodSync(destPath, 0o666);
} else {
copyDirectory(srcPath, destPath);
fs.chmodSync(destPath, 0o777);
}
getLogger().info(`Copied default theme: ${theme}`);
} catch (copyErr) {
getLogger().warn(`Failed to copy theme ${theme}: ${copyErr.message}`);
}
}
}
} else {
getLogger().warn(`Default themes source path not found: ${defaultThemesSourcePath}`);
}
@@ -229,16 +239,23 @@ function copyDirectory(src, dest) {
}
// Runtime validation of critical binaries
if (!userYtDlp) {
getLogger().error("Missing yt-dlp binary");
}
// if (!userYtDlp) {
// getLogger().error("Missing yt-dlp binary");
// }
if (!ffmpegPath) {
getLogger().error("Missing ffmpeg binary");
}
// if (!ffmpegPath) {
// getLogger().error("Missing ffmpeg binary");
// }
if (!denoPath) {
getLogger().error("Missing deno binary");
// if (!denoPath) {
// getLogger().error("Missing deno binary");
// }
function validateBinaries() {
if (!userYtDlp) getLogger().error("Missing yt-dlp binary");
if (!ffmpegPath) getLogger().error("Missing ffmpeg binary");
if (!denoPath) getLogger().error("Missing deno binary");
}
/**
@@ -249,4 +266,4 @@ function getLogger() {
return require("../logger.js").logger;
}
module.exports = { userYtDlp, ffmpegPath, denoPath, iconPaths, binaryPaths, resourcesPath, defaultDownloadFolder, userThemesPath, initUserThemes, isWindows };
module.exports = { userYtDlp, ffmpegPath, denoPath, iconPaths, binaryPaths, resourcesPath, defaultDownloadFolder, userThemesPath, initUserThemes, isWindows, validateBinaries };

View File

@@ -5,6 +5,7 @@ const path = require("path");
const os = require("os");
const config = require("../config");
const {isWindows} = require("./helpers/path.helpers");
const { logSystemInfo } = require("./sysinfo");
// Logs folder in Windows
const logDir = isWindows ? path.join(os.homedir(), "AppData", "Local", "FreedomLoader", "logs") : path.join(process.env.XDG_DATA_HOME || path.join(os.homedir(), ".local", "share"), "FreedomLoader", "logs");
@@ -52,9 +53,10 @@ const logger = createLogger({
/**
* Start Log Session
*/
function logSessionStart() {
function logSessionStart(logDir, downloadPath) {
logger.info(`--- Starting session: ${new Date().toISOString()} ---`);
logger.info(`Application Version: ${config.version}`)
logSystemInfo(logger, logDir, downloadPath)
}
/**

142
server/sysinfo.js Normal file
View File

@@ -0,0 +1,142 @@
const os = require("os");
const fs = require("fs");
const { execSync } = require("child_process");
const { app } = require("electron");
/**
* Reads /etc/os-release to get the Linux distribution name
*/
function getLinuxDistro() {
try {
const content = fs.readFileSync("/etc/os-release", "utf-8");
const pretty = content.match(/^PRETTY_NAME="?(.+?)"?$/m);
if (pretty) return pretty[1];
const name = content.match(/^NAME="?(.+?)"?$/m);
return name ? name[1] : "Unknown Linux";
} catch {
return "Unknown Linux";
}
}
/**
* Reads the package-type file written by electron-builder
* to determine how the app was distributed (rpm, snap, AppImage, deb...)
*/
function getPackageType() {
try {
const pkgTypePath = require("path").join(process.resourcesPath, "package-type");
if (fs.existsSync(pkgTypePath)) {
return fs.readFileSync(pkgTypePath, "utf-8").trim();
}
} catch { /* ignore */ }
return "unknown";
}
/**
* Checks if Firefox is installed on the current platform
*/
function detectFirefox() {
const platform = process.platform;
if (platform === "win32") {
const paths = [
"C:\\Program Files\\Mozilla Firefox\\firefox.exe",
"C:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe",
`${process.env.LOCALAPPDATA}\\Mozilla Firefox\\firefox.exe`,
];
return paths.some(p => fs.existsSync(p));
}
if (platform === "linux") {
const paths = [
"/usr/bin/firefox",
"/usr/bin/firefox-esr",
"/usr/local/bin/firefox",
"/snap/bin/firefox",
"/var/lib/flatpak/exports/bin/org.mozilla.firefox",
`${os.homedir()}/.local/share/flatpak/exports/bin/org.mozilla.firefox`,
];
if (paths.some(p => fs.existsSync(p))) return true;
try { execSync("which firefox", { stdio: "ignore" }); return true; } catch { return false; }
}
return false;
}
/**
* Builds the system info object logged at startup
*
* @param {string} logDir - path to the log directory
* @param {string} downloadPath - current configured download path
*/
function getSystemInfo(logDir, downloadPath) {
const platform = process.platform;
const cpus = os.cpus();
const totalMem = (os.totalmem() / 1024 / 1024 / 1024).toFixed(1);
const freeMem = (os.freemem() / 1024 / 1024 / 1024).toFixed(1);
let platformLabel;
if (platform === "win32") {
platformLabel = `Windows (${os.release()})`;
} else if (platform === "linux") {
platformLabel = `Linux — ${getLinuxDistro()}`;
} else {
platformLabel = `${platform} ${os.release()} (unsupported)`;
}
const info = {
"Platform": platformLabel,
"Architecture": os.arch(),
"CPU": cpus.length ? `${cpus[0].model.trim()} (${cpus.length} cores)` : "Unknown",
"Memory": `${freeMem} GB free / ${totalMem} GB total`,
"Locale": app.getLocale(),
"Electron": process.versions.electron,
"Node": process.versions.node,
"Packaged": String(app.isPackaged),
"Package type": app.isPackaged ? getPackageType() : "dev",
"Firefox present": detectFirefox() ? "Yes" : "No — cookie features unavailable",
"Log directory": logDir,
"Download path": downloadPath,
};
// Linux-specific extras
if (platform === "linux") {
const sessionType = process.env.XDG_SESSION_TYPE || "unknown";
const waylandDisplay = process.env.WAYLAND_DISPLAY;
const x11Display = process.env.DISPLAY;
info["Display server"] = waylandDisplay
? `Wayland (${waylandDisplay})`
: x11Display
? `X11 (${x11Display})`
: sessionType !== "unknown"
? sessionType
: "unknown";
info["Desktop env"] = process.env.XDG_CURRENT_DESKTOP || process.env.DESKTOP_SESSION || "unknown";
}
return info;
}
/**
* Logs system info at application startup
*
* @param {object} logger - winston logger instance
* @param {string} logDir - path to the log directory
* @param {string} downloadPath - current configured download path
*/
function logSystemInfo(logger, logDir, downloadPath) {
const info = getSystemInfo(logDir, downloadPath);
const maxKeyLen = Math.max(...Object.keys(info).map(k => k.length));
logger.info("=".repeat(60));
logger.info("SYSTEM INFO");
logger.info("=".repeat(60));
for (const [key, val] of Object.entries(info)) {
logger.info(` ${key.padEnd(maxKeyLen)} : ${val}`);
}
logger.info("=".repeat(60));
}
module.exports = { logSystemInfo };