Skip to content

Create system-maintenance-workstations.vbs #11

Create system-maintenance-workstations.vbs

Create system-maintenance-workstations.vbs #11

name: VBScript Syntax Validation (Wine + SARIF + Summary) [Report-Only]
on:
push:
branches: [main, develop]
paths:
- "**/*.vbs"
- "**/*.hta"
- ".github/workflows/vbscript-syntax-validation.yml"
pull_request:
branches: [main, develop]
paths:
- "**/*.vbs"
- "**/*.hta"
- ".github/workflows/vbscript-syntax-validation.yml"
workflow_dispatch:
concurrency:
group: vbscript-syntax-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
security-events: write
jobs:
vbscript-syntax-check:
name: 🔍 VBScript Syntax Validation (SARIF + Artifacts)
runs-on: ubuntu-latest
timeout-minutes: 20
env:
OUT_DIR: vbscript-reports
OUT_SARIF: vbscript-results.sarif
OUT_MD: vbscript-summary.md
OUT_RAW: vbscript-raw.log
OUT_JSON: vbscript-results.json
# Report-only (never fail the job). Set to "false" if you want gating.
ALLOW_WARNINGS: "true"
# Wine noise control (must be quoted!)
WINEDEBUG: "-all"
steps:
- name: 📦 Checkout repository (short path)
uses: actions/checkout@v4
with:
path: repo
fetch-depth: 0
- name: 🍷 Setup Wine
shell: bash
run: |
set -euo pipefail
sudo dpkg --add-architecture i386 || true
sudo apt-get update
sudo apt-get install -y wine64
WINEDEBUG="${WINEDEBUG}" wineboot --init
- name: 📁 Ensure output folder
shell: bash
run: |
set -euo pipefail
mkdir -p "repo/${OUT_DIR}"
- name: 🧱 Initialize baseline outputs (always)
if: always()
shell: bash
run: |
set -euo pipefail
out="repo/${OUT_DIR}"
# Baseline SARIF (empty)
cat > "${out}/${OUT_SARIF}" <<'SARIF'
{
"$schema": "https://json.schemastore.org/sarif-2.1.0.json",
"version": "2.1.0",
"runs": [
{
"tool": {
"driver": {
"name": "VBScript Syntax Validation (Wine+cscript)",
"informationUri": "https://learn.microsoft.com/en-us/previous-versions//d1wf56tt(v=vs.85)"
}
},
"results": []
}
]
}
SARIF
# Baseline reports
: > "${out}/${OUT_MD}"
: > "${out}/${OUT_RAW}"
echo "[]" > "${out}/${OUT_JSON}"
- name: 🧪 Scan (.vbs + .hta with VBScript blocks) [Report-Only]
id: scan
working-directory: repo
shell: bash
run: |
set -euo pipefail
outdir="${OUT_DIR}"
raw="${outdir}/${OUT_RAW}"
md="${outdir}/${OUT_MD}"
json="${outdir}/${OUT_JSON}"
sarif="${outdir}/${OUT_SARIF}"
files_list="$(mktemp)"
find . -type f \( -iname "*.vbs" -o -iname "*.hta" \) -print0 > "${files_list}"
{
echo "# VBScript Syntax Validation (Report-Only)"
echo
echo "- **Workflow:** \`${GITHUB_WORKFLOW}\`"
echo "- **Event:** \`${GITHUB_EVENT_NAME}\`"
echo "- **Ref:** \`${GITHUB_REF}\`"
echo "- **Commit:** \`${GITHUB_SHA}\`"
echo
echo "## Findings"
echo
echo "| File | Line | Message |"
echo "|------|------|---------|"
} > "${md}"
tsv="${outdir}/findings.tsv"
: > "${tsv}"
total_files=0
scanned_files=0
skipped_files=0
findings=0
while IFS= read -r -d '' file; do
[[ -z "${file:-}" ]] && continue
total_files=$((total_files + 1))
rel="${file#./}"
echo "==> Candidate: ${rel}" >> "${raw}"
# HTA filtering: only scan if it contains VBScript blocks
if [[ "${file}" == *.hta ]]; then
if grep -iqE '^\s*<(html|!doctype)' "${file}"; then
if ! grep -iq '<script[^>]*language=["'"'"'"]vbscript["'"'"'"]' "${file}"; then
echo "::notice file=${rel}::Skipped HTA (HTML without VBScript blocks)"
echo "SKIP: ${rel} (HTML/no VBScript)" >> "${raw}"
skipped_files=$((skipped_files + 1))
continue
fi
else
if ! grep -iq '<script[^>]*language=["'"'"'"]vbscript["'"'"'"]' "${file}"; then
echo "::notice file=${rel}::Skipped HTA (no VBScript block)"
echo "SKIP: ${rel} (no VBScript)" >> "${raw}"
skipped_files=$((skipped_files + 1))
continue
fi
fi
fi
scanned_files=$((scanned_files + 1))
echo "SCAN: ${rel}" >> "${raw}"
tmp_err="$(mktemp)"
set +e
WINEDEBUG="${WINEDEBUG}" wine cscript.exe //nologo //B "${file}" 2> "${tmp_err}"
ec="$?"
set -e
if [[ "${ec}" -ne 0 ]]; then
msg_line="$(grep -nE 'error|erro|expected|unexpected|invalid|syntax' "${tmp_err}" | head -n 1 || true)"
line_number="$(echo "${msg_line}" | cut -d: -f1 || true)"
message="$(echo "${msg_line}" | cut -d: -f2- || true)"
if [[ -z "${line_number:-}" ]]; then line_number="1"; fi
if [[ -z "${message// }" ]]; then
message="$(head -n 1 "${tmp_err}" | tr -d '\r' || true)"
fi
if [[ -z "${message// }" ]]; then
message="VBScript syntax error (cscript exit ${ec})"
fi
safe_message="$(echo "${message}" | tr -d '\r' | sed 's/|/\\|/g')"
echo "::error file=${rel},line=${line_number}::${safe_message}"
echo "| \`${rel}\` | ${line_number} | ${safe_message} |" >> "${md}"
echo "${rel}\t${line_number}\t${message}" >> "${tsv}"
findings=$((findings + 1))
fi
cat "${tmp_err}" >> "${raw}" || true
echo "" >> "${raw}"
rm -f "${tmp_err}"
done < "${files_list}"
rm -f "${files_list}"
if [[ "${findings}" -eq 0 ]]; then
echo "| ✅ No syntax errors found. | - | - |" >> "${md}"
fi
python3 - <<'PY'
import json, os
outdir = os.environ.get("OUT_DIR", "vbscript-reports")
tsv = os.path.join(outdir, "findings.tsv")
out_json = os.path.join(outdir, os.environ.get("OUT_JSON", "vbscript-results.json"))
out_sarif = os.path.join(outdir, os.environ.get("OUT_SARIF", "vbscript-results.sarif"))
findings = []
if os.path.exists(tsv):
with open(tsv, "r", encoding="utf-8", errors="replace") as f:
for line in f:
line = line.rstrip("\n")
if not line.strip():
continue
parts = line.split("\t")
if len(parts) < 3:
continue
path, line_no, msg = parts[0], parts[1], "\t".join(parts[2:])
try:
ln = int(line_no)
except Exception:
ln = 1
findings.append({"file": path, "line": ln, "message": msg})
with open(out_json, "w", encoding="utf-8") as f:
json.dump(findings, f, ensure_ascii=False, indent=2)
sarif = {
"$schema": "https://json.schemastore.org/sarif-2.1.0.json",
"version": "2.1.0",
"runs": [{
"tool": {"driver": {
"name": "VBScript Syntax Validation (Wine+cscript)",
"informationUri": "https://learn.microsoft.com/en-us/previous-versions//d1wf56tt(v=vs.85)"
}},
"results": []
}]
}
for x in findings:
sarif["runs"][0]["results"].append({
"level": "error",
"message": {"text": x["message"]},
"locations": [{
"physicalLocation": {
"artifactLocation": {"uri": x["file"]},
"region": {"startLine": int(x["line"]) if x["line"] else 1}
}
}]
})
with open(out_sarif, "w", encoding="utf-8") as f:
json.dump(sarif, f, ensure_ascii=False, indent=2)
PY
echo "total_files=${total_files}" >> "${GITHUB_OUTPUT}"
echo "scanned_files=${scanned_files}" >> "${GITHUB_OUTPUT}"
echo "skipped_files=${skipped_files}" >> "${GITHUB_OUTPUT}"
echo "findings=${findings}" >> "${GITHUB_OUTPUT}"
exit 0
- name: 📝 Publish Job Summary (View Runs)
if: always()
working-directory: repo
shell: bash
run: |
set -euo pipefail
outdir="${OUT_DIR}"
{
echo "## 🧪 VBScript Syntax Validation (Report-Only)"
echo
echo "- **Workflow:** \`${GITHUB_WORKFLOW}\`"
echo "- **Event:** \`${GITHUB_EVENT_NAME}\`"
echo "- **Ref:** \`${GITHUB_REF}\`"
echo "- **Commit:** \`${GITHUB_SHA}\`"
echo
echo "### Stats"
echo
echo "- **Files discovered:** \`${{ steps.scan.outputs.total_files || '0' }}\`"
echo "- **Files scanned:** \`${{ steps.scan.outputs.scanned_files || '0' }}\`"
echo "- **Files skipped:** \`${{ steps.scan.outputs.skipped_files || '0' }}\`"
echo "- **Findings:** \`${{ steps.scan.outputs.findings || '0' }}\`"
echo
echo "### Markdown Report"
echo
if [[ -f "${outdir}/${OUT_MD}" ]]; then
cat "${outdir}/${OUT_MD}"
else
echo "_No markdown report file found:_ \`${outdir}/${OUT_MD}\`"
fi
echo
echo "### Artifacts"
echo
echo "- \`${outdir}/${OUT_MD}\`"
echo "- \`${outdir}/${OUT_SARIF}\`"
echo "- \`${outdir}/${OUT_JSON}\`"
echo "- \`${outdir}/${OUT_RAW}\`"
} >> "$GITHUB_STEP_SUMMARY"
- name: 📦 Upload artifacts (reports)
if: always()
uses: actions/upload-artifact@v4
with:
name: vbscript-syntax-reports
path: repo/${{ env.OUT_DIR }}/**
if-no-files-found: warn
retention-days: 30
- name: 🛰️ Upload SARIF to GitHub Code Scanning (report-only)
if: always() && hashFiles(format('repo/{0}/{1}', env.OUT_DIR, env.OUT_SARIF)) != ''
uses: github/codeql-action/upload-sarif@v4
with:
sarif_file: repo/${{ env.OUT_DIR }}/${{ env.OUT_SARIF }}
category: vbscript/syntax
- name: ✅ Policy Gate (optional)
if: always()
shell: bash
run: |
set -euo pipefail
if [[ "${ALLOW_WARNINGS}" == "true" ]]; then
echo "ALLOW_WARNINGS=true -> report-only mode. Passing."
exit 0
fi
findings="${{ steps.scan.outputs.findings || '0' }}"
if [[ "${findings}" != "0" ]]; then
echo "❌ VBScript syntax findings detected (${findings}). Failing (enforced mode)."
exit 1
fi
echo "✅ No VBScript syntax issues. Passing."