-
Notifications
You must be signed in to change notification settings - Fork 2k
feat(sdk): add Vercel provider with 30 security checks #10189
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
alejandrobailo
wants to merge
24
commits into
master
Choose a base branch
from
feat/vercel-sdk
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+9,071
−3
Open
Changes from 11 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 5c2b51d
feat(sdk): add Vercel provider with 30 security checks
alejandrobailo 842dfc1
fix(vercel): remove __init__.py from test directories
alejandrobailo 49841dd
refactor(sdk): rename environment checks to project_environment
alejandrobailo 67fb058
fix(sdk): normalize check metadata format
alejandrobailo 786d00d
feat(sdk): make stable branches configurable via audit_config
alejandrobailo f363e74
chore(sdk): remove Vercel compliance files
alejandrobailo 1a1317c
Merge branch 'master' into feat/vercel-sdk
danibarranqueroo a97a8b6
chore: vercel provider revision
danibarranqueroo 109ee80
chore: update metadata
danibarranqueroo a25c5d4
chore: add missing check tests
danibarranqueroo e583cfd
feat(vercel): add example mutelist
danibarranqueroo 6cfa67d
chore: add vercel to outputs and to html
danibarranqueroo 0186e9f
chore: remove cli authentication flags
danibarranqueroo 29cc9ea
fix: remove init from tests files
danibarranqueroo fb62b81
fix: parser tests
danibarranqueroo cc7fa7d
chore: update asserts in every unit test
danibarranqueroo 274cd07
chore: update services format
danibarranqueroo 273c8e4
Merge branch 'master' into feat/vercel-sdk
danibarranqueroo f8beded
chore: fix black
danibarranqueroo f9ccc89
chore: update metadata
danibarranqueroo 2d5e948
feat: scan all teams when no team is specified
danibarranqueroo ea5ba82
fix tests
danibarranqueroo db18e47
feat: add docs and modify gh workflows
danibarranqueroo File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
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
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
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
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
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
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
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
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
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
Empty file.
Empty file.
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,126 @@ | ||
| from prowler.exceptions.exceptions import ProwlerException | ||
|
|
||
|
|
||
| class VercelBaseException(ProwlerException): | ||
| """Base exception for Vercel provider errors.""" | ||
|
|
||
| VERCEL_ERROR_CODES = { | ||
| (13000, "VercelCredentialsError"): { | ||
| "message": "Vercel credentials not found or invalid.", | ||
| "remediation": "Set the VERCEL_TOKEN environment variable or pass --vercel-token with a valid Vercel API token. Generate one at https://vercel.com/account/tokens.", | ||
| }, | ||
| (13001, "VercelAuthenticationError"): { | ||
| "message": "Authentication to Vercel API failed.", | ||
| "remediation": "Verify your Vercel API token is valid and has not expired. Check at https://vercel.com/account/tokens.", | ||
| }, | ||
| (13002, "VercelSessionError"): { | ||
| "message": "Failed to create a Vercel API session.", | ||
| "remediation": "Check network connectivity and ensure the Vercel API is reachable at https://api.vercel.com.", | ||
| }, | ||
| (13003, "VercelIdentityError"): { | ||
| "message": "Failed to retrieve Vercel identity information.", | ||
| "remediation": "Ensure the API token has permissions to read user and team information.", | ||
| }, | ||
| (13004, "VercelInvalidTeamError"): { | ||
| "message": "The specified Vercel team was not found or is not accessible.", | ||
| "remediation": "Verify the team ID or slug is correct and that your token has access to the team.", | ||
| }, | ||
| (13005, "VercelInvalidProviderIdError"): { | ||
| "message": "The provided Vercel provider ID is invalid.", | ||
| "remediation": "Ensure the provider UID matches a valid Vercel team ID or user ID format.", | ||
| }, | ||
| (13006, "VercelAPIError"): { | ||
| "message": "An error occurred while calling the Vercel API.", | ||
| "remediation": "Check the Vercel API status at https://www.vercel-status.com/ and retry the request.", | ||
| }, | ||
| (13007, "VercelRateLimitError"): { | ||
| "message": "Rate limited by the Vercel API.", | ||
| "remediation": "Wait and retry. Vercel API rate limits vary by endpoint. See https://vercel.com/docs/rest-api#rate-limits.", | ||
| }, | ||
| (13008, "VercelPlanLimitationError"): { | ||
| "message": "This feature requires a higher Vercel plan.", | ||
| "remediation": "Some security features (e.g., WAF managed rulesets) require Vercel Enterprise. Upgrade your plan or skip these checks.", | ||
| }, | ||
| } | ||
|
|
||
| def __init__(self, code, file=None, original_exception=None, message=None): | ||
| provider = "Vercel" | ||
| error_info = self.VERCEL_ERROR_CODES.get((code, self.__class__.__name__)) | ||
| if error_info is None: | ||
| error_info = { | ||
| "message": message or "Unknown Vercel error.", | ||
| "remediation": "Check the Vercel API documentation for more details.", | ||
| } | ||
| elif message: | ||
| error_info = error_info.copy() | ||
| error_info["message"] = message | ||
| super().__init__( | ||
| code=code, | ||
| source=provider, | ||
| file=file, | ||
| original_exception=original_exception, | ||
| error_info=error_info, | ||
| ) | ||
|
|
||
|
|
||
| class VercelCredentialsError(VercelBaseException): | ||
| def __init__(self, file=None, original_exception=None, message=None): | ||
| super().__init__( | ||
| 13000, file=file, original_exception=original_exception, message=message | ||
| ) | ||
|
|
||
|
|
||
| class VercelAuthenticationError(VercelBaseException): | ||
| def __init__(self, file=None, original_exception=None, message=None): | ||
| super().__init__( | ||
| 13001, file=file, original_exception=original_exception, message=message | ||
| ) | ||
|
|
||
|
|
||
| class VercelSessionError(VercelBaseException): | ||
| def __init__(self, file=None, original_exception=None, message=None): | ||
| super().__init__( | ||
| 13002, file=file, original_exception=original_exception, message=message | ||
| ) | ||
|
|
||
|
|
||
| class VercelIdentityError(VercelBaseException): | ||
| def __init__(self, file=None, original_exception=None, message=None): | ||
| super().__init__( | ||
| 13003, file=file, original_exception=original_exception, message=message | ||
| ) | ||
|
|
||
|
|
||
| class VercelInvalidTeamError(VercelBaseException): | ||
| def __init__(self, file=None, original_exception=None, message=None): | ||
| super().__init__( | ||
| 13004, file=file, original_exception=original_exception, message=message | ||
| ) | ||
|
|
||
|
|
||
| class VercelInvalidProviderIdError(VercelBaseException): | ||
| def __init__(self, file=None, original_exception=None, message=None): | ||
| super().__init__( | ||
| 13005, file=file, original_exception=original_exception, message=message | ||
| ) | ||
|
|
||
|
|
||
| class VercelAPIError(VercelBaseException): | ||
| def __init__(self, file=None, original_exception=None, message=None): | ||
| super().__init__( | ||
| 13006, file=file, original_exception=original_exception, message=message | ||
| ) | ||
|
|
||
|
|
||
| class VercelRateLimitError(VercelBaseException): | ||
| def __init__(self, file=None, original_exception=None, message=None): | ||
| super().__init__( | ||
| 13007, file=file, original_exception=original_exception, message=message | ||
| ) | ||
|
|
||
|
|
||
| class VercelPlanLimitationError(VercelBaseException): | ||
| def __init__(self, file=None, original_exception=None, message=None): | ||
| super().__init__( | ||
| 13008, file=file, original_exception=original_exception, message=message | ||
| ) |
Empty file.
Empty file.
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| def init_parser(self): | ||
| """Init the Vercel provider CLI parser.""" | ||
| vercel_parser = self.subparsers.add_parser( | ||
| "vercel", | ||
| parents=[self.common_providers_parser], | ||
| help="Vercel Provider", | ||
| ) | ||
|
|
||
| # Authentication | ||
| auth_group = vercel_parser.add_argument_group("Authentication") | ||
| auth_group.add_argument( | ||
| "--vercel-token", | ||
| nargs="?", | ||
| default=None, | ||
| metavar="TOKEN", | ||
| help="Vercel API Bearer Token. Falls back to VERCEL_TOKEN environment variable.", | ||
| ) | ||
|
|
||
| # Scope | ||
| scope_group = vercel_parser.add_argument_group("Scope") | ||
| scope_group.add_argument( | ||
| "--vercel-team", | ||
| nargs="?", | ||
| default=None, | ||
| metavar="TEAM_ID", | ||
| help="Vercel Team ID or slug to scope the scan. Falls back to VERCEL_TEAM environment variable.", | ||
| ) | ||
| scope_group.add_argument( | ||
| "--project", | ||
| "--projects", | ||
| nargs="*", | ||
| default=None, | ||
| metavar="PROJECT", | ||
| help="Filter scan to specific Vercel project names or IDs.", | ||
| ) |
Empty file.
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| from prowler.lib.check.models import CheckReportVercel | ||
| from prowler.lib.mutelist.mutelist import Mutelist | ||
| from prowler.lib.outputs.utils import unroll_dict, unroll_tags | ||
|
|
||
|
|
||
| class VercelMutelist(Mutelist): | ||
| """Vercel-specific mutelist helper.""" | ||
|
|
||
| def is_finding_muted( | ||
| self, | ||
| finding: CheckReportVercel, | ||
| team_id: str, | ||
| ) -> bool: | ||
| return self.is_muted( | ||
| team_id, | ||
| finding.check_metadata.CheckID, | ||
| "global", # Vercel is a global service | ||
| finding.resource_id or finding.resource_name, | ||
| unroll_dict(unroll_tags(finding.resource_tags)), | ||
| ) | ||
Empty file.
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.