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
4 changes: 4 additions & 0 deletions .github/workflows/codeql.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ on:
schedule:
- cron: '0 0 * * 0' # Weekly on Sunday at midnight UTC

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

permissions:
contents: read # Default to read-only; the analyze job overrides where required

Expand Down
99 changes: 99 additions & 0 deletions .github/workflows/pr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
# (it does NOT, by itself, prevent steps from accessing github.token / GITHUB_TOKEN if you explicitly expose it)
# - After checkout, configuration files (.editorconfig, BannedSymbols.txt, etc.) are fetched from
# the main branch to prevent malicious PRs from disabling analyzers or bypassing code quality checks
# - If a PR changes any of these protected configuration files, CI explicitly fails with instructions
# for a maintainer to manually review and verify the changes before merging
# - Default GITHUB_TOKEN permissions are restricted to read-only repository contents to limit impact if exposed

name: PR Checks v3 (Gated)
Expand Down Expand Up @@ -70,6 +72,103 @@ jobs:
ref: refs/pull/${{ github.event.pull_request.number }}/head
persist-credentials: false

- name: Fetch trusted configuration files from main branch
run: |
echo "Fetching configuration files from main branch to prevent malicious overrides..."

# Fetch the main branch
git fetch origin main:main-branch

# List of configuration files that should come from trusted main branch
config_files=(
".editorconfig"
"Directory.Build.props"
"Directory.Build.targets"
"BannedSymbols.txt"
"*.globalconfig"
"*.ruleset"
)

# Copy each configuration file from main branch if it exists
for config_file in "${config_files[@]}"; do
# Handle glob patterns
if [[ "$config_file" == *"*"* ]]; then
# Find files matching the pattern in main branch
git ls-tree -r --name-only main-branch | grep -E "${config_file//\*/.*}" | while read -r file; do
if [ -n "$file" ]; then
echo " ✓ Copying $file from main branch"
mkdir -p "$(dirname "$file")"
git show "main-branch:$file" > "$file" || echo " ⚠️ Failed to copy $file"
fi
done
else
# Check if file exists in main branch
if git cat-file -e "main-branch:$config_file" 2>/dev/null; then
echo " ✓ Copying $config_file from main branch"
git show "main-branch:$config_file" > "$config_file"
else
echo " ℹ️ $config_file not found in main branch, skipping"
fi
fi
done

echo ""
echo "✅ Configuration files secured - using versions from main branch"

- name: Detect protected configuration file changes
run: |
echo "Checking for changes to protected configuration files in this PR..."

# Verify main-branch ref is available (it was fetched in the previous step)
if ! git cat-file -e main-branch 2>/dev/null; then
echo "❌ main-branch ref not found - cannot detect configuration file changes"
exit 1
fi

changed_files=()

# Check exact file matches against main branch git objects
# 2>/dev/null suppresses output when a file doesn't exist in one ref (new/deleted file),
# which git diff handles correctly via its exit code
exact_files=(
".editorconfig"
"Directory.Build.props"
"Directory.Build.targets"
"BannedSymbols.txt"
)

for config_file in "${exact_files[@]}"; do
if ! git diff --quiet main-branch HEAD -- "$config_file" 2>/dev/null; then
changed_files+=("$config_file")
fi
done

# Check .globalconfig and .ruleset files using the same git diff approach
# --diff-filter=AMRC: Added, Modified, Renamed, Copied (excludes Deleted)
while IFS= read -r file; do
changed_files+=("$file")
done < <(git diff --name-only --diff-filter=AMRC main-branch HEAD 2>/dev/null | grep -E '\.(globalconfig|ruleset)$' || true)

if [ ${#changed_files[@]} -gt 0 ]; then
echo ""
echo "⚠️ PROTECTED CONFIGURATION FILES CHANGED IN THIS PR:"
for file in "${changed_files[@]}"; do
echo " - $file"
done
echo ""
echo "❌ CI uses the main branch version of these files to prevent security bypasses."
echo " The PR's changes to these files were NOT tested by CI."
echo " A maintainer must manually review and verify these changes before merging."
echo ""
echo "To proceed, a maintainer should:"
echo " 1. Review the configuration changes in this PR carefully"
echo " 2. Test the changes locally to confirm they work correctly"
echo " 3. Merge with awareness that CI did not validate these configuration changes"
exit 1
else
echo "✅ No protected configuration files changed - CI fully validates this PR"
fi

- name: Check for .NET project files
id: check-projects
run: |
Expand Down
Loading
Loading