Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
9ce8a9a
Add self-hosted validation workflow for release testing
Mar 15, 2026
13f7371
feat: implement Defender CLI v2 with v1/v2 folder structure
Mar 16, 2026
0ebbec9
chore: update validation workflow policy to azuredevops
Mar 16, 2026
f941645
chore: remove debug flag from validation workflow
Mar 16, 2026
b3cc53f
chore: change validation policy to mdc
Mar 16, 2026
1127116
fix: set sarifFile output for downstream SARIF upload
Mar 16, 2026
96bd737
chore: add model scan job for Qwen3.5-35B-A3B validation
Mar 16, 2026
d38c90d
fix: call setupEnvironment in model scan to install Defender CLI
Mar 16, 2026
148f542
chore: add vulnerable model scan job for bert-tiny-torch-vuln
Mar 16, 2026
b57d3ad
chore: remove upload-sarif from model scan jobs (incompatible URI sch…
Mar 16, 2026
38abab4
chore: add filesystem scan job with azuredevops policy
Mar 16, 2026
cfe50ee
refactor: split validation into v1/v2 workflows, restore v1 action.yml
Mar 17, 2026
0d4071e
chore: gitignore copilot-instructions.md
Mar 17, 2026
57c1be2
chore: add comprehensive v2 test variations
Mar 18, 2026
3dfd65b
fix: change default policy from github to mdc
Mar 18, 2026
7273151
merge resolution
Mar 19, 2026
21a4605
Merge branch 'main' into main
omerb97 Mar 19, 2026
3a42543
remove obselete arch
Mar 19, 2026
2f77780
Merge branch 'main' of https://github.com/omerb97/security-devops-action
Mar 19, 2026
568a7d6
cr
Mar 22, 2026
b8deec4
cr
Mar 22, 2026
de1b1a4
Merge pull request #213 from omerb97/main
omerb97 Mar 23, 2026
2ec54a5
fix(ci): probe — guardian init only, weekly cache, parse .gdntool XML…
DimaBir Mar 23, 2026
dabaaf6
fix(ci): rewrite probe — scrape .gdn/i/ dirs, fix broken cache SHA, d…
DimaBir Mar 23, 2026
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
5 changes: 3 additions & 2 deletions .github/workflows/msdo-breach-monitor.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
# Nightly supply chain breach monitor for MSDO toolchain dependencies

on:
schedule:
- cron: daily
workflow_dispatch:
# Triggered by toolchain-version-probe after committing fresh versions.
# No schedule here — the probe owns the daily cadence and guarantees
# toolchain-versions.json is fresh before this workflow reads it.
roles: [write]

engine:
Expand Down
29 changes: 29 additions & 0 deletions .github/workflows/self-hosted-validation-v1.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: MSDO v1 self-hosted validation
on: push

permissions:
id-token: write
security-events: write

jobs:
msdo-scan:
name: MSDO v1 - Security Scan

runs-on: self-hosted

steps:

# Checkout your code repository to scan
- uses: actions/checkout@v6

# Run MSDO v1
- name: Run MSDO
uses: ./
id: msdo

# Upload results to the Security tab
- name: Upload results to Security tab
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: ${{ steps.msdo.outputs.sarifFile }}
35 changes: 35 additions & 0 deletions .github/workflows/self-hosted-validation-v2.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Defender CLI v2 self-hosted validation
on:
push:
branches: [main, 'release/**']
workflow_dispatch:

permissions:
id-token: write
security-events: write

jobs:
defender-image-scan:
name: Image Scan (mdc policy)

runs-on: self-hosted

steps:

- uses: actions/checkout@v6

- name: Run Defender CLI - Image Scan
uses: ./v2/
id: defender
with:
command: 'image'
imageName: 'ubuntu:latest'
policy: 'mdc'
break: 'false'
pr-summary: 'true'

- name: Upload results to Security tab
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: ${{ steps.defender.outputs.sarifFile }}
72 changes: 35 additions & 37 deletions .github/workflows/toolchain-version-probe.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,60 +31,64 @@ jobs:
tools: bandit,binskim,checkov,eslint,templateanalyzer,terrascan,trivy

- name: Collect resolved tool versions from install dirs
id: collect
run: |
python3 - <<'PYEOF'
import os, json, re, pathlib, datetime

# MSDO installs packages into $RUNNER_TEMP/../_msdo/packages/nuget/{PackageName}.{version}/
# and npm tools into $RUNNER_TEMP/../_msdo/packages/node_modules/{tool}/package.json
runner_temp = pathlib.Path(os.environ.get('RUNNER_TEMP', '/tmp'))
MSDO_PACKAGES = runner_temp.parent / '_msdo' / 'packages'
# MSDO installs packages into .gdn/i/{type}/{PackageName}.{version}/
# DotNetToolClient.cs:244 → nuget dirs are PackageName.Version
# ZipClient / Pip3Client → same pattern via PackageInstaller
GDN_I = pathlib.Path('.gdn/i')

VER_PAT = re.compile(r'^(.+?)\.(v?\d+\.\d+(?:\.\d+)*(?:[-+][0-9A-Za-z.-]+)?)$', re.IGNORECASE)

# Actual Guardian NuGet package names → canonical tool names.
# Pattern: Microsoft.Guardian.{Tool}Redist_{platform}.{version}
# Map installed package names → canonical tool names used in our inventory.
# Keys are lowercase. Add new entries after the first probe run reveals
# the exact package names for terrascan, trivy, eslint, bandit, checkov.
PKG_TO_TOOL = {
'microsoft.guardian.banditredist_linux_amd64': 'bandit',
'microsoft.guardian.banditredist_win_amd64': 'bandit',
'microsoft.codeanalysis.binskim': 'binskim',
'microsoft.guardian.checkovredist_linux_amd64': 'checkov',
'microsoft.guardian.checkovredist_win_amd64': 'checkov',
'azure.templates.analyzer.commandline.linux-x64': 'templateanalyzer',
'azure.templates.analyzer.commandline.win-x64': 'templateanalyzer',
'microsoft.guardian.terrascanredist_linux_amd64': 'terrascan',
'microsoft.guardian.terrascanredist_win_amd64': 'terrascan',
'microsoft.guardian.trivyredist_linux_amd64': 'trivy',
'microsoft.guardian.trivyredist_win_amd64': 'trivy',
# NuGet
'microsoft.codeanalysis.binskim': 'binskim',
'microsoft.azure.templates.analyzer': 'templateanalyzer',
# pip (package name == tool name for these)
'bandit': 'bandit',
'checkov': 'checkov',
# npm
'eslint': 'eslint',
# zip / GitHub releases (names TBD from first run — check raw_dirs)
'trivy': 'trivy',
'terrascan': 'terrascan',
}

# Internal CLI package — skip in output
CLI_PKGS = {
'microsoft.security.devops.cli',
'microsoft.security.devops.cli.linux-x64',
'microsoft.security.devops.cli.linux-arm64',
'microsoft.security.devops.cli.win-x64',
}

tools = {}
raw_dirs = {}

# NuGet packages (all tools except eslint)
nuget_dir = MSDO_PACKAGES / 'nuget'
if nuget_dir.exists():
entries = sorted(d.name for d in nuget_dir.iterdir() if d.is_dir())
raw_dirs['nuget'] = entries
for pkg_type in ('nuget', 'pip', 'npm', 'zip'):
type_dir = GDN_I / pkg_type
if not type_dir.exists():
continue
entries = sorted(d.name for d in type_dir.iterdir() if d.is_dir())
raw_dirs[pkg_type] = entries
for name in entries:
m = VER_PAT.match(name)
if not m:
continue
pkg_lower = m.group(1).lower()
version = m.group(2)
if pkg_lower in CLI_PKGS:
continue
canonical = PKG_TO_TOOL.get(pkg_lower)
if canonical is None:
continue
tools[canonical] = version

# eslint is installed via npm into node_modules/eslint/package.json
eslint_pkg = MSDO_PACKAGES / 'node_modules' / 'eslint' / 'package.json'
if eslint_pkg.exists():
eslint_version = json.loads(eslint_pkg.read_text()).get('version')
if eslint_version:
tools['eslint'] = eslint_version

output = {
'generated_at': datetime.datetime.now(datetime.timezone.utc).strftime('%Y-%m-%dT%H:%M:%SZ'),
'msdo_cli_version': os.environ.get('MSDO_INSTALLEDVERSION', 'unknown'),
Expand All @@ -95,12 +99,7 @@ jobs:
expected = set(PKG_TO_TOOL.values())
missing = expected - set(tools.keys())
if not tools:
print('WARNING: no tool versions resolved — MSDO packages dir empty or MSDO failed. Skipping commit to preserve last known-good state.')
gh_out = os.environ.get('GITHUB_OUTPUT', '')
if gh_out:
with open(gh_out, 'a') as f:
f.write('skip_commit=true\n')
import sys; sys.exit(0)
raise SystemExit('ERROR: no tool versions resolved — .gdn/i/ may be empty. Aborting to avoid poisoning toolchain-versions.json.')
if missing:
print(f'WARNING: expected tools not found in install dirs: {sorted(missing)}')

Expand All @@ -111,7 +110,6 @@ jobs:
PYEOF

- name: Commit updated versions
if: steps.collect.outputs.skip_commit != 'true'
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
Expand Down
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -329,3 +329,9 @@ ASALocalRun/

# MFractors (Xamarin productivity tool) working folder
.mfractor/

# GitHub Actions Runner
actions-runner/

# Copilot instructions
.github/copilot-instructions.md
6 changes: 3 additions & 3 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@ outputs:
description: A file path to a SARIF results file.
runs:
using: 'node24'
main: 'lib/main.js'
pre: 'lib/pre.js'
post: 'lib/post.js'
main: 'lib/v1/main.js'
pre: 'lib/v1/pre.js'
post: 'lib/v1/post.js'
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loading
Loading