|
| 1 | +name: bughunt npm probe |
| 2 | +on: |
| 3 | + push: |
| 4 | + branches: ['bughunt/npm/**'] |
| 5 | +permissions: |
| 6 | + contents: read |
| 7 | +jobs: |
| 8 | + probe: |
| 9 | + strategy: |
| 10 | + fail-fast: false |
| 11 | + matrix: |
| 12 | + os: [ubuntu-latest, macos-latest, windows-latest] |
| 13 | + npm: ['10.9.7', '12.1.0'] |
| 14 | + runs-on: ${{ matrix.os }} |
| 15 | + timeout-minutes: 45 |
| 16 | + defaults: |
| 17 | + run: |
| 18 | + shell: bash |
| 19 | + steps: |
| 20 | + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 |
| 21 | + with: |
| 22 | + persist-credentials: false |
| 23 | + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 |
| 24 | + with: |
| 25 | + node-version: '24.15.0' |
| 26 | + - name: Build CLI |
| 27 | + run: cargo build --release -p socket-patch-cli |
| 28 | + - name: Install npm |
| 29 | + run: npm install -g npm@${{ matrix.npm }} && npm --version |
| 30 | + - name: Probe |
| 31 | + env: |
| 32 | + SOCKET_NO_UPDATE_CHECK: '1' |
| 33 | + SOCKET_NO_CONFIG: '1' |
| 34 | + run: | |
| 35 | + set +e |
| 36 | + BIN="$PWD/target/release/socket-patch" |
| 37 | + [ -f "$BIN.exe" ] && BIN="$BIN.exe" |
| 38 | + git config --global user.email probe@example.com; git config --global user.name probe |
| 39 | + git config --global init.defaultBranch main |
| 40 | + W="$RUNNER_TEMP/pr obé ü"; mkdir -p "$W" |
| 41 | + cat > "$W/stage.js" <<'JS' |
| 42 | + const fs=require('fs'),path=require('path'),crypto=require('crypto'); |
| 43 | + const [proj,purl,pkgdir]=process.argv.slice(2); |
| 44 | + const before=fs.readFileSync(path.join(pkgdir,'index.js')); |
| 45 | + const after=Buffer.concat([Buffer.from('/* SOCKET-PATCHED */\n'),before]); |
| 46 | + const gh=b=>crypto.createHash('sha256').update(Buffer.concat([Buffer.from('blob '+b.length+'\0'),b])).digest('hex'); |
| 47 | + fs.mkdirSync(path.join(proj,'.socket','blobs'),{recursive:true}); |
| 48 | + const m={patches:{[purl]:{uuid:'1a2b3c4d-5e6f-4a1b-8c2d-0123456789ab',exportedAt:'2026-01-01T00:00:00Z', |
| 49 | + files:{'package/index.js':{beforeHash:gh(before),afterHash:gh(after)}}, |
| 50 | + vulnerabilities:{'GHSA-xxxx-yyyy-zzzz':{cves:['CVE-2024-99999'],summary:'s',severity:'high',description:'d'}}, |
| 51 | + description:'m',license:'MIT',tier:'free'}}}; |
| 52 | + fs.writeFileSync(path.join(proj,'.socket','manifest.json'),JSON.stringify(m,null,2)+'\n'); |
| 53 | + fs.writeFileSync(path.join(proj,'.socket','blobs',gh(after)),after); |
| 54 | + fs.writeFileSync(path.join(proj,'.socket','blobs',gh(before)),before); |
| 55 | + JS |
| 56 | + head20() { node -e "process.stdout.write(require('fs').readFileSync(process.argv[1],'utf8').slice(0,20).replace(/\r?\n/g,' '))" "$1" 2>/dev/null || echo MISSING; } |
| 57 | + vexst() { node -e "try{const d=require(process.argv[1]);console.log((d.statements||[]).map(s=>s.status).join(',')||'none')}catch(e){console.log('nodoc')}" "$1"; } |
| 58 | + T="${{ matrix.os }} npm ${{ matrix.npm }}" |
| 59 | +
|
| 60 | + echo "::group::vendored on LF, fresh clone with core.autocrlf=true" |
| 61 | + V="$W/vend src"; mkdir -p "$V"; cd "$V" |
| 62 | + echo '{"name":"app","version":"1.0.0","private":true,"dependencies":{"left-pad":"1.3.0","is-odd":"3.0.1","is-number":"7.0.0"}}' > package.json |
| 63 | + printf 'node_modules\n' > .gitignore |
| 64 | + npm install --no-audit --no-fund >/dev/null 2>&1 |
| 65 | + node "$W/stage.js" . pkg:npm/left-pad@1.3.0 node_modules/left-pad |
| 66 | + "$BIN" vendor --offline --json > "$W/vendor1.json"; echo "vendor exit $?" |
| 67 | + git init -q . && git add -A && git commit -qm vendored |
| 68 | + C="$W/vend clone"; git -c core.autocrlf=true clone -q "$V" "$C"; cd "$C" |
| 69 | + echo "lock has CRLF: $(grep -c $'\r' package-lock.json) state.json CRLF: $(grep -c $'\r' .socket/vendor/state.json 2>/dev/null)" |
| 70 | + npm ci --no-audit --no-fund > "$W/ci.log" 2>&1; CI=$? |
| 71 | + "$BIN" vex --output "$W/v1.json" --json > "$W/vex1.json" 2>&1; VX=$? |
| 72 | + echo "RESULT autocrlf-ci $T: ci=$CI left-pad=[$(head20 node_modules/left-pad/index.js)] vex_exit=$VX vex=$(vexst "$W/v1.json")" |
| 73 | + cat "$W/vex1.json" | head -c 1500; echo |
| 74 | + "$BIN" vendor --offline --json > "$W/vendor2.json" 2>&1; R2=$? |
| 75 | + echo "RESULT autocrlf-revendor $T: exit=$R2 status=$(node -e "console.log(require(process.argv[1]).status)" "$W/vendor2.json") gitdiff=[$(git status --short | tr '\n' ' ')]" |
| 76 | + head -c 1500 "$W/vendor2.json"; echo |
| 77 | + "$BIN" vendor --revert --json > "$W/revert.json" 2>&1; RV=$? |
| 78 | + echo "RESULT autocrlf-revert $T: exit=$RV gitstatus=[$(git status --short | tr '\n' ' ')] diffstat=[$(git diff --stat HEAD~0 | tail -1)]" |
| 79 | + head -c 1500 "$W/revert.json"; echo |
| 80 | + echo "::endgroup::" |
| 81 | +
|
| 82 | + echo "::group::agent mode, CRLF manifest + unicode/space path" |
| 83 | + AG="$W/agent é"; mkdir -p "$AG"; cd "$AG" |
| 84 | + echo '{"name":"app","version":"1.0.0","private":true,"dependencies":{"left-pad":"1.3.0"}}' > package.json |
| 85 | + npm install --no-audit --no-fund >/dev/null 2>&1 |
| 86 | + node "$W/stage.js" . pkg:npm/left-pad@1.3.0 node_modules/left-pad |
| 87 | + node -e "const f='.socket/manifest.json';const fs=require('fs');fs.writeFileSync(f,fs.readFileSync(f,'utf8').replace(/\n/g,'\r\n'))" |
| 88 | + "$BIN" apply --offline --json > "$W/ap.json" 2>&1; AP=$? |
| 89 | + "$BIN" vex --offline --output "$W/v2.json" --json > /dev/null 2>&1; VX2=$? |
| 90 | + "$BIN" rollback --offline --json > "$W/rb.json" 2>&1; RB=$? |
| 91 | + echo "RESULT agent-crlf $T: apply=$AP vex=$VX2/$(vexst "$W/v2.json") rollback=$RB after_rb=[$(head20 node_modules/left-pad/index.js)]" |
| 92 | + head -c 800 "$W/ap.json"; echo |
| 93 | + echo "::endgroup::" |
| 94 | +
|
| 95 | + echo "::group::agent mode --cwd from elsewhere with deep path" |
| 96 | + D="$W/$(printf 'd%.0s' {1..60})/$(printf 'e%.0s' {1..60})/$(printf 'f%.0s' {1..60})/$(printf 'g%.0s' {1..60})"; mkdir -p "$D"; cd "$D" |
| 97 | + echo '{"name":"app","version":"1.0.0","private":true,"dependencies":{"left-pad":"1.3.0"}}' > package.json |
| 98 | + npm install --no-audit --no-fund >/dev/null 2>&1; NI=$? |
| 99 | + node "$W/stage.js" . pkg:npm/left-pad@1.3.0 node_modules/left-pad |
| 100 | + cd "$W" |
| 101 | + "$BIN" vendor --offline --json --cwd "$D" > "$W/vd.json" 2>&1; VD=$? |
| 102 | + cd "$D"; rm -rf node_modules; npm ci --no-audit --no-fund >/dev/null 2>&1; CI2=$? |
| 103 | + echo "RESULT deep-vendor $T: pathlen=${#D} install=$NI vendor=$VD ci=$CI2 left-pad=[$(head20 node_modules/left-pad/index.js)]" |
| 104 | + head -c 800 "$W/vd.json"; echo |
| 105 | + echo "::endgroup::" |
| 106 | + exit 0 |
0 commit comments