Back to Checks
vercel

Vercel API tokens have not expired

authentication_token_not_expired
Service: authenticationSeverity: high
OfficialBuilt-inVerified
Categories:trust-boundariesvercel-hobby-plan
Resource Type:NotDefined

Vercel API tokens are assessed for expiration status to identify expired tokens or those about to expire within a configurable threshold (default: 7 days). Tokens about to expire are flagged proactively so they can be rotated before causing disruptions. Tokens without an expiration date are considered valid.

Risk

Expired tokens indicate poor token lifecycle management. Tokens about to expire risk imminent service disruption if not rotated in time. Integrations or CI/CD pipelines relying on expired or soon-to-expire tokens will fail silently.

Run this check with Prowler

Run in Prowler Cloud
Run
prowler vercel --checks authentication_token_not_expired

Recommendation

Remove expired tokens and create new ones with appropriate expiration dates. Implement a token rotation schedule to ensure tokens are refreshed before they expire. Update all integrations and automation that depend on the replaced tokens.

Remediation

Other

1Sign in to the Vercel dashboard
2Navigate to Account Settings > Tokens
3Identify any expired tokens
4Delete expired tokens that are no longer needed
5Create new tokens with appropriate expiration dates to replace expired ones
6Update any integrations or CI/CD pipelines that used the expired tokens

Check Code

from datetime import datetime, timezone
from typing import List

from prowler.lib.check.models import Check, CheckReportVercel, Severity
from prowler.providers.vercel.services.authentication.authentication_client import (
    authentication_client,
)


class authentication_token_not_expired(Check):
    """Check if API tokens have not expired or are about to expire.

    This class verifies whether each Vercel API token is still valid by
    checking its expiration date against the current time. Tokens expiring
    within a configurable threshold (default: 7 days) are flagged as
    about to expire with medium severity.
    """

    def execute(self) -> List[CheckReportVercel]:
        """Execute the Vercel Token Expiration check.

        Iterates over all tokens and checks if each token has expired or
        is about to expire soon. The threshold is configurable via
        ``days_to_expire_threshold`` in audit_config (default: 7 days).
        Tokens without an expiration date are considered valid (no expiry set).

        Returns:
            List[CheckReportVercel]: A list of reports for each token.
        """
        findings = []
        now = datetime.now(timezone.utc)
        days_to_expire_threshold = authentication_client.audit_config.get(
            "days_to_expire_threshold", 7
        )
        for token in authentication_client.tokens.values():
            report = CheckReportVercel(
                metadata=self.metadata(),
                resource=token,
                resource_name=token.name,
                resource_id=token.id,
            )

            if token.expires_at is None:
                report.status = "PASS"
                report.status_extended = (
                    f"Token '{token.name}' ({token.id}) does not have an expiration "
                    f"date set and is currently valid."
                )
            elif token.expires_at <= now:
                report.status = "FAIL"
                report.check_metadata.Severity = Severity.high
                report.status_extended = (
                    f"Token '{token.name}' ({token.id}) has expired "
                    f"on {token.expires_at.strftime('%Y-%m-%d %H:%M UTC')}."
                )
            else:
                days_left = (token.expires_at - now).days
                if days_left <= days_to_expire_threshold:
                    report.status = "FAIL"
                    report.check_metadata.Severity = Severity.medium
                    report.status_extended = (
                        f"Token '{token.name}' ({token.id}) is about to expire "
                        f"in {days_left} days "
                        f"on {token.expires_at.strftime('%Y-%m-%d %H:%M UTC')}."
                    )
                else:
                    report.status = "PASS"
                    report.status_extended = (
                        f"Token '{token.name}' ({token.id}) is valid and expires "
                        f"on {token.expires_at.strftime('%Y-%m-%d %H:%M UTC')}."
                    )

            findings.append(report)

        return findings