PHPackages                             apiposture/apiposture - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. apiposture/apiposture

ActiveLibrary[API Development](/categories/api)

apiposture/apiposture
=====================

Static analysis tool that scans PHP projects for API security posture issues

v1.1.1(1mo ago)3961[1 issues](https://github.com/BlagoCuljak/ApiPosture.php/issues)MITPHPPHP ^8.1CI passing

Since Feb 26Pushed 1mo ago1 watchersCompare

[ Source](https://github.com/BlagoCuljak/ApiPosture.php)[ Packagist](https://packagist.org/packages/apiposture/apiposture)[ RSS](/packages/apiposture-apiposture/feed)WikiDiscussions main Synced 3w ago

READMEChangelog (10)Dependencies (8)Versions (13)Used By (0)

ApiPosture.php
==============

[](#apiposturephp)

[![Build and Test](https://github.com/BlagoCuljak/ApiPosture.php/actions/workflows/build.yml/badge.svg)](https://github.com/BlagoCuljak/ApiPosture.php/actions/workflows/build.yml)[![Packagist Version](https://camo.githubusercontent.com/d93ff2a640cfdf3f25ebdf715019c604b186d6ca1884306fb74478f1777b928a/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f617069706f73747572652f617069706f73747572653f6c6f676f3d7061636b6167697374266c6162656c3d5061636b6167697374)](https://packagist.org/packages/apiposture/apiposture)[![Packagist Downloads](https://camo.githubusercontent.com/51af8922bd526db5f57827be264fb92cbe116987169616a0d7d70431b5502419/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f617069706f73747572652f617069706f73747572653f6c6f676f3d7061636b6167697374266c6162656c3d446f776e6c6f616473)](https://packagist.org/packages/apiposture/apiposture)[![License: MIT](https://camo.githubusercontent.com/fdf2982b9f5d7489dcf44570e714e3a15fce6253e0cc6b5aa61a075aac2ff71b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d79656c6c6f772e737667)](https://opensource.org/licenses/MIT)[![PHP](https://camo.githubusercontent.com/bf5636cbc371789cbd19fba904014740aca026d6f5d725b435fa0d3b224a1cf9/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e31253230253743253230382e32253230253743253230382e33253230253743253230382e342d3737374242343f6c6f676f3d706870)](https://www.php.net/)[![Ko-fi](https://camo.githubusercontent.com/842b6111e079ba83969bc86f49acd77d5706f38f1af8720bdb860f96fed211fb/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4b6f2d2d66692d737570706f72742d4646354535423f6c6f676f3d6b6f2d6669266c6f676f436f6c6f723d7768697465)](https://ko-fi.com/blagoculjak)

A CLI security inspection tool for PHP APIs. Performs static source-code analysis using [nikic/php-parser](https://github.com/nikic/PHP-Parser) to identify authorization misconfigurations and security risks in Laravel, Symfony, and Slim applications.

### Terminal Output

[](#terminal-output)

[![Terminal Output](assets/images/php1.png)](assets/images/php1.png)

### Findings Report

[](#findings-report)

[![Findings Report](assets/images/php2.png)](assets/images/php2.png)

Features
--------

[](#features)

- Static analysis of PHP projects (no runtime required)
- Discovers endpoints from Laravel routes, Symfony attributes, and Slim route definitions
- Detects 8 common security issues with authorization
- Multiple output formats: Terminal, JSON, Markdown, HTML
- Sorting, filtering, and grouping of results
- Configuration file support with suppressions
- Accessibility options (no-color, no-icons)
- CI/CD integration with `--fail-on` exit codes
- Works with PHP 8.1+

Installation
------------

[](#installation)

```
# Install globally (recommended — scan any project from anywhere)
composer global require apiposture/apiposture

# Or install as a dev dependency inside your project
composer require --dev apiposture/apiposture
```

> **Global install tip:** After `composer global require`, make sure Composer's global bin directory is on your `PATH`. The location varies by system — find yours with `composer global config bin-dir --absolute`, then add it:
>
> ```
> # Modern Linux / macOS (Composer 2.x)
> export PATH="$PATH:$HOME/.config/composer/vendor/bin"
>
> # Older Linux / macOS
> export PATH="$PATH:$HOME/.composer/vendor/bin"
>
> # Add whichever applies to ~/.bashrc or ~/.zshrc to make it permanent
> ```
>
>
>
> Then run `apiposture scan /path/to/project` from anywhere.

> **Project install tip:** `vendor/bin/apiposture` must be run from the directory where you ran `composer require` (where the `vendor/` folder lives). Pass the target path as an argument:
>
> ```
> # Installed in ~/myapp, scanning a subdirectory
> cd ~/myapp
> vendor/bin/apiposture scan src/Controller
>
> # Scanning a completely separate project
> vendor/bin/apiposture scan /path/to/other-project
> ```

Usage
-----

[](#usage)

```
# Scan a project directory (global install)
apiposture scan /path/to/project

# Scan a project directory (project install — run from vendor root)
vendor/bin/apiposture scan /path/to/project

# Scan a subdirectory
vendor/bin/apiposture scan ./src/Controller

# Output as JSON
vendor/bin/apiposture scan . --output json

# Output as Markdown report
vendor/bin/apiposture scan . --output markdown --output-file report.md

# Output as HTML report
vendor/bin/apiposture scan . --output html --output-file report.html

# Filter by severity
vendor/bin/apiposture scan . --severity medium

# CI integration - fail if high severity findings
vendor/bin/apiposture scan . --fail-on high

# Sorting
vendor/bin/apiposture scan . --sort-by route --sort-dir asc

# Filtering
vendor/bin/apiposture scan . --classification public --method POST
vendor/bin/apiposture scan . --route-contains admin --controller UserController

# Grouping
vendor/bin/apiposture scan . --group-by controller
vendor/bin/apiposture scan . --group-findings-by severity

# Accessibility (no colors/icons)
vendor/bin/apiposture scan . --no-color --no-icons

# Use config file
vendor/bin/apiposture scan . --config .apiposture.json
```

Supported Frameworks
--------------------

[](#supported-frameworks)

### Laravel

[](#laravel)

- `Route::get()`, `Route::post()`, `Route::put()`, `Route::delete()`, `Route::patch()`
- `Route::middleware(['auth'])->group(...)` with nested routes
- `Route::prefix('/api')->group(...)` with path prefixes
- Controller middleware via `$this->middleware('auth')` in constructors
- `#[Middleware('auth')]` attributes (Laravel 11+)
- Auth detection: `auth`, `auth:sanctum`, `auth:api`, `role:*`, `can:*`, `guest`

### Symfony

[](#symfony)

- `#[Route('/path', methods: ['GET'])]` attributes
- `#[IsGranted('ROLE_ADMIN')]` security attributes
- `#[Security("is_granted('ROLE_USER')")]` expressions
- Class-level route prefixes and security inheritance
- `ROLE_*` pattern detection

### Slim

[](#slim)

- `$app->get()`, `$app->post()`, `$app->put()`, `$app->delete()`, `$app->patch()`
- `$app->group('/prefix', ...)` with nested routes
- `->add(new AuthMiddleware())` middleware chains
- Auth middleware detection via naming conventions

Configuration File
------------------

[](#configuration-file)

Create `.apiposture.json` in your project root:

```
{
  "severity": { "default": "low", "failOn": "high" },
  "suppressions": [
    { "route": "/api/health", "ruleId": "AP001" },
    { "route": "/api/webhook/*", "ruleId": "AP002" }
  ],
  "rules": {
    "AP006": { "enabled": false }
  },
  "display": { "useColors": true, "useIcons": true }
}
```

Security Rules
--------------

[](#security-rules)

Rule IDNameSeverityDescriptionAP001Public without explicit intentMediumEndpoint is publicly accessible without `guest` middleware or explicit markerAP002AllowAnonymous on writeHigh\*Public POST/PUT/DELETE/PATCH operationsAP003Controller/action conflictHighAction overrides controller-level auth with anonymous accessAP004Missing auth on writesCriticalWrite endpoint with zero authentication whatsoeverAP005Excessive role accessMediumMore than 3 roles on a single endpointAP006Weak role namingLowGeneric role names like "user", "admin", "guest"AP007Sensitive route keywordsHigh/Low`admin`, `debug`, `export`, `secret` in routes (High without auth, Low with auth)AP008Unprotected endpointHigh/InfoEndpoint with no auth middleware (High for writes, Info for reads)\*AP002 severity adjusts dynamically: webhooks → Medium, auth/login endpoints → Low, analytics → Low

Example Output
--------------

[](#example-output)

### Sample Terminal Output

[](#sample-terminal-output)

```
ApiPosture Scan Results
────────────────────────────────────────────────────────
  Path:     /path/to/project
  Duration: 0.25s
  Files:    15 scanned

Summary
+-------------+-------+
| Metric      | Count |
+-------------+-------+
| Endpoints   | 42    |
| Findings    | 8     |
|   Critical  | 1     |
|   High      | 3     |
|   Medium    | 2     |
|   Low       | 2     |
+-------------+-------+

Endpoints
+---------------------+---------+----------------+----------------+------+
| Route               | Methods | Classification | Controller     | Auth |
+---------------------+---------+----------------+----------------+------+
| /api/users          | GET     | Authenticated  | UserController | Yes  |
| /api/admin          | GET     | Public         | AdminController| No   |
| /api/orders         | POST    | Role Restricted| OrderController| Yes  |
+---------------------+---------+----------------+----------------+------+

```

GitHub Actions Integration
--------------------------

[](#github-actions-integration)

Create `.github/workflows/api-security-scan.yml`:

### Basic Workflow

[](#basic-workflow)

```
name: API Security Scan

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]

jobs:
  security-scan:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout code
      uses: actions/checkout@v4

    - name: Setup PHP
      uses: shivammathur/setup-php@v2
      with:
        php-version: '8.3'

    - name: Install dependencies
      run: composer install --prefer-dist --no-progress

    - name: Scan API for security issues
      run: vendor/bin/apiposture scan ./app --fail-on high
```

### Advanced Workflow with Reports

[](#advanced-workflow-with-reports)

```
name: API Security Scan

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]

jobs:
  security-scan:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout code
      uses: actions/checkout@v4

    - name: Setup PHP
      uses: shivammathur/setup-php@v2
      with:
        php-version: '8.3'

    - name: Install dependencies
      run: composer install --prefer-dist --no-progress

    - name: Run security scan
      id: scan
      continue-on-error: true
      run: |
        vendor/bin/apiposture scan ./app \
          --output json \
          --output-file scan-results.json \
          --fail-on high

    - name: Generate Markdown report
      if: always()
      run: |
        vendor/bin/apiposture scan ./app \
          --output markdown \
          --output-file api-security-report.md

    - name: Upload JSON results
      if: always()
      uses: actions/upload-artifact@v4
      with:
        name: security-scan-json
        path: scan-results.json

    - name: Upload Markdown report
      if: always()
      uses: actions/upload-artifact@v4
      with:
        name: security-scan-report
        path: api-security-report.md

    - name: Comment PR with results
      if: github.event_name == 'pull_request' && always()
      uses: actions/github-script@v7
      with:
        script: |
          const fs = require('fs');
          const report = fs.readFileSync('api-security-report.md', 'utf8');
          github.rest.issues.createComment({
            issue_number: context.issue.number,
            owner: context.repo.owner,
            repo: context.repo.repo,
            body: `## API Security Scan Results\n\n${report}`
          });

    - name: Fail if high severity issues found
      if: steps.scan.outcome == 'failure'
      run: exit 1
```

### Configuration Options

[](#configuration-options)

- `--fail-on `: Exit with code 1 if findings of specified severity or higher are found
- `--output json`: Generate machine-readable JSON output for further processing
- `--output markdown`: Generate human-readable Markdown reports
- `--output html`: Generate self-contained HTML reports
- `--severity `: Set minimum severity level to report
- `--config .apiposture.json`: Use configuration file for suppressions and custom rules

### Exit Codes

[](#exit-codes)

- `0`: Scan completed successfully with no findings above the fail threshold
- `1`: Findings above the fail threshold were detected, or error during scan

Project Structure
-----------------

[](#project-structure)

```
ApiPosture.php/
├── src/
│   ├── Core/
│   │   ├── Analyzer/          # Scan orchestrator
│   │   ├── Classification/    # Security classifier
│   │   ├── Config/            # Configuration loader
│   │   ├── Discovery/         # Laravel, Symfony, Slim discoverers
│   │   └── Model/             # Endpoint, Finding, ScanResult, Enums
│   ├── Rules/                 # 8 security rules + engine
│   ├── Output/                # Terminal, JSON, Markdown formatters
│   └── Command/               # CLI scan command
├── tests/
│   ├── Core/
│   ├── Rules/
│   ├── Output/
│   ├── Command/
│   └── Fixtures/              # Laravel, Symfony, Slim sample code
├── bin/apiposture              # CLI entry point
└── composer.json

```

Building from Source
--------------------

[](#building-from-source)

```
# Clone and install
git clone https://github.com/BlagoCuljak/ApiPosture.php.git
cd ApiPosture.php
composer install

# Run tests
vendor/bin/phpunit

# Run against sample fixtures
vendor/bin/apiposture scan tests/Fixtures/Laravel
vendor/bin/apiposture scan tests/Fixtures/Symfony --output json
vendor/bin/apiposture scan tests/Fixtures/Slim --output markdown
```

Related Projects
----------------

[](#related-projects)

- [ApiPosture](https://github.com/BlagoCuljak/ApiPosture) - .NET version (ASP.NET Core)
- [ApiPosture.Java](https://github.com/BlagoCuljak/ApiPosture.Java) - Java version (Spring Boot)
- [ApiPosture.Python](https://github.com/BlagoCuljak/ApiPosture.Python) - Python version (Django, Flask, FastAPI)
- [ApiPosture.Node.js](https://github.com/BlagoCuljak/ApiPosture.Node.js) - Node.js version (Express, Fastify, NestJS)
- [ApiPosture.Go](https://github.com/BlagoCuljak/ApiPosture.Go) - Go version (Gin, Echo, Chi)

Contributing
------------

[](#contributing)

We welcome contributions! Please:

- [Report a bug](https://github.com/BlagoCuljak/ApiPosture.php/issues/new)
- [Request a feature](https://github.com/BlagoCuljak/ApiPosture.php/issues/new)

License
-------

[](#license)

MIT

###  Health Score

42

—

FairBetter than 89% of packages

Maintenance87

Actively maintained with recent releases

Popularity15

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity50

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~8 days

Recently: every ~19 days

Total

12

Last Release

30d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/22b0fee9954932ff8e3f6e16b54e7255ee5c8fac0037800e05a7815d362802e0?d=identicon)[blago.culjak](/maintainers/blago.culjak)

---

Top Contributors

[![BlagoCuljak](https://avatars.githubusercontent.com/u/34435929?v=4)](https://github.com/BlagoCuljak "BlagoCuljak (17 commits)")

---

Tags

apisymfonylaravelstatic analysissecurityslim

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/apiposture-apiposture/health.svg)

```
[![Health](https://phpackages.com/badges/apiposture-apiposture/health.svg)](https://phpackages.com/packages/apiposture-apiposture)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3345.1M337](/packages/psalm-plugin-laravel)[phparkitect/phparkitect

Enforce architectural constraints in your PHP applications

9184.1M24](/packages/phparkitect-phparkitect)[aeliot/todo-registrar

Register TODOs from source code in issue tracker

153.0k](/packages/aeliot-todo-registrar)[jolicode/castor

A lightweight and modern task runner. Automate everything. In PHP.

54642.4k4](/packages/jolicode-castor)[rector/rector-src

Instant Upgrade and Automated Refactoring of any PHP code

136400.8k14](/packages/rector-rector-src)[friendsoftypo3/content-blocks

TYPO3 CMS Content Blocks - Content Types API | Define reusable components via YAML

101466.4k45](/packages/friendsoftypo3-content-blocks)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
