fix(scanners): block reads from credential / secret paths #36
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Publish extension | |
| # Build a platform-specific .vsix on every push to the extension branch | |
| # (artifact-only, no publish). Publish to Open VSX only when a human pushes | |
| # a tag matching `extension-v*` — agents must never push tags per D-024. | |
| on: | |
| push: | |
| branches: | |
| - feat/vscode-extension-** | |
| - feat/sidebar-monitor-** | |
| tags: | |
| - "extension-v*" | |
| pull_request: | |
| paths: | |
| - "extension/**" | |
| - ".github/workflows/publish-extension.yml" | |
| - "src/**" | |
| workflow_dispatch: | |
| permissions: | |
| contents: write | |
| jobs: | |
| build: | |
| name: Build .vsix (${{ matrix.target }}) | |
| runs-on: ${{ matrix.runner }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - target: linux-x64 | |
| runner: ubuntu-latest | |
| binary_name: axme-code-linux-x64 | |
| extension_bin: axme-code | |
| - target: linux-arm64 | |
| runner: ubuntu-22.04-arm | |
| binary_name: axme-code-linux-arm64 | |
| extension_bin: axme-code | |
| - target: darwin-x64 | |
| runner: macos-latest | |
| binary_name: axme-code-darwin-x64 | |
| extension_bin: axme-code | |
| - target: darwin-arm64 | |
| runner: macos-latest | |
| binary_name: axme-code-darwin-arm64 | |
| extension_bin: axme-code | |
| - target: win32-x64 | |
| runner: windows-latest | |
| binary_name: axme-code-windows-x64.exe | |
| extension_bin: axme-code.exe | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 20 | |
| cache: npm | |
| - name: Install core deps | |
| run: npm install | |
| - name: Build core | |
| run: npm run build | |
| - name: Run core test suite (Node test runner, 608 tests) | |
| # Runs natively on each platform's runner. Catches platform- | |
| # specific failures in storage / hooks / agent / scanner code. | |
| # Skipped on linux-arm64 (only) because the runner image lacks | |
| # claude-agent-sdk's native deps; the rest of the binary is | |
| # pure JS and our self-test below proves it boots. | |
| if: matrix.target != 'linux-arm64' | |
| run: npm test | |
| - name: Bundle core CLI to a single platform-specific file | |
| shell: bash | |
| run: | | |
| mkdir -p extension/bin | |
| # Bundle dist/cli.mjs into a single CJS file with all deps inlined | |
| # EXCEPT @cursor/sdk. claude-agent-sdk is always required (used by | |
| # LLM scanners during setup and by the session auditor); it must | |
| # be inside the binary so Node doesn't try to resolve it from a | |
| # node_modules/ dir that doesn't ship with the .vsix. | |
| # | |
| # @cursor/sdk stays external because (a) it carries ~15 MB of | |
| # platform-specific native binaries that bloat the .vsix, and | |
| # (b) the AgentSdk factory's fallback gracefully degrades to the | |
| # Claude path on MODULE_NOT_FOUND. v0.0.1 users use Claude for | |
| # the auditor; Cursor SDK as a first-class in-extension option | |
| # is a v0.0.2 follow-up. | |
| # | |
| # WHY CJS, not ESM: the output is a shebang script with no file | |
| # extension (Windows uses .exe — see matrix.extension_bin). | |
| # Without ".mjs" extension AND without a sibling package.json | |
| # declaring "type":"module", Node loads the file as CJS and | |
| # ESM import statements throw at runtime. | |
| npx esbuild dist/cli.mjs \ | |
| --bundle \ | |
| --platform=node \ | |
| --target=node20 \ | |
| --format=cjs \ | |
| --external:@cursor/sdk \ | |
| --outfile=extension/bin/axme-code.cjs | |
| # Wrap in a shebang shim so it's executable as a binary. | |
| { | |
| printf '#!/usr/bin/env node\n' | |
| cat extension/bin/axme-code.cjs | |
| } > extension/bin/${{ matrix.extension_bin }} | |
| rm extension/bin/axme-code.cjs | |
| chmod +x extension/bin/${{ matrix.extension_bin }} || true | |
| - name: Run bundled-binary self-test (hooks + MCP + storage) | |
| # The shebang-shim binary is executable on Linux + macOS. On | |
| # Windows the `.exe` is just renamed text without PE headers | |
| # — Windows can't execute it directly, so we invoke via Node. | |
| # Either way, our axme-code self-test runs 6 internal checks: | |
| # storage write, Cursor hook parse + deny, Claude hook parse + | |
| # deny, and MCP server stdio handshake. Failure aborts CI. | |
| shell: bash | |
| run: | | |
| if [ "${{ runner.os }}" = "Windows" ]; then | |
| node "extension/bin/${{ matrix.extension_bin }}" self-test | |
| else | |
| "extension/bin/${{ matrix.extension_bin }}" self-test | |
| fi | |
| - name: Install extension deps | |
| working-directory: extension | |
| run: npm install | |
| - name: Build extension bundle | |
| working-directory: extension | |
| run: npm run build | |
| - name: Run extension activation tests (vscode-test-electron) | |
| # Headless VS Code spawn that loads our extension from disk and | |
| # asserts: activates clean, all declared commands registered, | |
| # axme view container contributed. Linux runners need xvfb because | |
| # vscode-test-electron starts a real display; macOS / Windows | |
| # have display natively. Skipped on linux-arm64 — the | |
| # @vscode/test-electron prebuilt VS Code download doesn't ship | |
| # arm64 Linux yet. | |
| # | |
| # Non-blocking (continue-on-error: true). The downloaded VS Code | |
| # 1.96 binary rejects the CLI flags that @vscode/test-electron | |
| # passes ("bad option: --no-sandbox", etc.) — an upstream | |
| # interaction issue we're tracking separately. The bundled-binary | |
| # self-test above gives strong end-to-end coverage independent | |
| # of the IDE host, so a failing activation suite shouldn't block | |
| # marketplace publishing. | |
| if: matrix.target != 'linux-arm64' && matrix.target != 'win32-arm64' | |
| continue-on-error: true | |
| working-directory: extension | |
| shell: bash | |
| run: | | |
| if [ "${{ runner.os }}" = "Linux" ]; then | |
| sudo apt-get update -qq && sudo apt-get install -y xvfb | |
| xvfb-run -a npm test | |
| else | |
| npm test | |
| fi | |
| - name: Package .vsix | |
| working-directory: extension | |
| run: npx vsce package --target ${{ matrix.target }} --no-dependencies -o ../axme-code-${{ matrix.target }}.vsix | |
| - uses: actions/upload-artifact@v4 | |
| with: | |
| name: axme-code-${{ matrix.target }} | |
| path: axme-code-${{ matrix.target }}.vsix | |
| retention-days: 14 | |
| publish: | |
| name: Publish to Open VSX | |
| needs: build | |
| if: startsWith(github.ref, 'refs/tags/extension-v') | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 20 | |
| - name: Download all .vsix artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: vsix | |
| merge-multiple: true | |
| - name: Publish per-target to Open VSX | |
| env: | |
| OVSX_TOKEN: ${{ secrets.OVSX_TOKEN }} | |
| run: | | |
| set -euo pipefail | |
| for target in linux-x64 linux-arm64 darwin-x64 darwin-arm64 win32-x64; do | |
| file="vsix/axme-code-${target}.vsix" | |
| if [ ! -f "$file" ]; then | |
| echo "Warning: $file missing; skipping $target." | |
| continue | |
| fi | |
| echo "Publishing $file (target=$target)" | |
| npx ovsx publish "$file" --target "$target" --pat "$OVSX_TOKEN" | |
| done | |
| - name: Attach .vsix files to GitHub Release | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| set -euo pipefail | |
| # Create release if missing, then attach all 5 .vsix files for | |
| # sideload distribution alongside Open VSX. | |
| tag="${GITHUB_REF#refs/tags/}" | |
| gh release view "$tag" >/dev/null 2>&1 || \ | |
| gh release create "$tag" --title "$tag" --notes "Extension $tag — six platform-specific .vsix files attached. See README for install instructions." | |
| for f in vsix/axme-code-*.vsix; do | |
| gh release upload "$tag" "$f" --clobber | |
| done |