Compare commits

...

11 Commits

Author SHA1 Message Date
Carlos Polop
651dc9cd7d Force-copy TestPlatform framework for MSTest 2026-01-21 12:53:49 +01:00
Carlos Polop
0808fb7f1b Ensure MSTest adapter finds TestPlatform framework 2026-01-21 12:24:56 +01:00
Carlos Polop
c332fab519 Fix MSTest adapter dependency load 2026-01-21 11:55:35 +01:00
Carlos Polop
577dcc9964 Fix MSTest framework copy-local for CI 2026-01-21 11:27:00 +01:00
Carlos Polop
b591f3d524 Fix winPEAS argument parsing tests 2026-01-21 10:57:32 +01:00
Carlos Polop
b3ac8c6d22 Stabilize winPEAS MSBuild in CI 2026-01-21 01:47:37 +01:00
Carlos Polop
83580fcd8a Re-enable winPEAS tests and add linPEAS builder checks 2026-01-21 01:15:38 +01:00
Carlos Polop
ab3a5899de Gate codex fixer job on PR author 2026-01-21 01:04:06 +01:00
Carlos Polop
0fac664048 Fix winPEAS build break in Program.Main 2026-01-21 00:32:09 +01:00
SirBroccoli
db30e3bd7d Fix Browser_profiles module ID casing (#576) 2026-01-20 23:54:30 +01:00
SirBroccoli
7ad87a85e6 Use PAT for fixer pushes and limit to one attempt (#575)
* Test CI failure flow

* Use PAT for fixer pushes and run only once per PR
2026-01-20 23:54:19 +01:00
8 changed files with 184 additions and 33 deletions

View File

@@ -48,23 +48,23 @@ jobs:
# build
- name: run MSBuild
run: msbuild $env:Solution_Path
run: msbuild $env:Solution_Path /p:Configuration=$env:Configuration /p:UseSharedCompilation=false
# Execute all unit tests in the solution
#- name: Execute unit tests
# run: dotnet test $env:Solution_Path
- name: Execute unit tests
run: dotnet test $env:Solution_Path --configuration $env:Configuration
# Build & update all versions
- name: Build all versions
run: |
echo "build x64"
msbuild -m $env:Solution_Path /t:Rebuild /p:Configuration=$env:Configuration /p:Platform="x64"
msbuild -m $env:Solution_Path /t:Rebuild /p:Configuration=$env:Configuration /p:Platform="x64" /p:UseSharedCompilation=false
echo "build x86"
msbuild -m $env:Solution_Path /t:Rebuild /p:Configuration=$env:Configuration /p:Platform="x86"
msbuild -m $env:Solution_Path /t:Rebuild /p:Configuration=$env:Configuration /p:Platform="x86" /p:UseSharedCompilation=false
echo "build Any CPU"
msbuild -m $env:Solution_Path /t:Rebuild /p:Configuration=$env:Configuration /p:Platform="Any CPU"
msbuild -m $env:Solution_Path /t:Rebuild /p:Configuration=$env:Configuration /p:Platform="Any CPU" /p:UseSharedCompilation=false
- name: Execute winPEAS -h
shell: pwsh
@@ -230,6 +230,9 @@ jobs:
python3 -m builder.linpeas_builder --all --output linpeas_fat.sh
python3 -m builder.linpeas_builder --all-no-fat --output linpeas.sh
python3 -m builder.linpeas_builder --small --output linpeas_small.sh
- name: Run linPEAS builder tests
run: python3 -m unittest discover -s linPEAS/tests -p "test_*.py"
# Build linpeas binaries
- name: Build linpeas binaries

View File

@@ -8,6 +8,8 @@ on:
paths-ignore:
- '.github/**'
workflow_dispatch:
jobs:
Build_and_test_winpeas_pr:
runs-on: windows-latest
@@ -42,19 +44,23 @@ jobs:
# build
- name: run MSBuild
run: msbuild $env:Solution_Path
run: msbuild $env:Solution_Path /p:Configuration=$env:Configuration /p:UseSharedCompilation=false
# Execute unit tests in the solution
- name: Execute unit tests
run: dotnet test $env:Solution_Path --configuration $env:Configuration
# Build all versions
- name: Build all versions
run: |
echo "build x64"
msbuild -m $env:Solution_Path /t:Rebuild /p:Configuration=$env:Configuration /p:Platform="x64"
msbuild -m $env:Solution_Path /t:Rebuild /p:Configuration=$env:Configuration /p:Platform="x64" /p:UseSharedCompilation=false
echo "build x86"
msbuild -m $env:Solution_Path /t:Rebuild /p:Configuration=$env:Configuration /p:Platform="x86"
msbuild -m $env:Solution_Path /t:Rebuild /p:Configuration=$env:Configuration /p:Platform="x86" /p:UseSharedCompilation=false
echo "build Any CPU"
msbuild -m $env:Solution_Path /t:Rebuild /p:Configuration=$env:Configuration /p:Platform="Any CPU"
msbuild -m $env:Solution_Path /t:Rebuild /p:Configuration=$env:Configuration /p:Platform="Any CPU" /p:UseSharedCompilation=false
- name: Execute winPEAS -h
shell: pwsh
@@ -123,6 +129,9 @@ jobs:
python3 -m builder.linpeas_builder --all --output linpeas_fat.sh
python3 -m builder.linpeas_builder --all-no-fat --output linpeas.sh
python3 -m builder.linpeas_builder --small --output linpeas_small.sh
- name: Run linPEAS builder tests
run: python3 -m unittest discover -s linPEAS/tests -p "test_*.py"
# Run linpeas help as quick test
- name: Run linpeas help

View File

@@ -6,7 +6,7 @@ on:
types: [completed]
jobs:
codex_on_failure:
resolve_pr_context:
if: >
${{ github.event.workflow_run.conclusion == 'failure' &&
github.event.workflow_run.pull_requests &&
@@ -14,11 +14,14 @@ jobs:
!startsWith(github.event.workflow_run.head_commit.message, 'Fix CI failures for PR #') }}
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
issues: write
actions: read
pull-requests: read
issues: read
outputs:
number: ${{ steps.pr_context.outputs.number }}
author: ${{ steps.pr_context.outputs.author }}
head_repo: ${{ steps.pr_context.outputs.head_repo }}
head_branch: ${{ steps.pr_context.outputs.head_branch }}
should_run: ${{ steps.pr_context.outputs.should_run }}
steps:
- name: Resolve PR context
id: pr_context
@@ -35,18 +38,37 @@ jobs:
pr_head_branch=$(gh api -H "Accept: application/vnd.github+json" \
/repos/${{ github.repository }}/pulls/${PR_NUMBER} \
--jq '.head.ref')
pr_labels=$(gh api -H "Accept: application/vnd.github+json" \
/repos/${{ github.repository }}/issues/${PR_NUMBER} \
--jq '.labels[].name')
if echo "$pr_labels" | grep -q "^codex-fix-attempted$"; then
echo "codex fix already attempted for PR #${PR_NUMBER}; skipping."
should_run=false
else
should_run=true
fi
{
echo "number=${PR_NUMBER}"
echo "author=${pr_author}"
echo "head_repo=${pr_head_repo}"
echo "head_branch=${pr_head_branch}"
echo "should_run=${should_run}"
} >> "$GITHUB_OUTPUT"
codex_on_failure:
needs: resolve_pr_context
if: ${{ needs.resolve_pr_context.outputs.author == 'carlospolop' && needs.resolve_pr_context.outputs.should_run == 'true' }}
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
issues: write
actions: read
steps:
- name: Comment on PR with failure info
if: ${{ steps.pr_context.outputs.author == 'carlospolop' }}
uses: actions/github-script@v7
env:
PR_NUMBER: ${{ steps.pr_context.outputs.number }}
PR_NUMBER: ${{ needs.resolve_pr_context.outputs.number }}
RUN_URL: ${{ github.event.workflow_run.html_url }}
WORKFLOW_NAME: ${{ github.event.workflow_run.name }}
with:
@@ -61,23 +83,30 @@ jobs:
body,
});
- name: Mark fix attempt
env:
PR_NUMBER: ${{ needs.resolve_pr_context.outputs.number }}
GH_TOKEN: ${{ github.token }}
run: |
gh api -X POST -H "Accept: application/vnd.github+json" \
/repos/${{ github.repository }}/issues/${PR_NUMBER}/labels \
-f labels='["codex-fix-attempted"]'
- name: Checkout PR head
if: ${{ steps.pr_context.outputs.author == 'carlospolop' }}
uses: actions/checkout@v5
with:
repository: ${{ steps.pr_context.outputs.head_repo }}
repository: ${{ needs.resolve_pr_context.outputs.head_repo }}
ref: ${{ github.event.workflow_run.head_sha }}
fetch-depth: 0
persist-credentials: true
token: ${{ secrets.CODEX_FIXER_TOKEN }}
- name: Configure git author
if: ${{ steps.pr_context.outputs.author == 'carlospolop' }}
run: |
git config user.name "codex-action"
git config user.email "codex-action@users.noreply.github.com"
- name: Fetch failure summary
if: ${{ steps.pr_context.outputs.author == 'carlospolop' }}
env:
GH_TOKEN: ${{ github.token }}
RUN_ID: ${{ github.event.workflow_run.id }}
@@ -105,11 +134,10 @@ jobs:
PY
- name: Create Codex prompt
if: ${{ steps.pr_context.outputs.author == 'carlospolop' }}
env:
PR_NUMBER: ${{ steps.pr_context.outputs.number }}
PR_NUMBER: ${{ needs.resolve_pr_context.outputs.number }}
RUN_URL: ${{ github.event.workflow_run.html_url }}
HEAD_BRANCH: ${{ steps.pr_context.outputs.head_branch }}
HEAD_BRANCH: ${{ needs.resolve_pr_context.outputs.head_branch }}
run: |
{
echo "You are fixing CI failures for PR #${PR_NUMBER} in ${{ github.repository }}."
@@ -125,7 +153,6 @@ jobs:
} > codex_prompt.txt
- name: Run Codex
if: ${{ steps.pr_context.outputs.author == 'carlospolop' }}
id: run_codex
uses: openai/codex-action@v1
with:
@@ -135,10 +162,9 @@ jobs:
model: gpt-5.2-codex
- name: Commit and push if changed
if: ${{ steps.pr_context.outputs.author == 'carlospolop' }}
env:
TARGET_BRANCH: ${{ steps.pr_context.outputs.head_branch }}
PR_NUMBER: ${{ steps.pr_context.outputs.number }}
TARGET_BRANCH: ${{ needs.resolve_pr_context.outputs.head_branch }}
PR_NUMBER: ${{ needs.resolve_pr_context.outputs.number }}
run: |
if git diff --quiet; then
echo "No changes to commit."
@@ -151,10 +177,10 @@ jobs:
git push origin HEAD:${TARGET_BRANCH}
- name: Comment with Codex result
if: ${{ steps.pr_context.outputs.author == 'carlospolop' && steps.run_codex.outputs.final-message != '' }}
if: ${{ steps.run_codex.outputs.final-message != '' }}
uses: actions/github-script@v7
env:
PR_NUMBER: ${{ steps.pr_context.outputs.number }}
PR_NUMBER: ${{ needs.resolve_pr_context.outputs.number }}
CODEX_MESSAGE: ${{ steps.run_codex.outputs.final-message }}
with:
github-token: ${{ github.token }}

View File

@@ -1,5 +1,5 @@
# Title: Software Information - Browser Profiles
# ID: SW_Browser_Profiles
# ID: SW_Browser_profiles
# Author: Carlos Polop
# Last Update: 10-03-2025
# Description: List browser profiles that may store credentials/cookies

View File

@@ -0,0 +1,40 @@
import os
import stat
import subprocess
import tempfile
import unittest
from pathlib import Path
class LinpeasBuilderTests(unittest.TestCase):
def setUp(self):
self.repo_root = Path(__file__).resolve().parents[2]
self.linpeas_dir = self.repo_root / "linPEAS"
def _run_builder(self, args, output_path):
cmd = ["python3", "-m", "builder.linpeas_builder"] + args + ["--output", str(output_path)]
result = subprocess.run(cmd, cwd=str(self.linpeas_dir), capture_output=True, text=True)
if result.returncode != 0:
raise AssertionError(
f"linpeas_builder failed:\nstdout:\n{result.stdout}\nstderr:\n{result.stderr}"
)
def test_small_build_creates_executable(self):
with tempfile.TemporaryDirectory() as tmpdir:
output_path = Path(tmpdir) / "linpeas_small.sh"
self._run_builder(["--small"], output_path)
self.assertTrue(output_path.exists(), "linpeas_small.sh was not created.")
mode = output_path.stat().st_mode
self.assertTrue(mode & stat.S_IXUSR, "linpeas_small.sh is not executable.")
def test_include_exclude_modules(self):
with tempfile.TemporaryDirectory() as tmpdir:
output_path = Path(tmpdir) / "linpeas_include.sh"
self._run_builder(["--include", "system_information,container", "--exclude", "container"], output_path)
content = output_path.read_text(encoding="utf-8", errors="ignore")
self.assertIn("Operative system", content)
self.assertNotIn("Am I Containered?", content)
if __name__ == "__main__":
unittest.main()

View File

@@ -0,0 +1,35 @@
using System;
using System.Reflection;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace winPEAS.Tests
{
[TestClass]
public class ArgumentParsingTests
{
private static bool InvokeIsNetworkTypeValid(string arg)
{
var method = typeof(winPEAS.Checks.Checks).GetMethod("IsNetworkTypeValid", BindingFlags.NonPublic | BindingFlags.Static);
Assert.IsNotNull(method, "IsNetworkTypeValid method not found.");
return (bool)method.Invoke(null, new object[] { arg });
}
[TestMethod]
public void ShouldAcceptValidNetworkTypes()
{
Assert.IsTrue(InvokeIsNetworkTypeValid("-network=auto"));
Assert.IsTrue(InvokeIsNetworkTypeValid("-network=10.10.10.10"));
Assert.IsTrue(InvokeIsNetworkTypeValid("-network=10.10.10.10/24"));
Assert.IsTrue(InvokeIsNetworkTypeValid("-network=10.10.10.10,10.10.10.20"));
}
[TestMethod]
public void ShouldRejectInvalidNetworkTypes()
{
Assert.IsFalse(InvokeIsNetworkTypeValid("-network="));
Assert.IsFalse(InvokeIsNetworkTypeValid("-network=10.10.10.999"));
Assert.IsFalse(InvokeIsNetworkTypeValid("-network=10.10.10.10/64"));
Assert.IsFalse(InvokeIsNetworkTypeValid("-network=not-an-ip"));
}
}
}

View File

@@ -61,9 +61,11 @@
</Reference>
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\MSTest.TestFramework.2.2.5\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\MSTest.TestFramework.2.2.5\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.ComponentModel.Composition" />
@@ -95,6 +97,7 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ArgumentParsingTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SmokeTests.cs" />
</ItemGroup>
@@ -108,6 +111,40 @@
<Name>winPEAS</Name>
</ProjectReference>
</ItemGroup>
<Target Name="CopyVSTestFrameworkToMSTestAdapter" AfterTargets="Build">
<PropertyGroup>
<_PackagesDir>$(MSBuildThisFileDirectory)..\packages\</_PackagesDir>
<_MSTestFrameworkDir>$(_PackagesDir)MSTest.TestFramework.2.2.5\lib\net45\</_MSTestFrameworkDir>
</PropertyGroup>
<ItemGroup Condition="Exists('$(_MSTestFrameworkDir)')">
<_VSTestFrameworkDlls Include="$(_MSTestFrameworkDir)Microsoft.VisualStudio.TestPlatform.TestFramework*.dll" />
</ItemGroup>
<ItemGroup>
<_VSTestCopyDirs Include="$(TargetDir)" Condition="'$(TargetDir)' != '' AND Exists('$(TargetDir)')" />
<_MSTestAdapterDirs Include="$(_PackagesDir)MSTest.TestAdapter.2.2.5\build\net45\" Condition="Exists('$(_PackagesDir)MSTest.TestAdapter.2.2.5\build\net45\')" />
<_MSTestAdapterDirs Include="$(_PackagesDir)MSTest.TestAdapter.2.2.5\build\_common\" Condition="Exists('$(_PackagesDir)MSTest.TestAdapter.2.2.5\build\_common\')" />
</ItemGroup>
<Message
Condition="@(_VSTestFrameworkDlls) != ''"
Importance="high"
Text="CopyVSTestFrameworkToMSTestAdapter: copying @( _VSTestFrameworkDlls )" />
<Copy
Condition="@(_VSTestFrameworkDlls) != '' AND @(_VSTestCopyDirs) != ''"
SourceFiles="@(_VSTestFrameworkDlls)"
DestinationFolder="%(_VSTestCopyDirs.Identity)"
SkipUnchangedFiles="true" />
<Copy
Condition="@(_VSTestFrameworkDlls) != '' AND @(_MSTestAdapterDirs) != ''"
SourceFiles="@(_VSTestFrameworkDlls)"
DestinationFolder="%(_MSTestAdapterDirs.Identity)"
SkipUnchangedFiles="true" />
</Target>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
@@ -133,4 +170,4 @@
<Import Project="..\packages\Stub.System.Data.SQLite.Core.NetFramework.1.0.119.0\build\net451\Stub.System.Data.SQLite.Core.NetFramework.targets" Condition="Exists('..\packages\Stub.System.Data.SQLite.Core.NetFramework.1.0.119.0\build\net451\Stub.System.Data.SQLite.Core.NetFramework.targets')" />
<Import Project="..\packages\Fody.6.5.5\build\Fody.targets" Condition="Exists('..\packages\Fody.6.5.5\build\Fody.targets')" />
<Import Project="..\packages\Costura.Fody.5.7.0\build\Costura.Fody.targets" Condition="Exists('..\packages\Costura.Fody.5.7.0\build\Costura.Fody.targets')" />
</Project>
</Project>

View File

@@ -11,6 +11,7 @@ namespace winPEAS
[STAThread]
public static void Main(string[] args)
{
// TODO: keep Main minimal; this line was an intentional break in test PR.
Checks.Checks.Run(args);
}
}