Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
ba54da2
chore: init feature branch for Vercel provider
alejandrobailo Feb 27, 2026
5c2b51d
feat(sdk): add Vercel provider with 30 security checks
alejandrobailo Feb 27, 2026
842dfc1
fix(vercel): remove __init__.py from test directories
alejandrobailo Feb 27, 2026
49841dd
refactor(sdk): rename environment checks to project_environment
alejandrobailo Mar 3, 2026
67fb058
fix(sdk): normalize check metadata format
alejandrobailo Mar 3, 2026
786d00d
feat(sdk): make stable branches configurable via audit_config
alejandrobailo Mar 3, 2026
f363e74
chore(sdk): remove Vercel compliance files
alejandrobailo Mar 3, 2026
1a1317c
Merge branch 'master' into feat/vercel-sdk
danibarranqueroo Mar 17, 2026
a97a8b6
chore: vercel provider revision
danibarranqueroo Mar 17, 2026
109ee80
chore: update metadata
danibarranqueroo Mar 17, 2026
a25c5d4
chore: add missing check tests
danibarranqueroo Mar 17, 2026
e583cfd
feat(vercel): add example mutelist
danibarranqueroo Mar 17, 2026
6cfa67d
chore: add vercel to outputs and to html
danibarranqueroo Mar 17, 2026
0186e9f
chore: remove cli authentication flags
danibarranqueroo Mar 17, 2026
29cc9ea
fix: remove init from tests files
danibarranqueroo Mar 17, 2026
fb62b81
fix: parser tests
danibarranqueroo Mar 18, 2026
cc7fa7d
chore: update asserts in every unit test
danibarranqueroo Mar 18, 2026
274cd07
chore: update services format
danibarranqueroo Mar 19, 2026
273c8e4
Merge branch 'master' into feat/vercel-sdk
danibarranqueroo Mar 19, 2026
f8beded
chore: fix black
danibarranqueroo Mar 19, 2026
f9ccc89
chore: update metadata
danibarranqueroo Mar 20, 2026
2d5e948
feat: scan all teams when no team is specified
danibarranqueroo Mar 20, 2026
ea5ba82
fix tests
danibarranqueroo Mar 20, 2026
db18e47
feat: add docs and modify gh workflows
danibarranqueroo Mar 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .github/labeler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ provider/googleworkspace:
- any-glob-to-any-file: "prowler/providers/googleworkspace/**"
- any-glob-to-any-file: "tests/providers/googleworkspace/**"

provider/vercel:
- changed-files:
- any-glob-to-any-file: "prowler/providers/vercel/**"
- any-glob-to-any-file: "tests/providers/vercel/**"

github_actions:
- changed-files:
- any-glob-to-any-file: ".github/workflows/*"
Expand Down Expand Up @@ -102,6 +107,8 @@ mutelist:
- any-glob-to-any-file: "tests/providers/openstack/lib/mutelist/**"
- any-glob-to-any-file: "prowler/providers/googleworkspace/lib/mutelist/**"
- any-glob-to-any-file: "tests/providers/googleworkspace/lib/mutelist/**"
- any-glob-to-any-file: "prowler/providers/vercel/lib/mutelist/**"
- any-glob-to-any-file: "tests/providers/vercel/lib/mutelist/**"

integration/s3:
- changed-files:
Expand Down
8 changes: 8 additions & 0 deletions .github/test-impact.yml
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,14 @@ modules:
- tests/providers/llm/**
e2e: []

- name: sdk-vercel
match:
- prowler/providers/vercel/**
- prowler/compliance/vercel/**
tests:
- tests/providers/vercel/**
e2e: []

# ============================================
# SDK - Lib modules
# ============================================
Expand Down
24 changes: 24 additions & 0 deletions .github/workflows/sdk-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,30 @@ jobs:
flags: prowler-py${{ matrix.python-version }}-googleworkspace
files: ./googleworkspace_coverage.xml

# Vercel Provider
- name: Check if Vercel files changed
if: steps.check-changes.outputs.any_changed == 'true'
id: changed-vercel
uses: tj-actions/changed-files@7dee1b0c1557f278e5c7dc244927139d78c0e22a # v47.0.4
with:
files: |
./prowler/**/vercel/**
./tests/**/vercel/**
./poetry.lock

- name: Run Vercel tests
if: steps.changed-vercel.outputs.any_changed == 'true'
run: poetry run pytest -n auto --cov=./prowler/providers/vercel --cov-report=xml:vercel_coverage.xml tests/providers/vercel

- name: Upload Vercel coverage to Codecov
if: steps.changed-vercel.outputs.any_changed == 'true'
uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5.5.2
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
with:
flags: prowler-py${{ matrix.python-version }}-vercel
files: ./vercel_coverage.xml

# Lib
- name: Check if Lib files changed
if: steps.check-changes.outputs.any_changed == 'true'
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ Every AWS provider scan will enqueue an Attack Paths ingestion job automatically
| Image | N/A | N/A | N/A | N/A | Official | CLI, API |
| Google Workspace | 1 | 1 | 0 | 1 | Official | CLI |
| OpenStack | 27 | 4 | 0 | 8 | Official | UI, API, CLI |
| Vercel | 30 | 6 | 0 | 5 | Official | CLI |
| NHN | 6 | 2 | 1 | 0 | Unofficial | CLI |

> [!Note]
Expand Down
7 changes: 7 additions & 0 deletions docs/docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,13 @@
"user-guide/providers/openstack/getting-started-openstack",
"user-guide/providers/openstack/authentication"
]
},
{
"group": "Vercel",
"pages": [
"user-guide/providers/vercel/getting-started-vercel",
"user-guide/providers/vercel/authentication"
]
}
]
},
Expand Down
1 change: 1 addition & 0 deletions docs/introduction.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ The supported providers right now are:
| [Infra as Code](/user-guide/providers/iac/getting-started-iac) | Official | Repositories | UI, API, CLI |
| [MongoDB Atlas](/user-guide/providers/mongodbatlas/getting-started-mongodbatlas) | Official | Organizations | UI, API, CLI |
| [OpenStack](/user-guide/providers/openstack/getting-started-openstack) | Official | Projects | UI, API, CLI |
| [Vercel](/user-guide/providers/vercel/getting-started-vercel) | Official | Teams / Projects | CLI |
| [LLM](/user-guide/providers/llm/getting-started-llm) | Official | Models | CLI |
| [Image](/user-guide/providers/image/getting-started-image) | Official | Container Images | CLI, API |
| [Google Workspace](/user-guide/providers/googleworkspace/getting-started-googleworkspace) | Official | Domains | CLI |
Expand Down
137 changes: 137 additions & 0 deletions docs/user-guide/providers/vercel/authentication.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
---
title: "Vercel Authentication in Prowler"
---

import { VersionBadge } from "/snippets/version-badge.mdx"

<VersionBadge version="5.21.0" />

Prowler for Vercel authenticates using an **API Token**.

## Required Permissions

Prowler requires read-only access to Vercel teams, projects, deployments, domains, and security settings. The API Token must have access to the target team scope.

<Note>
Vercel API Tokens inherit the permissions of the user that created them. Ensure the user has at least a **Viewer** role on the team to be scanned.
</Note>

| Resource | Access | Description |
|----------|--------|-------------|
| Teams | Read | Required to list teams, members, and SSO configuration |
| Projects | Read | Required to list projects, environment variables, and deployment protection settings |
| Deployments | Read | Required to list deployments and protection status |
| Domains | Read | Required to list domains, DNS records, and SSL certificates |
| Firewall | Read | Required to read WAF rules, rate limiting, and IP blocking configuration |

---

## API Token

### Step 1: Create an API Token

1. Log into the [Vercel Dashboard](https://vercel.com/dashboard).
2. Click the account avatar in the bottom-left corner and select "Settings".

![Vercel Account Settings](/user-guide/providers/vercel/images/vercel-account-settings.png)

3. In the left sidebar, click "Tokens".
4. Under **Create Token**, enter a descriptive name (e.g., "Prowler Scan").
5. Select the **Scope** — choose the team to be scanned or "Full Account" for all teams.
6. Set an **Expiration** date, or select "No expiration" for continuous scanning.
7. Click **Create**.

![Create Vercel Token](/user-guide/providers/vercel/images/vercel-create-token.png)

8. Copy the token immediately.

<Warning>
Vercel only displays the token once. Copy it immediately and store it securely. If lost, a new token must be created.
</Warning>

### Step 2: Provide the Token to Prowler

Export the token as an environment variable:

```console
export VERCEL_TOKEN="your-api-token-here"
prowler vercel
```

---

## Team Scoping (Optional)

By default, Prowler auto-discovers all teams the authenticated user belongs to and scans each one. To restrict the scan to a specific team, provide the Team ID.

### Locate the Team ID

1. In the Vercel Dashboard, navigate to "Settings" for the target team.
2. Scroll down to the **Team ID** section and copy the value.

![Vercel Team ID](/user-guide/providers/vercel/images/vercel-team-id.png)

### Provide the Team ID to Prowler

Export the Team ID as an environment variable:

```console
export VERCEL_TOKEN="your-api-token-here"
export VERCEL_TEAM="team_Yj41RYnEfdjpqxzAecFgwYAR"
prowler vercel
```

---

## Environment Variables Reference

| Variable | Required | Description |
|----------|----------|-------------|
| `VERCEL_TOKEN` | Yes | Vercel API Bearer Token |
| `VERCEL_TEAM` | No | Team ID or slug to scope the scan to a single team |

---

## Best Practices

- **Create a dedicated token for Prowler** — Avoid reusing tokens shared with other integrations.
- **Use environment variables** — Never hardcode credentials in scripts or commands.
- **Scope tokens to specific teams** — When possible, limit token access to the team being scanned.
- **Set token expiration** — Use time-limited tokens and rotate them regularly.
- **Use least privilege** — Assign the Viewer role to the user creating the token unless write access is explicitly needed.

---

## Troubleshooting

### "Vercel credentials not found" Error

This error occurs when no API Token is provided. Ensure the `VERCEL_TOKEN` environment variable is set:

```console
export VERCEL_TOKEN="your-api-token-here"
```

### "Invalid or expired Vercel API token" Error

- Verify the API Token is correct and has not expired.
- Check that the token has not been revoked in the Vercel Dashboard under "Settings" > "Tokens".

### "Insufficient permissions" Error

- Ensure the user that created the token has at least a **Viewer** role on the target team.
- If scanning a specific team, verify the token scope includes that team.

### "Team not found or not accessible" Error

This error occurs when the provided `VERCEL_TEAM` value does not match an accessible team. Verify the Team ID is correct:

1. Navigate to the team "Settings" in the Vercel Dashboard.
2. Copy the exact **Team ID** value from the settings page.

### "Rate limit exceeded" Error

Vercel applies rate limits to API requests. Prowler automatically retries rate-limited requests up to 3 times with exponential backoff. If this error persists:

- Reduce the number of projects being scanned in a single run using the `--project` argument.
- Wait a few minutes and retry the scan.
108 changes: 108 additions & 0 deletions docs/user-guide/providers/vercel/getting-started-vercel.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
---
title: "Getting Started With Vercel on Prowler"
---

import { VersionBadge } from "/snippets/version-badge.mdx"

Prowler for Vercel scans teams and projects for security misconfigurations, including deployment protection, environment variable exposure, WAF rules, domain configuration, team access controls, and more.

## Prerequisites

Set up authentication for Vercel with the [Vercel Authentication](/user-guide/providers/vercel/authentication) guide before starting:

- Create a Vercel API Token with access to the target team
- Identify the Team ID (optional, required to scope the scan to a single team)

## Prowler CLI

<VersionBadge version="5.21.0" />

### Step 1: Set Up Authentication

Follow the [Vercel Authentication](/user-guide/providers/vercel/authentication) guide to create an API Token, then export it:

```console
export VERCEL_TOKEN="your-api-token-here"
```

Optionally, scope the scan to a specific team:

```console
export VERCEL_TEAM="team_Yj41RYnEfdjpqxzAecFgwYAR"
```

### Step 2: Run the First Scan

Run a baseline scan after credentials are configured:

```console
prowler vercel
```

Prowler automatically discovers all teams accessible with the provided token and runs security checks against them.

### Step 3: Filter the Scan Scope (Optional)

#### Filter by Team

To scan a specific team, set the `VERCEL_TEAM` environment variable with the Team ID or slug:

```console
export VERCEL_TEAM="team_Yj41RYnEfdjpqxzAecFgwYAR"
prowler vercel
```

<Note>
When no team is specified, Prowler auto-discovers all teams the authenticated user belongs to and scans each one.
</Note>

#### Filter by Project

To scan only specific projects, use the `--project` argument:

```console
prowler vercel --project my-project-name
```

Multiple projects can be specified:

```console
prowler vercel --project my-project-name another-project
```

Project IDs are also supported:

```console
prowler vercel --project prj_abc123def456
```

### Step 4: Use a Custom Configuration (Optional)

Prowler uses a configuration file to customize provider behavior. The Vercel configuration includes:

```yaml
vercel:
# Maximum number of retries for API requests (default is 3)
max_retries: 3
```

To use a custom configuration:

```console
prowler vercel --config-file /path/to/config.yaml
```

---

## Supported Services

Prowler for Vercel includes security checks across the following services:

| Service | Description |
|---------|-------------|
| **Authentication** | Token expiration and staleness checks |
| **Deployment** | Preview deployment access and production stability |
| **Domain** | DNS configuration, SSL certificates, and wildcard exposure |
| **Project** | Deployment protection, environment variable security, fork protection, and skew protection |
| **Security** | Web Application Firewall (WAF), rate limiting, IP blocking, and managed rulesets |
| **Team** | SSO enforcement, directory sync, member access, and invitation hygiene |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions prowler/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@

All notable changes to the **Prowler SDK** are documented in this file.

## [5.22.0] (Prowler UNRELEASED)

### 🚀 Added

- `Vercel` provider support with 30 checks [(#10189)](https://github.com/prowler-cloud/prowler/pull/10189)

---

## [5.21.0] (Prowler v5.21.0)

### 🚀 Added
Expand Down
5 changes: 5 additions & 0 deletions prowler/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@
from prowler.providers.nhn.models import NHNOutputOptions
from prowler.providers.openstack.models import OpenStackOutputOptions
from prowler.providers.oraclecloud.models import OCIOutputOptions
from prowler.providers.vercel.models import VercelOutputOptions


def prowler():
Expand Down Expand Up @@ -385,6 +386,10 @@ def prowler():
output_options = OpenStackOutputOptions(
args, bulk_checks_metadata, global_provider.identity
)
elif provider == "vercel":
output_options = VercelOutputOptions(
args, bulk_checks_metadata, global_provider.identity
)

# Run the quick inventory for the provider if available
if hasattr(args, "quick_inventory") and args.quick_inventory:
Expand Down
1 change: 1 addition & 0 deletions prowler/config/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class Provider(str, Enum):
ALIBABACLOUD = "alibabacloud"
OPENSTACK = "openstack"
IMAGE = "image"
VERCEL = "vercel"


# Providers that delegate scanning to an external tool (e.g. Trivy, promptfoo)
Expand Down
8 changes: 8 additions & 0 deletions prowler/config/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -609,3 +609,11 @@ cloudflare:
# Maximum number of retries for API requests (default is 2)
# Set to 0 to disable retries
max_retries: 3

# Vercel Configuration
vercel:
# vercel.deployment_production_uses_stable_target
# Branches considered stable for production deployments
stable_branches:
- "main"
- "master"
Loading
Loading