Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions build/scripts/linux/build-avalonia-packages.sh.orig
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#!/usr/bin/env bash
set -euo pipefail

REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." BASH_SOURCE[0]}")/../../.." BASH_SOURCE[0]}")/../.." && pwdBASH_SOURCE[0]}")/../.." && pwd pwd)BASH_SOURCE[0]}")/../.." && pwd) pwd)"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 HIGH RISK

This file is a temporary artifact from a failed merge conflict resolution and should be removed. Furthermore, line 4 contains malformed and garbled syntax (repeated BASH_SOURCE variables) that would cause execution errors if this script were used as a template.

PROJECT_PATH="$REPO_ROOT/src/GregModmanager.Avalonia/GregModmanager.Avalonia.csproj"
OUTPUT_ROOT="${1:-$REPO_ROOT/artifacts/avalonia-linux}"
VERSION="${2:-1.1.0}"
IS_PRE="${3:-false}"
RID="linux-x64"

PRE_SUFFIX=""
if [ "$IS_PRE" = "true" ] || [ "$IS_PRE" = "1" ]; then
PRE_SUFFIX="-pre"
fi

PUBLISH_DIR="$OUTPUT_ROOT/publish"
PKG_DIR="$OUTPUT_ROOT/packages"
mkdir -p "$PUBLISH_DIR" "$PKG_DIR"

dotnet publish "$PROJECT_PATH" -c Release -r "$RID" --self-contained true -o "$PUBLISH_DIR"

tar -C "$PUBLISH_DIR" -czf "$PKG_DIR/gregModmanager-${VERSION}${PRE_SUFFIX}-Linux.tar.gz" .

NFP_CONFIG="$OUTPUT_ROOT/nfpm.yaml"
cat > "$NFP_CONFIG" <<EOF
name: gregmodmanager
arch: amd64
platform: linux
version: ${VERSION}
section: utils
priority: optional
maintainer: teamGreg <noreply@gregframework.eu>
description: gregModmanager desktop client built with Avalonia UI.
vendor: gregFramework
homepage: https://github.com/mleem97/gregModmanager
license: Proprietary
depends:
- libicu
contents:
- src: ${PUBLISH_DIR}/
dst: /opt/gregmodmanager/
- src: ${REPO_ROOT}/build/scripts/linux/gregmodmanager.desktop
dst: /usr/share/applications/gregmodmanager.desktop
file_info:
mode: 0644
- src: ${REPO_ROOT}/build/scripts/linux/gregmodmanager
dst: /usr/bin/gregmodmanager
file_info:
mode: 0755
EOF

build_nfpm() {
local packager="$1"
local target="$2"

if command -v nfpm >/dev/null 2>&1; then
nfpm package --packager "$packager" --config "$NFP_CONFIG" --target "$target"
return
fi

echo "nfpm not found in PATH. Install with: echo 'deb [trusted=yes] https://repo.goreleaser.com/apt/ /' | sudo tee /etc/apt/sources.list.d/goreleaser.list && sudo apt update && sudo apt install nfpm" >&2
exit 1
}

build_nfpm deb "$PKG_DIR/gregModmanager-${VERSION}${PRE_SUFFIX}-Linux.deb"
build_nfpm rpm "$PKG_DIR/gregModmanager-${VERSION}${PRE_SUFFIX}-Linux.rpm"
build_nfpm archlinux "$PKG_DIR/gregModmanager-${VERSION}${PRE_SUFFIX}-Linux.pkg.tar.zst"

echo "Artifacts ready in: $OUTPUT_ROOT"
11 changes: 11 additions & 0 deletions build/scripts/linux/build-avalonia-packages.sh.rej
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
--- build-avalonia-packages.sh

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 MEDIUM RISK

This is a patch reject file (.rej) created when a change cannot be applied cleanly. It should be removed from the repository before the PR is merged.

+++ build-avalonia-packages.sh
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
set -euo pipefail

-REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
+REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)"
PROJECT_PATH="$REPO_ROOT/src/GregModmanager.Avalonia/GregModmanager.Avalonia.csproj"
OUTPUT_ROOT="${1:-$REPO_ROOT/artifacts/avalonia-linux}"
VERSION="${2:-1.1.0}"
11 changes: 11 additions & 0 deletions patch.diff
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
--- build/scripts/linux/build-avalonia-packages.sh

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 MEDIUM RISK

This temporary patch.diff file appears to be a redundant artifact and should be removed from the commit.

+++ build/scripts/linux/build-avalonia-packages.sh
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
set -euo pipefail

-REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
+REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)"
PROJECT_PATH="$REPO_ROOT/src/GregModmanager.Avalonia/GregModmanager.Avalonia.csproj"
OUTPUT_ROOT="${1:-$REPO_ROOT/artifacts/avalonia-linux}"
VERSION="${2:-1.1.0}"
238 changes: 120 additions & 118 deletions src/GregModmanager.Core/Services/SafeProcess.cs
Original file line number Diff line number Diff line change
@@ -1,118 +1,120 @@
using System;
using System.Diagnostics;
using System.Threading.Tasks;

namespace GregModmanager.Services;

public static class SafeProcess
{
/// <summary>
/// Opens a URL in the default browser safely, ensuring only http and https schemes are allowed.
/// </summary>
public static Task OpenUrlAsync(string url)
{
if (string.IsNullOrWhiteSpace(url)) return Task.CompletedTask;

try
{
if (Uri.TryCreate(url, UriKind.Absolute, out var uri) &&
(uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps))
{
Process.Start(new ProcessStartInfo
{
FileName = uri.ToString(),
UseShellExecute = true
});
}
else
{
AppFileLog.Warn($"Blocked attempt to open insecure or invalid URL: {url}");
}
}
catch (Exception ex)
{
AppFileLog.Error($"Failed to open URL: {url}", ex);
}

return Task.CompletedTask;
}

/// <summary>
/// Opens a folder in the system's file explorer.
/// </summary>
public static void OpenFolder(string path)
{
if (string.IsNullOrWhiteSpace(path)) return;

try
{
if (OperatingSystem.IsWindows())
{
Process.Start(new ProcessStartInfo
{
FileName = "explorer.exe",
Arguments = $"\"{path}\"",
UseShellExecute = false
});
}
else
{
// For other OS, we might still need UseShellExecute for some scenarios,
// but we should be careful. MAUI doesn't have a direct "OpenFolder" that works everywhere.
Process.Start(new ProcessStartInfo
{
FileName = path,
UseShellExecute = true
});
}
}
catch (Exception ex)
{
AppFileLog.Error($"Failed to open folder: {path}", ex);
}
}

/// <summary>
/// Specifically for Windows, opens explorer and selects a file.
/// </summary>
public static void OpenExplorerAndSelect(string filePath)
{
if (!OperatingSystem.IsWindows() || string.IsNullOrWhiteSpace(filePath)) return;

try
{
Process.Start(new ProcessStartInfo
{
FileName = "explorer.exe",
Arguments = $"/select,\"{filePath}\"",
UseShellExecute = false
});
}
catch (Exception ex)
{
AppFileLog.Error($"Failed to open explorer and select: {filePath}", ex);
}
}

/// <summary>
/// Launches an executable with UseShellExecute = false.
/// </summary>
public static void LaunchApp(string exePath, string arguments = "")
{
if (string.IsNullOrWhiteSpace(exePath)) return;

try
{
Process.Start(new ProcessStartInfo
{
FileName = exePath,
Arguments = arguments,
UseShellExecute = false
});
}
catch (Exception ex)
{
AppFileLog.Error($"Failed to launch app: {exePath}", ex);
}
}
}
using System;
using System.Diagnostics;
using System.Threading.Tasks;

namespace GregModmanager.Services;

public static class SafeProcess
{
/// <summary>
/// Opens a URL in the default browser safely, ensuring only http and https schemes are allowed.
/// </summary>
public static Task OpenUrlAsync(string url)
{
if (string.IsNullOrWhiteSpace(url)) return Task.CompletedTask;

try
{
if (Uri.TryCreate(url, UriKind.Absolute, out var uri) &&
(uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps))
{
Process.Start(new ProcessStartInfo
{
FileName = uri.ToString(),
UseShellExecute = true
});
}
else
{
AppFileLog.Warn($"Blocked attempt to open insecure or invalid URL: {url}");
}
}
catch (Exception ex)
{
AppFileLog.Error($"Failed to open URL: {url}", ex);
}

return Task.CompletedTask;
}

/// <summary>
/// Opens a folder in the system's file explorer.
/// </summary>
public static void OpenFolder(string path)
{
if (string.IsNullOrWhiteSpace(path)) return;

try
{
if (OperatingSystem.IsWindows())
{
var psi = new ProcessStartInfo
{
FileName = "explorer.exe",
UseShellExecute = false
};
psi.ArgumentList.Add(path);
Process.Start(psi);

Check failure on line 57 in src/GregModmanager.Core/Services/SafeProcess.cs

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/GregModmanager.Core/Services/SafeProcess.cs#L57

OS command injection is a critical vulnerability that can lead to a full system compromise as it may allow an adversary to pass in arbitrary commands or arguments to be executed.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 HIGH RISK

Suggestion: To harden this method, validate that the input path is a well-formed local directory path and does not contain unauthorized characters. Consider resolving the path using Path.GetFullPath before adding it to psi.ArgumentList to ensure it points to the intended location.

}
else
{
// For other OS, we might still need UseShellExecute for some scenarios,
// but we should be careful. MAUI doesn't have a direct "OpenFolder" that works everywhere.
Process.Start(new ProcessStartInfo
{
FileName = path,
UseShellExecute = true
});
}
}
catch (Exception ex)
{
AppFileLog.Error($"Failed to open folder: {path}", ex);
}
}

/// <summary>
/// Specifically for Windows, opens explorer and selects a file.
/// </summary>
public static void OpenExplorerAndSelect(string filePath)
{
if (!OperatingSystem.IsWindows() || string.IsNullOrWhiteSpace(filePath)) return;

try
{
var psi = new ProcessStartInfo
{
FileName = "explorer.exe",
UseShellExecute = false
};
psi.ArgumentList.Add($"/select,{filePath}");
Process.Start(psi);
}
catch (Exception ex)
{
AppFileLog.Error($"Failed to open explorer and select: {filePath}", ex);
}
}

/// <summary>
/// Launches an executable with UseShellExecute = false.
/// </summary>
public static void LaunchApp(string exePath, string arguments = "")
{
if (string.IsNullOrWhiteSpace(exePath)) return;

try
{
Process.Start(new ProcessStartInfo
{
FileName = exePath,
Arguments = arguments,
UseShellExecute = false
});
}
catch (Exception ex)
{
AppFileLog.Error($"Failed to launch app: {exePath}", ex);
}
}
}
Loading