php2shell-scanner.git

php2shell-scanner

~ Check PHP2Shell (CVE-2026-109618, CVE-2026-109619) from inside your server: distribution backports, missed restarts and interim mitigations, verdicts computed in the browser.
git clone https://github.com/debuman/php2shell-scanner.git

.github/workflows/pages.yml (4516B)

      1 name: Deploy site
      2 
      3 on:
      4   push:
      5     branches: [main]
      6   schedule:
      7     # Fetch distribution security data again every 6 hours.
      8     - cron: '17 */6 * * *'
      9   workflow_dispatch:
     10 
     11 permissions:
     12   contents: read
     13 
     14 # One run at a time, including its data commit. A newer run waits; it is never cancelled midway.
     15 concurrency:
     16   group: pages
     17   cancel-in-progress: false
     18 
     19 # The site is built, tested and deployed from exactly the commit this run checked out, plus
     20 # freshly fetched data. Recording that data in git is a separate, last job: it never pulls new
     21 # code into the build, and a rejected push can never hold back a deploy.
     22 jobs:
     23   build:
     24     runs-on: ubuntu-latest
     25     permissions:
     26       contents: read
     27       pages: read
     28     outputs:
     29       data_changed: ${{ steps.data.outputs.changed }}
     30     steps:
     31       - uses: actions/checkout@v4
     32         with:
     33           persist-credentials: false
     34 
     35       - uses: actions/setup-node@v4
     36         with:
     37           node-version: 22
     38 
     39       # The same command as ci.yml.
     40       - name: Test
     41         run: npm test
     42 
     43       # If the fixed versions in the official advisories differ from upstream.json, fail here and do not deploy.
     44       - name: Update distro data
     45         id: data
     46         run: |
     47           node tools/update-distro-data.mjs
     48           if git diff --quiet -- site/data/distro.json; then
     49             echo "changed=false" >> "$GITHUB_OUTPUT"
     50           else
     51             echo "changed=true" >> "$GITHUB_OUTPUT"
     52           fi
     53         env:
     54           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
     55 
     56       # The verdict tests above use a frozen copy of the data; this checks the data just fetched before it is
     57       # deployed or committed.
     58       - name: Check the fetched data
     59         run: node --test test/data.test.mjs
     60 
     61       - name: Assemble site
     62         run: node tools/build-site.mjs
     63 
     64       - uses: actions/configure-pages@v5
     65 
     66       - uses: actions/upload-pages-artifact@v3
     67         with:
     68           path: _site
     69 
     70       - name: Keep the new distro.json for the data commit
     71         if: steps.data.outputs.changed == 'true'
     72         uses: actions/upload-artifact@v4
     73         with:
     74           name: distro-data
     75           path: site/data/distro.json
     76           if-no-files-found: error
     77           retention-days: 1
     78           overwrite: true
     79 
     80   deploy:
     81     needs: build
     82     runs-on: ubuntu-latest
     83     permissions:
     84       pages: write
     85       id-token: write
     86     environment:
     87       name: github-pages
     88       url: ${{ steps.deployment.outputs.page_url }}
     89     steps:
     90       - id: deployment
     91         uses: actions/deploy-pages@v4
     92 
     93   # Commit the data that is now live to main, so the history of distro.json is the history of
     94   # the deployed data, and the next run starts from it. Runs only after a successful deploy.
     95   commit-data:
     96     needs: [build, deploy]
     97     if: needs.build.outputs.data_changed == 'true' && github.ref == 'refs/heads/main'
     98     runs-on: ubuntu-latest
     99     permissions:
    100       contents: write
    101     steps:
    102       # The latest main, not this run's commit: main may have moved on while this run waited or ran.
    103       - uses: actions/checkout@v4
    104         with:
    105           ref: main
    106 
    107       - uses: actions/download-artifact@v4
    108         with:
    109           name: distro-data
    110           path: ${{ runner.temp }}/distro-data
    111 
    112       - name: Commit distro.json
    113         env:
    114           NEW_DATA: ${{ runner.temp }}/distro-data/distro.json
    115         run: |
    116           # Compare without updated_at, so a main that already holds the same data is left alone.
    117           strip() { jq -S 'del(.updated_at)' "$1"; }
    118           if [ -f site/data/distro.json ] && [ "$(strip "$NEW_DATA")" = "$(strip site/data/distro.json)" ]; then
    119             echo "main already has this data"
    120             exit 0
    121           fi
    122           cp "$NEW_DATA" site/data/distro.json
    123           git config user.name "github-actions[bot]"
    124           git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
    125           git add site/data/distro.json
    126           git commit -m "data: update distro advisories"
    127           # No pull and no retry: if main moved on again, or a rule on main blocks pushes from
    128           # workflows, the deployed site is still current and the next run fetches and commits again.
    129           if ! git push origin HEAD:main; then
    130             echo "::warning title=Data commit not pushed::The new distro.json is deployed but was not pushed to main. The next run fetches the data again and retries. If a ruleset or branch protection on main blocks pushes from workflows, see the README section on self-hosting."
    131           fi