Skip to content

Commit 2f9f0b1

Browse files
nullvariantclaude
andauthored
ci: excessive security hardening (supply chain + static analysis + docs) (#336)
* ci: add supply chain security (Trivy, Cosign, SBOM, dependency-review) ## Background SLSA Level 3 provenance was already in place, but the release pipeline lacked VSIX signing, SBOM generation, and PR-level dependency checks. ## Changes - publish.yml: Add Trivy fs scan (CRITICAL/HIGH gate before publish) - publish.yml: Add Cosign keyless VSIX signing (.bundle artifact) - publish.yml: Add Syft CycloneDX SBOM generation + attestation - publish.yml: Attach sbom-cyclonedx.json and .vsix.bundle to Release - ci.yml: Add dependency-review-action (license + CVE check on PRs) - README.md: Add Supply Chain Security verification instructions All new Actions are SHA-pinned with Harden-Runner coverage. Cosign signing and SBOM attestation are soft-fail (warn on failure). 🖥️ IDE: [Cursor](https://cursor.sh) 🔌 Extension: [Claude Code](https://claude.ai/download) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Model-Raw: claude-opus-4-6 * ci: add Semgrep SAST and Socket.dev firewall to security checks ## Background CodeQL was the only SAST engine. A single engine has detection blind spots that complementary tools can cover. ## Changes - security.yml: Add Semgrep job (p/typescript, p/security-audit, p/secrets) - security.yml: Add Socket.dev firewall job (npm supply chain risk on PRs) - ci.yml: Migrate dependency-review from deny-licenses to allow-licenses - .github/dependency-review-config.yml: New config with MIT-compatible allowlist All new Actions are SHA-pinned with Harden-Runner coverage. Socket.dev requires GitHub App installation (Free tier). 🖥️ IDE: [Cursor](https://cursor.sh) 🔌 Extension: [Claude Code](https://claude.ai/download) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Model-Raw: claude-opus-4-6 * docs(git-id-switcher): add STRIDE threat model, Webview CSP policy, and OpenVEX declaration ## Background Security documentation existed only as implicit knowledge in code comments. Threat model, capability boundaries, and vulnerability impact assessment were not formalized. ## Changes - docs/THREAT_MODEL.md: STRIDE-based threat model (S2/T3/R1/I2/D3/E3) with existing mitigation mapping and residual risk assessment - docs/ARCHITECTURE.md: Add Webview CSP policy (nonce-based, future use) and Extension Capabilities table (granted + explicitly denied) - .vex/vex.json: OpenVEX declaration (zero production dependencies, devDependency CVEs do not affect end users) - .github/dependency-review-config.yml: Allow Semgrep and Socket.dev actions (CI-only, unknown license resolved) 🖥️ IDE: [Cursor](https://cursor.sh) 🔌 Extension: [Claude Code](https://claude.ai/download) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Model-Raw: claude-opus-4-6 * ci: add anti-impersonation measures (fingerprint, URL validation, typosquat reporting) ## Background VS Code Marketplace typosquatting is a growing threat. Users need a way to verify they have the authentic extension. ## Changes - README.md: Add Extension Fingerprint section (Publisher ID, Extension ID, Marketplace/Open VSX URLs) - ci.yml: Add package.json URL validation step (repository.url and homepage must match expected values) - SECURITY.md: Add typosquat reporting procedure with verification checklist (Cosign, SLSA, publisher, extension ID) - docs/THREAT_MODEL.md: Promote S3 (Impersonation) from unmitigated to Spoofing section with existing mitigations mapped 🖥️ IDE: [Cursor](https://cursor.sh) 🔌 Extension: [Claude Code](https://claude.ai/download) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Model-Raw: claude-opus-4-6 * chore: release v0.16.20 ## Background Supply chain security hardening, static analysis, threat model, and anti-impersonation measures were added across steps 1-3.5. ## Changes - CHANGELOG.md: Add 0.16.20 entry (Security + Documentation) - package.json: Bump version 0.16.19 → 0.16.20 🖥️ IDE: [Cursor](https://cursor.sh) 🔌 Extension: [Claude Code](https://claude.ai/download) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Model-Raw: claude-opus-4-6 --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent ab437c7 commit 2f9f0b1

12 files changed

Lines changed: 592 additions & 30 deletions

File tree

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Dependency Review configuration
2+
# https://github.com/actions/dependency-review-action
3+
#
4+
# Uses allow-list approach (recommended over deny-list).
5+
# Only explicitly permitted licenses pass the check.
6+
7+
fail-on-severity: moderate
8+
9+
# SPDX license identifiers compatible with MIT
10+
allow-licenses:
11+
- '0BSD'
12+
- 'Apache-2.0'
13+
- 'BlueOak-1.0.0'
14+
- 'BSD-2-Clause'
15+
- 'BSD-3-Clause'
16+
- 'CC0-1.0'
17+
- 'CC-BY-3.0'
18+
- 'CC-BY-4.0'
19+
- 'ISC'
20+
- 'MIT'
21+
- 'PSF-2.0'
22+
- 'Python-2.0'
23+
- 'Unlicense'
24+
25+
# GitHub Actions with undetectable licenses
26+
# These are CI-only tools (not bundled in VSIX), so license compatibility
27+
# with the extension's MIT license is not a concern.
28+
allow-dependencies-licenses:
29+
- 'pkg:githubactions/semgrep/semgrep-action'
30+
- 'pkg:githubactions/SocketDev/action'

.github/workflows/ci.yml

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,28 @@ jobs:
7070
shell: bash
7171
run: ls -la extensions/git-id-switcher/*.vsix
7272

73+
- name: Verify package.json URLs (anti-impersonation)
74+
shell: bash
75+
run: |
76+
cd extensions/git-id-switcher
77+
REPO_URL=$(node -e "console.log(require('./package.json').repository.url)")
78+
HOMEPAGE=$(node -e "console.log(require('./package.json').homepage)")
79+
80+
EXPECTED_REPO="https://github.com/nullvariant/nullvariant-vscode-extensions"
81+
EXPECTED_HOME_PREFIX="https://github.com/nullvariant/nullvariant-vscode-extensions"
82+
83+
if [ "$REPO_URL" != "$EXPECTED_REPO" ]; then
84+
echo "::error::repository.url mismatch: expected '$EXPECTED_REPO', got '$REPO_URL'"
85+
exit 1
86+
fi
87+
88+
if [[ "$HOMEPAGE" != "$EXPECTED_HOME_PREFIX"* ]]; then
89+
echo "::error::homepage does not start with '$EXPECTED_HOME_PREFIX': got '$HOMEPAGE'"
90+
exit 1
91+
fi
92+
93+
echo "package.json URLs verified"
94+
7395
e2e:
7496
name: E2E Tests (${{ matrix.os }})
7597
strategy:
@@ -113,3 +135,27 @@ jobs:
113135
if: runner.os != 'Linux'
114136
run: npm run test:e2e
115137
working-directory: extensions/git-id-switcher
138+
139+
dependency-review:
140+
name: Dependency Review
141+
runs-on: ubuntu-latest
142+
# Only run on pull requests (requires base/head comparison)
143+
if: github.event_name == 'pull_request'
144+
permissions:
145+
contents: read
146+
pull-requests: write
147+
148+
steps:
149+
- name: Harden Runner
150+
uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1
151+
with:
152+
egress-policy: audit
153+
154+
- name: Checkout
155+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
156+
157+
- name: Dependency Review
158+
uses: actions/dependency-review-action@2031cfc080254a8a887f58cffee85186f0e49e48 # v4.9.0
159+
with:
160+
config-file: './.github/dependency-review-config.yml'
161+
comment-summary-in-pr: always

.github/workflows/publish.yml

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,61 @@ jobs:
5050
id: version
5151
run: echo "version=${GITHUB_REF#refs/tags/git-id-switcher-v}" >> $GITHUB_OUTPUT
5252

53+
# Supply Chain Security: Trivy VSIX scan (post-package, pre-publish)
54+
# Scans the packaged VSIX for known CVEs before any publishing step
55+
- name: Scan VSIX with Trivy
56+
uses: aquasecurity/trivy-action@57a97c7e7821a5776cebc9bb87c984fa69cba8f1 # 0.35.0
57+
with:
58+
scan-type: 'fs'
59+
scan-ref: 'extensions/git-id-switcher'
60+
severity: 'CRITICAL,HIGH'
61+
exit-code: '1'
62+
63+
# Supply Chain Security: Cosign keyless signing for VSIX
64+
# Uses GitHub OIDC token (no secret key management required)
65+
- name: Install Cosign
66+
uses: sigstore/cosign-installer@ba7bc0a3fef59531c69a25acd34668d6d3fe6f22 # v4.1.0
67+
68+
- name: Sign VSIX with Cosign (keyless)
69+
id: cosign-sign
70+
continue-on-error: true
71+
run: |
72+
VSIX_FILE="extensions/git-id-switcher/git-id-switcher-${{ steps.version.outputs.version }}.vsix"
73+
VSIX_BASENAME=$(basename "$VSIX_FILE")
74+
75+
cosign sign-blob "$VSIX_FILE" \
76+
--yes \
77+
--bundle "extensions/git-id-switcher/${VSIX_BASENAME}.bundle"
78+
79+
echo "vsix_file=$VSIX_FILE" >> $GITHUB_OUTPUT
80+
echo "bundle_file=extensions/git-id-switcher/${VSIX_BASENAME}.bundle" >> $GITHUB_OUTPUT
81+
82+
- name: Warn if Cosign signing failed
83+
if: steps.cosign-sign.outcome == 'failure'
84+
run: echo "::warning::Cosign VSIX signing failed. The VSIX will be published without a Cosign signature."
85+
86+
# Supply Chain Security: SBOM generation (CycloneDX via Syft)
87+
- name: Generate SBOM (CycloneDX)
88+
uses: anchore/sbom-action@57aae528053a48a3f6235f2d9461b05fbcb7366d # v0.23.1
89+
with:
90+
path: extensions/git-id-switcher
91+
artifact-name: sbom-cyclonedx.json
92+
output-file: extensions/git-id-switcher/sbom-cyclonedx.json
93+
format: cyclonedx-json
94+
95+
# Supply Chain Security: SBOM attestation (signed with GitHub Attestation API)
96+
- name: Attest SBOM
97+
id: sbom-attest
98+
continue-on-error: true
99+
uses: actions/attest-sbom@07e74fc4e78d1aad915e867f9a094073a9f71527 # v4.0.0
100+
with:
101+
subject-path: extensions/git-id-switcher/*.vsix
102+
sbom-path: extensions/git-id-switcher/sbom-cyclonedx.json
103+
104+
- name: Warn if SBOM attestation failed
105+
if: steps.sbom-attest.outcome == 'failure'
106+
run: echo "::warning::SBOM attestation failed. The SBOM will be included in the release without attestation."
107+
53108
# SLSA Provenance: Generate attestation via GitHub Attestation API
54109
# This creates verifiable build provenance for supply chain security
55110
- name: Generate SLSA Provenance attestation
@@ -91,6 +146,8 @@ jobs:
91146
files: |
92147
extensions/git-id-switcher/*.vsix
93148
extensions/git-id-switcher/*.intoto.jsonl
149+
extensions/git-id-switcher/sbom-cyclonedx.json
150+
extensions/git-id-switcher/*.vsix.bundle
94151
generate_release_notes: true
95152
env:
96153
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/security.yml

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,55 @@ jobs:
172172
with:
173173
category: "/language:typescript"
174174

175+
semgrep:
176+
name: Semgrep SAST
177+
runs-on: ubuntu-latest
178+
# Skip forked PRs (no SARIF upload permission)
179+
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
180+
permissions:
181+
contents: read
182+
security-events: write
183+
184+
steps:
185+
- name: Harden Runner
186+
uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1
187+
with:
188+
egress-policy: audit
189+
190+
- name: Checkout repository
191+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
192+
193+
- name: Run Semgrep
194+
uses: semgrep/semgrep-action@713efdd345f3035192eaa63f56867b88e63e4e5d # v1
195+
with:
196+
config: >-
197+
p/typescript
198+
p/security-audit
199+
p/secrets
200+
201+
socket-security:
202+
name: Socket.dev Security
203+
runs-on: ubuntu-latest
204+
# Only run on pull requests (analyzes dependency changes)
205+
if: github.event_name == 'pull_request'
206+
permissions:
207+
contents: read
208+
pull-requests: write
209+
210+
steps:
211+
- name: Harden Runner
212+
uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1
213+
with:
214+
egress-policy: audit
215+
216+
- name: Checkout repository
217+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
218+
219+
- name: Socket Security Review
220+
uses: SocketDev/action@937f824ec476dfd164d4a4d9995751427b0be143 # v1
221+
with:
222+
mode: firewall
223+
175224
scorecard:
176225
name: OpenSSF Scorecard
177226
runs-on: ubuntu-latest

README.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,56 @@ git push origin git-id-switcher-v1.0.0
176176

177177
The [publish workflow](.github/workflows/publish.yml) will automatically build and publish the extension to VS Code Marketplace and Open VSX.
178178

179+
## Supply Chain Security
180+
181+
Every release includes cryptographic verification artifacts:
182+
183+
| Artifact | Description |
184+
| --------------------- | ----------------------------------- |
185+
| `*.vsix` | The extension package |
186+
| `*.vsix.intoto.jsonl` | SLSA Level 3 build provenance |
187+
| `*.vsix.bundle` | Cosign keyless signature (Sigstore) |
188+
| `sbom-cyclonedx.json` | CycloneDX SBOM with attestation |
189+
190+
### Verify VSIX signature (Cosign)
191+
192+
```bash
193+
# Download the VSIX and its .bundle from the GitHub Release, then:
194+
cosign verify-blob git-id-switcher-<version>.vsix \
195+
--bundle git-id-switcher-<version>.vsix.bundle \
196+
--certificate-identity-regexp="https://github.com/nullvariant/nullvariant-vscode-extensions/" \
197+
--certificate-oidc-issuer="https://token.actions.githubusercontent.com"
198+
```
199+
200+
### Verify SLSA provenance (GitHub CLI)
201+
202+
```bash
203+
gh attestation verify git-id-switcher-<version>.vsix \
204+
--repo nullvariant/nullvariant-vscode-extensions
205+
```
206+
207+
### Verify SBOM attestation (GitHub CLI)
208+
209+
```bash
210+
gh attestation verify git-id-switcher-<version>.vsix \
211+
--repo nullvariant/nullvariant-vscode-extensions \
212+
--predicate-type https://cyclonedx.org/bom
213+
```
214+
215+
## Extension Fingerprint
216+
217+
Use this information to verify you have the authentic Git ID Switcher extension:
218+
219+
| Field | Value |
220+
| ------------ | --------------------------------------------------------------------------------- |
221+
| Publisher | `nullvariant` |
222+
| Extension ID | `nullvariant.git-id-switcher` |
223+
| Repository | `https://github.com/nullvariant/nullvariant-vscode-extensions` |
224+
| Marketplace | `https://marketplace.visualstudio.com/items?itemName=nullvariant.git-id-switcher` |
225+
| Open VSX | `https://open-vsx.org/extension/nullvariant/git-id-switcher` |
226+
227+
If you find an extension with a similar name from a different publisher, please report it (see [SECURITY.md](SECURITY.md#reporting-typosquatting)).
228+
179229
## License
180230

181231
MIT

SECURITY.md

Lines changed: 44 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,25 @@ If you discover a security vulnerability, please report it by:
2727

2828
**Please do NOT open a public issue for security vulnerabilities.**
2929

30+
## Reporting Typosquatting
31+
32+
If you find a VS Code extension with a similar name to **Git ID Switcher** from a different publisher, it may be a typosquat attempt. Please report it:
33+
34+
1. **Report to us** via [GitHub Security Advisory](https://github.com/nullvariant/nullvariant-vscode-extensions/security/advisories/new) or email `security@nullvariant.com`
35+
2. **Report to the marketplace**:
36+
- VS Code Marketplace: Use the "Report" button on the extension page, or email `vscext@microsoft.com`
37+
- Open VSX: File an issue at [open-vsx/publish-extensions](https://github.com/open-vsx/publish-extensions/issues)
38+
39+
### How to Verify Authenticity
40+
41+
| Check | Expected Value |
42+
| ---------------- | ----------------------------------------------------------------------------------- |
43+
| Publisher | `nullvariant` |
44+
| Extension ID | `nullvariant.git-id-switcher` |
45+
| Repository URL | `https://github.com/nullvariant/nullvariant-vscode-extensions` |
46+
| VSIX signature | Verifiable via `cosign verify-blob` (see [README](README.md#supply-chain-security)) |
47+
| Build provenance | Verifiable via `gh attestation verify` (SLSA Level 3) |
48+
3049
## Security Measures
3150

3251
This repository contains VS Code extensions with the following security measures:
@@ -68,26 +87,26 @@ This section documents all secrets used in CI/CD workflows.
6887

6988
### Repository Secrets
7089

71-
| Name | Purpose | Used In | Rotation | Sensitivity |
72-
| ---- | ------- | ------- | -------- | ----------- |
73-
| RELEASE_PAT | Tag push to trigger publish workflow | auto-tag.yml | 90 days | High |
74-
| VSCE_PAT | VS Code Marketplace publishing | publish.yml, unpublish.yml | Annual | High |
75-
| OVSX_PAT | Open VSX publishing | publish.yml, unpublish.yml | Annual | High |
76-
| SONAR_TOKEN | SonarCloud code analysis | sonarcloud.yml | As needed | Medium |
77-
| CLOUDFLARE_API_TOKEN | Cloudflare Pages/R2 deployment | deploy-docs.yml, publish.yml | Annual | High |
78-
| CLOUDFLARE_ACCOUNT_ID | Cloudflare account identifier (public) | deploy-docs.yml, publish.yml | Never | Low (public ID) |
79-
| SLACK_WEBHOOK | Bot monitoring alerts | bot-monitoring.yml | As needed | Medium |
90+
| Name | Purpose | Used In | Rotation | Sensitivity |
91+
| --------------------- | -------------------------------------- | ---------------------------- | --------- | --------------- |
92+
| RELEASE_PAT | Tag push to trigger publish workflow | auto-tag.yml | 90 days | High |
93+
| VSCE_PAT | VS Code Marketplace publishing | publish.yml, unpublish.yml | Annual | High |
94+
| OVSX_PAT | Open VSX publishing | publish.yml, unpublish.yml | Annual | High |
95+
| SONAR_TOKEN | SonarCloud code analysis | sonarcloud.yml | As needed | Medium |
96+
| CLOUDFLARE_API_TOKEN | Cloudflare Pages/R2 deployment | deploy-docs.yml, publish.yml | Annual | High |
97+
| CLOUDFLARE_ACCOUNT_ID | Cloudflare account identifier (public) | deploy-docs.yml, publish.yml | Never | Low (public ID) |
98+
| SLACK_WEBHOOK | Bot monitoring alerts | bot-monitoring.yml | As needed | Medium |
8099

81100
### GitHub App Secrets (6 bots × 2 secrets each)
82101

83-
| Bot | Secrets | Used In |
84-
| --- | ------- | ------- |
102+
| Bot | Secrets | Used In |
103+
| ------- | ------------------------------------------- | --------------- |
85104
| Justice | JUSTICE_BOT_APP_ID, JUSTICE_BOT_PRIVATE_KEY | justice-bot.yml |
86-
| Luna | LUNA_BOT_APP_ID, LUNA_BOT_PRIVATE_KEY | luna-bot.yml |
87-
| Slow | SLOW_BOT_APP_ID, SLOW_BOT_PRIVATE_KEY | slow-bot.yml |
88-
| Blaze | BLAZE_BOT_APP_ID, BLAZE_BOT_PRIVATE_KEY | blaze-bot.yml |
89-
| Ciel | CIEL_BOT_APP_ID, CIEL_BOT_PRIVATE_KEY | ciel-bot.yml |
90-
| Mimi | MIMI_BOT_APP_ID, MIMI_BOT_PRIVATE_KEY | mimi-bot.yml |
105+
| Luna | LUNA_BOT_APP_ID, LUNA_BOT_PRIVATE_KEY | luna-bot.yml |
106+
| Slow | SLOW_BOT_APP_ID, SLOW_BOT_PRIVATE_KEY | slow-bot.yml |
107+
| Blaze | BLAZE_BOT_APP_ID, BLAZE_BOT_PRIVATE_KEY | blaze-bot.yml |
108+
| Ciel | CIEL_BOT_APP_ID, CIEL_BOT_PRIVATE_KEY | ciel-bot.yml |
109+
| Mimi | MIMI_BOT_APP_ID, MIMI_BOT_PRIVATE_KEY | mimi-bot.yml |
91110

92111
**Security Notes for GitHub Apps**:
93112

@@ -114,15 +133,15 @@ Marketplace publishing secrets (VSCE_PAT, OVSX_PAT) are protected by the `produc
114133

115134
### Provider Links
116135

117-
| Secret | Provider | Management URL | Expiration |
118-
| ------ | -------- | -------------- | ---------- |
119-
| RELEASE_PAT | GitHub | [GitHub Fine-grained PAT](https://github.com/settings/tokens?type=beta) | 2026-04-17 |
120-
| VSCE_PAT | Azure DevOps | [Azure DevOps Tokens](https://dev.azure.com/nullvariant/_usersSettings/tokens) | 2027-01-08 |
121-
| OVSX_PAT | Open VSX | [Open VSX Tokens](https://open-vsx.org/user-settings/tokens) | No expiration |
122-
| CLOUDFLARE_API_TOKEN | Cloudflare | [Cloudflare API Tokens](https://dash.cloudflare.com/profile/api-tokens) | No expiration |
123-
| SONAR_TOKEN | SonarCloud | [SonarCloud Security](https://sonarcloud.io/account/security) | No expiration |
124-
| GitHub App Keys | GitHub | [GitHub Apps](https://github.com/settings/apps) | No expiration |
125-
| SLACK_WEBHOOK | Slack | [Slack Apps](https://api.slack.com/apps) | No expiration |
136+
| Secret | Provider | Management URL | Expiration |
137+
| -------------------- | ------------ | ------------------------------------------------------------------------------ | ------------- |
138+
| RELEASE_PAT | GitHub | [GitHub Fine-grained PAT](https://github.com/settings/tokens?type=beta) | 2026-04-17 |
139+
| VSCE_PAT | Azure DevOps | [Azure DevOps Tokens](https://dev.azure.com/nullvariant/_usersSettings/tokens) | 2027-01-08 |
140+
| OVSX_PAT | Open VSX | [Open VSX Tokens](https://open-vsx.org/user-settings/tokens) | No expiration |
141+
| CLOUDFLARE_API_TOKEN | Cloudflare | [Cloudflare API Tokens](https://dash.cloudflare.com/profile/api-tokens) | No expiration |
142+
| SONAR_TOKEN | SonarCloud | [SonarCloud Security](https://sonarcloud.io/account/security) | No expiration |
143+
| GitHub App Keys | GitHub | [GitHub Apps](https://github.com/settings/apps) | No expiration |
144+
| SLACK_WEBHOOK | Slack | [Slack Apps](https://api.slack.com/apps) | No expiration |
126145

127146
**Token Details**:
128147

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"@context": "https://openvex.dev/ns/v0.2.0",
3+
"@id": "https://github.com/nullvariant/nullvariant-vscode-extensions/extensions/git-id-switcher/.vex/vex.json",
4+
"author": "Null;Variant <null@nullvariant.com>",
5+
"timestamp": "2026-03-15T12:00:00Z",
6+
"version": 1,
7+
"tooling": "manual",
8+
"statements": [
9+
{
10+
"vulnerability": {
11+
"@id": "https://github.com/nullvariant/nullvariant-vscode-extensions/extensions/git-id-switcher/.vex/vex.json#no-prod-deps",
12+
"name": "no-production-dependencies",
13+
"description": "This extension has zero production dependencies. All npm packages in package.json are devDependencies used only during development and CI. The published VSIX contains only compiled JavaScript with no third-party code bundled."
14+
},
15+
"products": [
16+
{
17+
"@id": "pkg:npm/git-id-switcher",
18+
"identifiers": {
19+
"purl": "pkg:npm/git-id-switcher"
20+
}
21+
}
22+
],
23+
"status": "not_affected",
24+
"justification": "vulnerable_code_not_in_execute_path",
25+
"impact_statement": "All dependencies are devDependencies. No third-party code is included in the published VSIX package. CVEs in devDependencies do not affect end users."
26+
}
27+
]
28+
}

0 commit comments

Comments
 (0)