### Full tuned config example Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/configuration.md Example of a complete Checkpoint configuration array. It enables ComposerAuditCheck and EnvironmentCheck, disables NpmAuditCheck for PHP-only projects, registers a custom check, and sets package freshness, autoload whitelist, suppression hashes, and excluded paths. Comments show defaults and commented-out options. ```php use Checkpoint\Checks; return [ 'checks' => [ Checks\ComposerAuditCheck::class => true, Checks\NpmAuditCheck::class => false, // PHP-only project Checks\EnvironmentCheck::class => true, // ... all others default to enabled if omitted ], 'extra_checks' => [ \App\Security\MyCustomCheck::class, ], 'package_freshness' => [ 'minimum_age_days' => 3, 'whitelist' => [ 'andreapollastri/checkpoint', // 'vendor/package', ], ], 'suspicious_autoload' => [ 'whitelist' => [ // 'my-org/internal-helpers', // 'acme/*', ], ], 'suppressed' => [ // 'a1b2c3d4e5f6', ], 'exclude_paths' => [ // 'storage/app/mounted-data', ], ]; ``` -------------------------------- ### Basic install (interactive) Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/install-hooks-command.md Runs the install-hooks command interactively, prompting for confirmation before modifying composer.json. ```bash php artisan checkpoint:install-hooks ``` -------------------------------- ### Install and set up Safe-Chain npm shim Source: https://github.com/andreapollastri/checkpoint/blob/main/docs/index.html Installs Safe-Chain globally and runs its setup. Safe-Chain is a free shell shim that blocks known-malicious npm packages before their install scripts run. Use it as a safety net when running npm on the host, such as on CI runners or machines without Docker. ```bash npm install -g @aikidosec/safe-chain safe-chain setup ``` -------------------------------- ### Basic EolVersionCheck usage Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/checks/supply-chain.md Basic example: creates an EolVersionCheck with base_path(), runs it, and prints details if status is not PASS. ```php use Checkpoint\Checks\EolVersionCheck; $result = (new EolVersionCheck(base_path()))->run(); if ($result->status !== CheckResult::PASS) { foreach ($result->details as $detail) { echo " ⚑ $detail\n"; } } ``` -------------------------------- ### ComposerAuditCheck preconditions handled Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/checks/process-audit.md Example showing how to check for missing composer.lock before running, which causes run() to return warn. ```php $lockMissing = ! file_exists(base_path().'/composer.lock'); if ($lockMissing) { /* run() returns warn */ } ``` -------------------------------- ### PackageFreshnessCheck extended usage with whitelist Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/checks/supply-chain.md Non-trivial example with extended freshness window (7 days) and whitelist. Iterates over details and prints hash for each failure. ```php use Checkpoint\Checks\PackageFreshnessCheck; $check = new PackageFreshnessCheck( basePath: base_path(), minimumAgeDays: 7, whitelist: ['acme/critical-patch', 'andreapollistri/checkpoint'], ); $result = $check->run(); if ($result->status === CheckResult::FAIL) { foreach ($result->details as $detail) { $hash = $result->hashFor($check->name(), $detail); echo " ✗ $detail [{$hash}]\n"; } } ``` -------------------------------- ### Unattended install for CI Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/install-hooks-command.md Runs the install-hooks command with --no-interaction to skip prompts, suitable for CI environments. ```bash php artisan checkpoint:install-hooks --no-interaction ``` -------------------------------- ### PackageFreshnessCheck basic usage Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/checks/supply-chain.md Basic example of running PackageFreshnessCheck with default minimumAgeDays = 3 and empty whitelist. ```php use Checkpoint\Checks\PackageFreshnessCheck; $result = (new PackageFreshnessCheck(base_path()))->run(); // default minimumAgeDays = 3, empty whitelist ``` -------------------------------- ### hashFinding example Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/check-result.md Computes a stable 12-character suppression hash. Line numbers are stripped from the detail before hashing, so refactors that shift lines do not invalidate the suppression. The example shows the expected usage and comment about stability. ```php CheckResult::hashFinding('Hardcoded Secrets', 'app/Models/User.php:14 — $secret = "x"'); // stable 12-char hex, unchanged if line 14 becomes line 22 ``` -------------------------------- ### ComposerAuditCheck basic usage Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/checks/process-audit.md Basic example of running ComposerAuditCheck and handling a fail result by printing each detail. ```php use Checkpoint\Checks\ComposerAuditCheck; $result = (new ComposerAuditCheck(base_path()))->run(); if ($result->status === CheckResult::FAIL) { foreach ($result->details as $detail) { echo "✗ $detail\n"; } } ``` -------------------------------- ### Run EnvironmentCheck and print warnings Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/checks/config-file.md Example usage of EnvironmentCheck. It runs the check with base_path() and prints the message and each detail when the status is CheckResult::WARN. ```php use Checkpoint\Checks\EnvironmentCheck; $result = (new EnvironmentCheck(base_path()))->run(); if ($result->status === CheckResult::WARN) { echo $result->message.PHP_EOL; foreach ($result->details as $detail) { echo " ⚑ $detail\n"; } } ``` -------------------------------- ### Human table output example Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/scan-command.md Example of the human-readable table output for each check, showing PASS, WARN, and FAIL status blocks, followed by a summary line and result line. ```text PASS Composer CVE Audit No known CVEs in Composer dependencies. WARN Environment Configuration 3 environment issue(s) found. ⚑ APP_DEBUG is true — full stack traces will be exposed to end users. [5c4b3a2d1e0f] FAIL Hardcoded Secrets 3 potential hardcoded secret(s) found. ✗ app/Services/PaymentService.php:14 — 'api_key' => 'sk_live_…' [a1b2c3d4e5f6] ``` -------------------------------- ### Inspect merged config from application code Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/checkpoint-service-provider.md PHP example using the Laravel helper config() to read a value from the merged package config, with a default of 3. ```php // Laravel helper; values come from the merged package config. $minimumAgeDays = config('checkpoint.package_freshness.minimum_age_days', 3); ``` -------------------------------- ### Run Checkpoint inside Docker container Source: https://github.com/andreapollastri/checkpoint/blob/main/README.md Typical workflow to run Composer install, npm install, and the Checkpoint scan inside a Docker container to limit the blast radius of untrusted install scripts. Use this instead of running installs directly on the host. ```bash docker compose up -d docker compose exec app composer install docker compose exec app npm install docker compose exec app php artisan checkpoint:scan ``` -------------------------------- ### EnvironmentCheck Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/checks/config-file.md Documentation for the EnvironmentCheck class, including constructor, methods, and usage example. ```APIDOC ## EnvironmentCheck ### Description Checks the Laravel environment configuration for common production issues. ### Constructor `public function __construct(private readonly string $basePath)` #### Parameters - **$basePath** (string) - Required - Project root. ### Methods #### `name(): string` Returns the check name `'Environment Configuration'`. #### `run(): CheckResult` Reads live Laravel runtime config via `\config()` and checks for `.env` existence. Returns `warn` if any issue exists, otherwise `pass` with message `'Environment configuration looks good.'`. ##### Issue Conditions 1. `\config('app.debug') === true` - `APP_DEBUG is true — full stack traces will be exposed to end users.` 2. `\config('app.env')` in `['local', 'development', 'dev']` - `APP_ENV is "{value}" — set to "production" in production environments.` 3. `empty(\config('app.key'))` - `APP_KEY is not set — encryption, sessions and cookies are insecure.` 4. `! file_exists($basePath.'/.env')` - `.env file not found.` 5. `\config('app.url')` contains `localhost` or `127.0.0.1` - `APP_URL is set to "{value}" — update it for production.` 6. `\config('session.secure') !== true` - `SESSION_SECURE_COOKIE is not enabled — session cookies will be sent over plain HTTP.` 7. `\config('session.driver', 'file') === 'array'` - `Session driver is "array" — sessions will not persist between requests.` ### Example ```php use Checkpoint\Checks\EnvironmentCheck; $result = (new EnvironmentCheck(base_path()))->run(); if ($result->status === CheckResult::WARN) { echo $result->message.PHP_EOL; foreach ($result->details as $detail) { echo " ⚑ $detail\n"; } } ``` ``` -------------------------------- ### Example scan output Source: https://github.com/andreapollastri/checkpoint/blob/main/README.md Example terminal output from running the Checkpoint scanner, showing a summary of passed, failed, and warning checks, including hardcoded secrets, path traversal risks, and environment configuration issues. ```text ┌─┐┬ ┬┌─┐┌─┐┬┌─┌─┐┌─┐┬┌┐┌┌┬┐ │ ├─┤├┤ │ ├┴┐├─┘│ │││││ │ └─┘┴ ┴└─┘└─┘┴ ┴┴ └─┘┴┘└┘ ┴ Laravel Security Scanner — andreapollastri/checkpoint Scanning: /var/www/my-app 26/26 [============================] 100% Hardcoded Secrets PASS Composer CVE Audit No known CVEs in Composer dependencies. FAIL Hardcoded Secrets 3 potential hardcoded secret(s) found. ✗ app/Services/PaymentService.php:14 — 'api_key' => 'sk_live_abc123…' [a1b2c3d4e5f6] ✗ config/services.php:8 — $secret = 'supersecretvalue' [9f8e7d6c5b4a] ✗ app/Http/Controllers/WebhookController.php:31 — 'api_key' => 'ghp_…' [3e2d1c0b9a8f] FAIL Path Traversal Risks 1 potential path traversal risk(s) found. ✗ app/Http/Controllers/DownloadController.php:24 — Storage::get($request->path) [7b6a5f4e3d2c] WARN Environment Configuration 3 environment issue(s) found. ⚑ APP_DEBUG is true — full stack traces will be exposed to end users. [5c4b3a2d1e0f] ⚑ SESSION_SECURE_COOKIE is not enabled. [1a2b3c4d5e6f] ⚑ APP_URL is set to "http://localhost" — update it for production. [6e5d4c3b2a1f] ───────────────────────────────────────────────────────── Summary 19 passed 4 warning(s) 2 failed (25 checks total) Scan result: FAIL — fix the issues above before deploying. ``` -------------------------------- ### Run Checkpoint scan in Docker container Source: https://github.com/andreapollastri/checkpoint/blob/main/docs/index.html Runs the Checkpoint scan inside a disposable Docker container, isolating installs and scans from the host. Recommended for day-to-day installs to limit the blast radius if a package turns hostile during install. Works with Docker Compose, a devcontainer, or a CI image with Composer and Node. ```bash docker compose exec app php artisan checkpoint:scan ``` -------------------------------- ### Run OpenRedirectCheck Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/checks/file-scan-ii.md Runs the OpenRedirectCheck against the base path. The comment shows an example redirect() call with unvalidated input that produces a WARN finding. ```php use Checkpoint\Checks\OpenRedirectCheck; $result = (new OpenRedirectCheck(base_path()))->run(); // redirect($request->input('next')) -> WARN finding ``` -------------------------------- ### SensitiveExposureCheck usage example Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/checks/file-scan-i.md Creates a SensitiveExposureCheck instance with base_path() and runs it. If the result status is WARN, it iterates over details and prints each detail with a warning symbol. ```php use Checkpoint\Checks\SensitiveExposureCheck; $result = (new SensitiveExposureCheck(base_path()))->run(); if ($result->status === CheckResult::WARN) { foreach ($result->details as $detail) { echo " ⚑ $detail\n"; } } ``` -------------------------------- ### JSON output shape example Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/scan-command.md Example of the JSON output produced with --json. It is an array of objects, each with fields check, status, message, details, and hashes. ```json [ { "check": "Composer CVE Audit", "status": "pass", "message": "No known CVEs in Composer dependencies.", "details": [], "hashes": [] }, { "check": "Hardcoded Secrets", "status": "fail", "message": "3 potential hardcoded secret(s) found.", "details": ["app/Services/PaymentService.php:14 — 'api_key' => 'sk_live_…'"], "hashes": ["a1b2c3d4e5f6"] } ] ``` -------------------------------- ### Example checkpoint:scan output with PASS/FAIL/WARN lines Source: https://github.com/andreapollastri/checkpoint/blob/main/docs/index.html Shows the terminal output of the 'php artisan checkpoint:scan' command. It lists a Composer CVE audit that passed, a hardcoded secret detection that failed, an environment configuration warning about APP_DEBUG being true, and a summary with counts and final status. ```text PASS Composer CVE Audit No known CVEs in Composer dependencies. FAIL Hardcoded Secrets ✗ app/Services/PaymentService.php:14 [a1b2c3d4e5f6] WARN Environment Configuration ⚑ APP_DEBUG is true [5c4b3a2d1e0f] ───────────────────────────────── Summary 23 passed 2 warn 1 failed Scan result: FAIL ``` -------------------------------- ### InsecureRngCheck usage example Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/checks/file-scan-ii.md Example of running the InsecureRngCheck on a base path. The check flags lines containing both an insecure RNG function and a security keyword, as shown in the comment. ```php use Checkpoint\Checks\InsecureRngCheck; $result = (new InsecureRngCheck(base_path()))->run(); // $resetToken = uniqid(); -> FAIL finding (line contains 'token') ``` -------------------------------- ### Example implementation of AbstractCheck Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/abstract-check.md A custom check class extending AbstractCheck, implementing name() and run(). The run() method returns a passing CheckResult. ```php class MyCustomCheck extends AbstractCheck { public function name(): string { return 'My Custom Check'; } public function run(): CheckResult { return CheckResult::pass('Everything looks good.'); } } ``` -------------------------------- ### Install checkpoint as dev dependency with Composer Source: https://github.com/andreapollastri/checkpoint/blob/main/docs/index.html Adds Checkpoint as a dev dependency via Composer. Laravel automatically discovers the package, so no service provider registration is required. ```bash composer require --dev andreapollastri/checkpoint ``` -------------------------------- ### CI usage for checkpoint:scan Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/errors.md Example GitHub Actions step that runs the scan with --json and --fail-on-warn, piping output to a report file. A non-zero exit aborts the pipeline step. ```yaml - name: Security audit run: php artisan checkpoint:scan --json --fail-on-warn | tee checkpoint-report.json ``` -------------------------------- ### WeakCryptographyCheck basic usage Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/checks/file-scan-ii.md Example of running WeakCryptographyCheck on the base path. The result is a CheckResult; comments show expected outcomes: mcrypt_encrypt fails, md5 with password warns. ```php use Checkpoint\Checks\WeakCryptographyCheck; $result = (new WeakCryptographyCheck(base_path()))->run(); // mcrypt_encrypt(...) -> FAIL // md5($password) same line as "password" -> WARN ``` -------------------------------- ### Example of FAIL finding with suppression hash Source: https://github.com/andreapollastri/checkpoint/blob/main/README.md Shows the output format for a FAIL finding, including the stable 12-character hash used for suppression. The hash is content-stable for line shifts but changes if file path or content changes. ```text FAIL Hardcoded Secrets 3 potential hardcoded secret(s) found. ✗ app/Services/PaymentService.php:14 — 'api_key' => 'sk_live_…' [a1b2c3d4e5f6] ✗ config/services.php:8 — $secret = 'super…' [9f8e7d6c5b4a] ``` -------------------------------- ### DebugFunctionsCheck usage example Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/checks/file-scan-i.md Creates a DebugFunctionsCheck instance with base_path() and runs it. The result will be a WARN finding if debug functions like dd() are called in production code outside tests. ```php use Checkpoint\Checks\DebugFunctionsCheck; $result = (new DebugFunctionsCheck(base_path()))->run(); // dd($request) in app/Http/Controllers/... -> WARN finding ``` -------------------------------- ### Limit checks with --only Source: https://github.com/andreapollastri/checkpoint/blob/main/docs/index.html Run only specific checks by display name (case-insensitive), comma-separated. Example shows running SQL Injection Risks and CSRF Protection. ```bash php artisan checkpoint:scan --only="SQL Injection Risks,CSRF Protection" ``` -------------------------------- ### Checkpoint scan output for missing route Source: https://github.com/andreapollastri/checkpoint/blob/main/docs/404.html Example output from the Checkpoint scan when a route does not exist. It shows a PASS for the docs index, a FAIL for the missing route, and a WARN for navigation, with a summary indicating the scan failed. ```text PASS Docs Index Home, install, and reference are reachable. FAIL Route Lookup x Requested path does not exist [404c4e9k0p01] WARN Navigation ! Prefer links from the docs TOC or site nav. --------------------------------- Summary 1 passed 1 warn 1 failed Scan result: FAIL — return to / ``` -------------------------------- ### CI gate on EOL PHP Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/checks/supply-chain.md CI gate example: runs the check and blocks deployment if status is FAIL, indicating PHP runtime is past upstream security support. ```php $result = (new EolVersionCheck(base_path()))->run(); if ($result->status === CheckResult::FAIL) { // block deploy: PHP runtime is past upstream security support } ``` -------------------------------- ### Run InsecureDeserializationCheck Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/checks/file-scan-ii.md Runs the InsecureDeserializationCheck against the base path. The comments show three example lines: a dynamic unserialize() call that fails, one with an allowed_classes restriction that is skipped, and an unserialize(base64_decode(...)) chain that fails. ```php use Checkpoint\Checks\InsecureDeserializationCheck; $result = (new InsecureDeserializationCheck(base_path()))->run(); // unserialize($request->input('data')) -> FAIL // unserialize($raw, ['allowed_classes' => [MyDto::class]]) -> skipped (restricted) // unserialize(base64_decode($payload)) -> FAIL ``` -------------------------------- ### Run default checks with withDefaultChecks Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/scanner.md Builds a Scanner with all 26 built-in checks and runs it. The base_path() argument is passed to every check constructor. Configuration keys checkpoint.checks, checkpoint.package_freshness.minimum_age_days, checkpoint.package_freshness.whitelist, checkpoint.suspicious_autoload.whitelist, and checkpoint.extra_checks are honored. ```php use Checkpoint\Scanner; $results = Scanner::withDefaultChecks(base_path())->run(); ``` -------------------------------- ### Basic usage of checkpoint:github Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/github-pipeline-command.md Runs the command to create .github/workflows/checkpoint.yml. The comment shows the expected result. ```bash php artisan checkpoint:github # creates .github/workflows/checkpoint.yml ``` -------------------------------- ### Basic call to checkpoint:gitlab Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/gitlab-pipeline-command.md Runs the command to create `.gitlab-ci.yml` in the project root. ```bash php artisan checkpoint:gitlab # creates .gitlab-ci.yml ``` -------------------------------- ### Class declaration of CheckpointServiceProvider Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/checkpoint-service-provider.md The full class definition with register() and boot() methods. register() merges the package config; boot() registers commands and publishes the config when running in console. ```php class CheckpointServiceProvider extends ServiceProvider { public function register(): void { $this->mergeConfigFrom(__DIR__.'/../config/checkpoint.php', 'checkpoint'); } public function boot(): void { if ($this->app->runningInConsole()) { $this->commands([ ScanCommand::class, GithubPipelineCommand::class, GitlabPipelineCommand::class, InstallHooksCommand::class, ]); $this->publishes([ __DIR__.'/../config/checkpoint.php' => config_path('checkpoint.php'), ], 'checkpoint-config'); } } } ``` -------------------------------- ### Basic implementation of run() returning CheckResult Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/abstract-check.md Shows a minimal run() implementation that checks for a vendor directory and returns a warn() or pass() CheckResult. The method must be side-effect-free and its result is rendered by ScanCommand. ```php public function run(): CheckResult { $vendor = $this->basePath.'/vendor'; if (! is_dir($vendor)) { return CheckResult::warn('vendor/ not found.'); } return CheckResult::pass('Vendor directory present.'); } ``` -------------------------------- ### Configure package freshness in config/checkpoint.php Source: https://github.com/andreapollastri/checkpoint/blob/main/docs/index.html Set minimum age in days and whitelist packages. Set minimum_age_days to 0 to keep the check but skip the age gate. ```php 'package_freshness' => [ 'minimum_age_days' => 3, 'whitelist' => [ 'andreapollastri/checkpoint', // 'vendor/package', ], ], ``` -------------------------------- ### run() with details and per-detail suppression hashes Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/abstract-check.md Shows a run() implementation that returns a fail() CheckResult with an array of details and optional per-detail suppression hashes. The details use the format 'file:line — message'. ```php public function run(): CheckResult { $details = ['config/services.php:14 — hardcoded value']; // "file:line — message" $hashes = [$details[0] => 'abc123def456']; // optional override return CheckResult::fail('1 hardcoded value found.', $details, $hashes); } ``` -------------------------------- ### ComposerAuditCheck Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/checks/process-audit.md Documentation for the ComposerAuditCheck class, including constructor, name, and run methods. ```APIDOC ## ComposerAuditCheck::__construct ### Description Creates a new ComposerAuditCheck instance with the given base path. ### Method __construct ### Signature `public function __construct(private readonly string $basePath) {}` ### Parameters - **$basePath** (string) - Required - Project root where `composer.lock` lives and the `composer` binary runs. ### Example ```php use Checkpoint\Checks\ComposerAuditCheck; $check = new ComposerAuditCheck(base_path()); ``` ``` ```APIDOC ## ComposerAuditCheck::name ### Description Returns the check name. ### Method name ### Signature `public function name(): string` ### Return Value - **string** - Returns `'Composer CVE Audit'`. ### Example ```php $check = new ComposerAuditCheck(base_path()); $name = $check->name(); // 'Composer CVE Audit' ``` ``` ```APIDOC ## ComposerAuditCheck::run ### Description Runs `composer audit --format=json --no-interaction` and parses the JSON advisories map. ### Method run ### Signature `public function run(): CheckResult` ### Parameters None. ### Return Value - **CheckResult** - The result of the audit. ### Return Behavior | Status | Condition | |--------|-----------| | `warn` | `composer.lock` missing — `'composer.lock not found — run \`composer install\` first.'` | | `pass` | No advisories — `'No known CVEs in Composer dependencies.'` | | `fail` | ≥1 advisory — `"{n} CVE(s) found in Composer dependencies."` with one detail per advisory: `"[{package}] {title} ({cve})"` where `cve` is `issue['cve']`, falling back to `issue['advisoryId']`, then `'n/a'`. | ### Example ```php use Checkpoint\Checks\ComposerAuditCheck; $result = (new ComposerAuditCheck(base_path()))->run(); if ($result->status === CheckResult::FAIL) { foreach ($result->details as $detail) { echo "✗ $detail\n"; } } ``` ``` -------------------------------- ### Project source tree Source: https://github.com/andreapollastri/checkpoint/blob/main/README.md Shows the directory structure of the Checkpoint project, including the service provider, scanner, commands, and all security check classes. Useful for understanding the project layout and locating specific components. ```text src/ ├── CheckpointServiceProvider.php # auto-registers the command ├── Scanner.php # orchestrates all checks ├── Commands/ │ ├── ScanCommand.php # php artisan checkpoint:scan │ ├── GithubPipelineCommand.php # php artisan checkpoint:github │ ├── GitlabPipelineCommand.php # php artisan checkpoint:gitlab │ └── InstallHooksCommand.php # php artisan checkpoint:install-hooks └── Checks/ ├── AbstractCheck.php # base class ├── CheckResult.php # pass / warn / fail value object ├── ComposerAuditCheck.php ├── NpmAuditCheck.php ├── EnvironmentCheck.php ├── GitIgnoreCheck.php ├── FilePermissionsCheck.php ├── HardcodedSecretsCheck.php ├── SqlInjectionCheck.php ├── MassAssignmentCheck.php ├── XssCheck.php ├── CsrfCheck.php ├── OpenRedirectCheck.php ├── CommandInjectionCheck.php ├── InsecureDeserializationCheck.php ├── DebugFunctionsCheck.php ├── SensitiveExposureCheck.php ├── SsrfCheck.php ├── TlsVerificationCheck.php ├── CorsConfigCheck.php ├── PackageFreshnessCheck.php ├── SuspiciousVendorAutoloadCheck.php ├── SupplyChainToolingCheck.php ├── PathTraversalCheck.php ├── WeakCryptographyCheck.php ├── InsecureRngCheck.php ├── SessionSecurityCheck.php └── EolVersionCheck.php ``` -------------------------------- ### CommandInjectionCheck correctly escaped code example Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/checks/file-scan-ii.md Shows a comment illustrating that code containing escapeshellarg is excluded from the check, even if a variable appears in the command. ```php // shell_exec(escapeshellarg($userInput)) — the line contains 'escapeshellarg', // so the check's exclusion regex skips it even though $userInput appears. ``` -------------------------------- ### Run MassAssignmentCheck Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/checks/file-scan-i.md Creates a MassAssignmentCheck instance with the base path and runs the check. The result is a WARN if mass assignment issues are found, and the details are printed. ```php use Checkpoint\Checks\MassAssignmentCheck; $result = (new MassAssignmentCheck(base_path()))->run(); if ($result->status === CheckResult::WARN) { foreach ($result->details as $detail) { echo " ⚑ $detail\n"; } } ``` -------------------------------- ### new NpmAuditCheck(string $basePath) Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/checks/process-audit.md Constructor for the NpmAuditCheck class. Initializes the check with the project root path where package.json and lockfiles are located. ```APIDOC ## new NpmAuditCheck(string $basePath) ### Description Constructor for the NpmAuditCheck class. Initializes the check with the project root path where package.json and lockfiles are located. ### Method Constructor ### Parameters - **$basePath** (string) - Required - Project root containing `package.json` / lockfiles; `npm audit` runs here. ### Request Example ```php new NpmAuditCheck(base_path()) ``` ``` -------------------------------- ### Fluent chaining with Scanner::add() Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/scanner.md Demonstrates fluent chaining of add() calls. The order of checks is preserved; MyCustomCheck runs after EnvironmentCheck. ```php $scanner = (new Scanner()) ->add(new Checks\EnvironmentCheck($basePath)) ->add(new MyCustomCheck()); // runs after EnvironmentCheck ``` -------------------------------- ### Basic usage of NpmAuditCheck Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/checks/process-audit.md Runs the NPM audit check and prints the message and details if the status is FAIL or WARN. Use this to display audit results. ```php use Checkpoint\Checks\NpmAuditCheck; $result = (new NpmAuditCheck(base_path()))->run(); if ($result->status === CheckResult::FAIL || $result->status === CheckResult::WARN) { echo $result->message.PHP_EOL; foreach ($result->details as $detail) { echo " - $detail\n"; } } ``` -------------------------------- ### Skip checks with --skip Source: https://github.com/andreapollastri/checkpoint/blob/main/docs/index.html Skip specific checks by display name (case-insensitive), comma-separated. Example shows skipping NPM CVE Audit and Debug Functions in Production Code. ```bash php artisan checkpoint:scan --skip="NPM CVE Audit,Debug Functions in Production Code" ``` -------------------------------- ### Ad-hoc subset scan with --only and --skip Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/scan-command.md Runs the scan with a subset of checks using --only or --skip flags. The two commands are separate examples of filtering checks. ```bash php artisan checkpoint:scan --only="SQL Injection Risks,CSRF Protection" ``` ```bash php artisan checkpoint:scan --skip="NPM CVE Audit" ``` -------------------------------- ### Basic SqlInjectionCheck usage Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/checks/file-scan-i.md Runs the SqlInjectionCheck and prints failure details. The check scans all *.php files under the base path, excluding vendor, node_modules, storage, bootstrap/cache, and .git by default. ```php use Checkpoint\Checks\SqlInjectionCheck; $result = (new SqlInjectionCheck(base_path()))->run(); if ($result->status === CheckResult::FAIL) { foreach ($result->details as $detail) { echo " ✗ $detail\n"; } } ``` -------------------------------- ### Direct construction of CheckResult with FAIL status Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/check-result.md Creates a new CheckResult instance directly, equivalent to CheckResult::fail(...). The example passes a FAIL status, a summary message, and a list of details. ```php $result = new CheckResult( CheckResult::FAIL, '2 CVE(s) found in Composer dependencies.', ['[vendor/pkg] CVE title (CVE-2026-0001)'], ); ``` -------------------------------- ### SuspiciousVendorAutoloadCheck::__construct Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/checks/supply-chain.md Creates a new SuspiciousVendorAutoloadCheck instance with the project root and an optional extra whitelist. ```APIDOC ## SuspiciousVendorAutoloadCheck::__construct ### Description Creates a new SuspiciousVendorAutoloadCheck instance. The base path is the project root containing `vendor/`. The extra whitelist is merged onto the baked-in default whitelist. ### Method Constructor ### Signature ```php /** * @param string[] $extraWhitelist Additional `vendor/pkg` patterns to allow. */ public function __construct( private readonly string $basePath, private readonly array $extraWhitelist = [], ) {} ``` ### Parameters - `$basePath` (string) - Required - Project root containing `vendor/`. - `$extraWhitelist` (array of string) - Optional - Default `[]`. Extra `vendor/pkg` patterns merged onto the baked-in default whitelist. Supports trailing-`*` wildcards (exact match or `str_starts_with` prefix match). ### Example ```php use Checkpoint\Checks\SuspiciousVendorAutoloadCheck; $check = new SuspiciousVendorAutoloadCheck(base_path(), [ 'my-org/internal-helpers', 'acme/*', ]); ``` ``` -------------------------------- ### PackageFreshnessCheck Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/checks/supply-chain.md Documentation for the PackageFreshnessCheck class, including its constructor, name method, and run method. ```APIDOC ## PackageFreshnessCheck::__construct ### Description Creates a new PackageFreshnessCheck instance that scans Composer dependencies for packages released too recently. ### Method `__construct` ### Signature ```php public function __construct( private readonly string $basePath, private readonly int $minimumAgeDays = 3, private readonly array $whitelist = [], ) {} ``` ### Parameters - **$basePath** (string) - Required - Project root containing `composer.lock`. - **$minimumAgeDays** (int) - Optional - Default: `3` - Packages released within this many days fail the scan. `0` bypasses the gate entirely. - **$whitelist** (array of string) - Optional - Default: `[]` - Fully-qualified package names (`vendor/pkg`) exempt from the freshness gate. ### Example ```php use Checkpoint\Checks\PackageFreshnessCheck; $check = new PackageFreshnessCheck( basePath: base_path(), minimumAgeDays: 7, whitelist: ['acme/critical-patch', 'andreapollistri/checkpoint'], ); ``` ``` ```APIDOC ## PackageFreshnessCheck::name ### Description Returns the display name of the check. ### Method `name` ### Signature ```php public function name(): string ``` ### Returns - **string** - The check name: `'Package Freshness (Supply Chain)'`. ``` ```APIDOC ## PackageFreshnessCheck::run ### Description Parses `composer.lock` and returns a CheckResult indicating whether any packages were released within the configured freshness window. ### Method `run` ### Signature ```php public function run(): CheckResult ``` ### Returns - **CheckResult** - The result of the freshness scan. ### Status Conditions - **warn** - `composer.lock` missing — `'composer.lock not found — run \`composer install\` first.'` - **warn** - `composer.lock` not valid JSON — `'composer.lock is not valid JSON — skipping freshness check.'` - **pass** - No fresh packages — `"All Composer packages are older than {n} day(s)"` plus `" ({skipped} whitelisted package(s) skipped)"` when the whitelist matched any. - **fail** - Fresh packages — `"{n} Composer package(s) released within the last {n} day(s) — whitelist in config/checkpoint.php if intentional."` ### Details Details are `"{name} {version} released {ageHours}h ago"` plus `" [dev]"` for `packages-dev` entries. Suppression hashes are **package name + version only** (per-detail `hashes` map override via `CheckResult::hashFinding($this->name(), "{$name} {$version}")`), so suppressions stay valid as displayed ages change. ### Example ```php use Checkpoint\Checks\PackageFreshnessCheck; $result = (new PackageFreshnessCheck(base_path()))->run(); // default minimumAgeDays = 3, empty whitelist ``` ``` -------------------------------- ### Merge WITH_TESTS with user-configured extra paths Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/scan-paths.md Shows config/checkpoint.php with an 'exclude_paths' key and usage merging it with WITH_TESTS. Configured paths are trimmed and merged onto the base list. ```php // config: 'exclude_paths' => ['storage/app/mounted-data', 'data/external'], // usage: $paths = ScanPaths::merge(ScanPaths::WITH_TESTS); ``` -------------------------------- ### hashFor example Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/check-result.md Resolves the effective suppression hash for a detail, preferring a check-supplied override stored under the exact detail message, otherwise falling back to hashFinding(). Used by consumers for suppression rendering, as shown in the loop over result details. ```php $result = $check->run(); foreach ($result->details as $detail) { $hash = $result->hashFor($check->name(), $detail); echo "$detail [$hash]".PHP_EOL; // hash matches config('checkpoint.suppressed') entries } ``` -------------------------------- ### SupplyChainToolingCheck::__construct Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/checks/supply-chain.md Creates a new SupplyChainToolingCheck instance with the project root path. ```APIDOC ## SupplyChainToolingCheck::__construct ### Description Creates a new SupplyChainToolingCheck instance. The base path is used only to detect package.json. ### Method Constructor ### Signature ```php public function __construct(private readonly string $basePath) {} ``` ### Parameters - `$basePath` (string) - Required - Project root, used only to detect `package.json`. ### Example ```php use Checkpoint\Checks\SupplyChainToolingCheck; $check = new SupplyChainToolingCheck(base_path()); ``` ``` -------------------------------- ### Publish the config with artisan vendor:publish Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/checkpoint-service-provider.md Command to publish the package config to config/checkpoint.php under the tag checkpoint-config. Creates the config file with toggle map, extra_checks, package_freshness, suspicious_autoload, suppressed, and exclude_paths sections. ```bash php artisan vendor:publish --tag=checkpoint-config ``` -------------------------------- ### Run SsrfCheck on project base path Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/checks/file-scan-ii.md Instantiates SsrfCheck with the project base path and runs the check. The comment shows that HTTP calls with user-controlled URLs (e.g., Http::get($request->url) or file_get_contents($_GET['url'])) will produce FAIL findings. ```php use Checkpoint\Checks\SsrfCheck; $result = (new SsrfCheck(base_path()))->run(); // Http::get($request->url) or file_get_contents($_GET['url']) -> FAIL findings ``` -------------------------------- ### Command signature and description Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/install-hooks-command.md Defines the Artisan command signature and description for checkpoint:install-hooks. The signature includes --force and --remove options. ```php protected $signature = 'checkpoint:install-hooks {--force : Replace any existing Checkpoint entry instead of leaving it untouched} {--remove : Remove Checkpoint entries from composer.json}'; protected $description = 'Wire `php artisan checkpoint:scan` into composer.json as a post-update / post-install hook'; ``` -------------------------------- ### Generate GitHub Actions workflow with checkpoint:github Source: https://github.com/andreapollastri/checkpoint/blob/main/docs/index.html Generates a GitHub Actions workflow file at .github/workflows/checkpoint.yml. The workflow runs on push to main/master and on every PR, uses PHP 8.2 with Composer cache, optionally sets up Node and runs npm ci when package-lock.json is present, and runs checkpoint:scan --json with the report uploaded as an artifact. Pass --force to overwrite an existing workflow. ```bash php artisan checkpoint:github ``` -------------------------------- ### Basic scan command Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/scan-command.md Runs the checkpoint scan with default settings. Outputs a human-readable table unless --json is used. ```bash php artisan checkpoint:scan ``` -------------------------------- ### Force overwrite with --force Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/gitlab-pipeline-command.md Overwrites an existing `.gitlab-ci.yml` file. ```bash php artisan checkpoint:gitlab --force ``` -------------------------------- ### Chain only() with default checks and run() Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/scanner.md Builds a scanner with default checks, filters to a single check, and runs it. The filter is applied before execution, so only the named check runs. An empty filter produces an empty result set. ```php $results = Scanner::withDefaultChecks(base_path()) ->only(['Composer CVE Audit']) ->run(); ``` -------------------------------- ### Existing file, refusing to overwrite Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/gitlab-pipeline-command.md When `.gitlab-ci.yml` already exists and `--force` is not set, the command prints an error and dumps the stub content to stdout. ```bash php artisan checkpoint:gitlab # error: .gitlab-ci.yml already exists. Pass --force to overwrite, or copy the snippet below... # prints stubs/gitlab-ci.yml to stdout ``` -------------------------------- ### Run GitIgnoreCheck and print result Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/checks/config-file.md Basic usage of GitIgnoreCheck. It runs the check on the base path and prints the status and message. The check fails if .gitignore is missing or .env is tracked by git, warns if required patterns are missing, and passes otherwise. ```php use Checkpoint\Checks\GitIgnoreCheck; $result = (new GitIgnoreCheck(base_path()))->run(); echo $result->status.': '.$result->message.PHP_EOL; ``` -------------------------------- ### SuspiciousVendorAutoloadCheck constructor Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/checks/supply-chain.md Constructor for SuspiciousVendorAutoloadCheck. Accepts a base path and an optional array of extra whitelist patterns. ```php /** * @param string[] $extraWhitelist Additional `vendor/pkg` patterns to allow. */ public function __construct( private readonly string $basePath, private readonly array $extraWhitelist = [], ) {} ``` -------------------------------- ### SuspiciousVendorAutoloadCheck::run Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/checks/supply-chain.md Runs the check to scan vendor composer.json files for suspicious autoload.files entries. ```APIDOC ## SuspiciousVendorAutoloadCheck::run ### Description Runs the check to scan vendor composer.json files for suspicious autoload.files entries. Iterates `vendor/{vendor}/{package}/composer.json` manifests (skipping `bin/` and `composer/` vendor dirs); warns when a package registers PHP via `autoload.files` or `autoload-dev.files` and is not whitelisted. ### Method Method ### Signature ```php public function run(): CheckResult ``` ### Returns - `CheckResult` - The result of the check. ### Status Conditions - `warn` - `vendor/` missing — `'vendor/ not found — run \`composer install\` first.'` - `pass` - No unexpected entries — `"No unexpected \`autoload.files\` entries across {scanned} vendor package(s)."` - `warn` - ≥1 unexpected entry — `"{n} vendor package(s) register code via \`autoload.files\` outside the known-safe whitelist — inspect the referenced files before trusting them, then add the package to \`suspicious_autoload.whitelist\` in config/checkpoint.php if intentional."` with details `"{package} — autoload.files: {first 3 files, then '…'}"`. ### Example ```php use Checkpoint\Checks\SuspiciousVendorAutoloadCheck; $result = (new SuspiciousVendorAutoloadCheck(base_path()))->run(); ``` ``` -------------------------------- ### Basic call to AbstractCheck::relativePath() Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/abstract-check.md Demonstrates the basic usage of relativePath() to strip a base path prefix from an absolute path, returning the relative path with leading slashes trimmed. ```php AbstractCheck::relativePath('/var/www/app', '/var/www/app/app/Models/User.php'); // "app/Models/User.php" ``` -------------------------------- ### run(?callable $beforeEach = null): array Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/scanner.md Executes every registered check and collects results keyed by check name. An optional callback can be provided to be invoked before each check runs, useful for progress reporting. ```APIDOC ## `run(?callable $beforeEach = null): array` ### Description Executes every registered check and collects results keyed by check name. If `$beforeEach` is provided it is invoked with the check instance immediately before that check's `run()` — this is how `ScanCommand` drives its progress bar. ### Method `run` ### Parameters #### Path Parameters - None #### Query Parameters - None #### Request Body - `$beforeEach` (callable(AbstractCheck): void) | null - Optional - Callback invoked before each check runs. ### Request Example ```php $results = $scanner->run(); foreach ($results as $name => $result) { echo "[{$result->status}] {$name}: {$result->message}".PHP_EOL; } ``` ### Response #### Success Response (200) - Returns `array` (array) - Map of check name (from `AbstractCheck::name()`) to its `CheckResult`. Order matches insertion order. #### Response Example ```php $results = $scanner->run(function ($check): void { echo "Running {$check->name()}...\n"; }); ``` ``` -------------------------------- ### Generate GitLab CI configuration with checkpoint:gitlab Source: https://github.com/andreapollastri/checkpoint/blob/main/docs/index.html Creates a .gitlab-ci.yml file, or prints a ready-to-paste snippet if one already exists. The generated pipeline follows the same pattern as the GitHub Actions workflow: JSON report artifact and optional Node on Alpine when a lockfile is present. Use --force to overwrite an existing file. ```bash php artisan checkpoint:gitlab ``` -------------------------------- ### PackageFreshnessCheck constructor Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/checks/supply-chain.md Constructor for PackageFreshnessCheck. Accepts basePath (required), minimumAgeDays (default 3), and whitelist (default empty array). ```php /** * @param string[] $whitelist Fully-qualified package names (vendor/pkg) to skip. */ public function __construct( private readonly string $basePath, private readonly int $minimumAgeDays = 3, private readonly array $whitelist = [], ) {} ``` -------------------------------- ### Print session/cookie security warnings with SessionSecurityCheck Source: https://github.com/andreapollastri/checkpoint/blob/main/_autodocs/api-reference/checks/config-file.md Runs the SessionSecurityCheck and prints each detail when the result status is WARN, which occurs when at least one session/cookie security issue is found. The details array contains the specific findings from the check. ```php use Checkpoint\Checks\SessionSecurityCheck; $result = (new SessionSecurityCheck(base_path()))->run(); if ($result->status === CheckResult::WARN) { foreach ($result->details as $detail) { echo " ⚑ $detail\n"; } } ``` -------------------------------- ### Run Checkpoint scan with only Route Lookup check Source: https://github.com/andreapollastri/checkpoint/blob/main/docs/404.html Use this command to run the Checkpoint scan with only the 'Route Lookup' check enabled. The output shows a PASS for the docs index, a FAIL for the missing route, and a WARN for navigation, resulting in a failed scan. ```bash php artisan checkpoint:scan --only="Route Lookup" ```