martinholovsky/sota-skills · Archived

sota-php

>- State-of-the-art PHP engineering (2026 baseline, PHP 8.3+ floor, 8.5 current) for both writing new PHP and auditing existing PHP code. Covers strict_types and modern idioms (enums, readonly, match, fibers, property hooks), OWASP-grade security (SQL injection, XSS, file uploads, LFI/RFI, unserialize/Phar object injection, sessions, password hashing, sodium, SSRF), framework-neutral web hardening, Composer supply chain and static analysis (PHPStan/Psalm levels, baselines), and runtime performa…

First seen Aug 5, 2026

Installation

$ npx skills add martinholovsky/sota-skills --skill sota-php

Stronger alternatives

This repository is archived — consider an actively maintained alternative.

Also in this package

Other skills from martinholovsky/sota-skills · top by installs.

npx skills add martinholovsky/sota-skills

Browse all from martinholovsky/sota-skills

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Stars 18
License LICENSE
Default branch main
Open issues 0
Status Archived

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 8,644 B
  • docs SUMMARY.md 922 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 1 installs

SKILL.md

SOTA PHP (2026)

Purpose

This skill encodes the 2026 state of the art for PHP: a supported-version baseline (PHP 8.3+ floor; 8.5 is the latest annual line — verify current, see rules/01), strict_types everywhere, typed object-oriented design, security-by-default at every trust boundary, a locked and audited Composer supply chain, and measured runtime performance. It serves two modes:

  • BUILD — writing new code or modifying existing code to this standard.
  • AUDIT — reviewing existing code against this standard and reporting findings.

The detailed rules live in rules/*.md. Read SKILL.md fully; load rules files on demand per the index table below.

BUILD mode

When creating or modifying PHP code:

  1. Establish context first. Check composer.json (require.php, config.platform),

composer.lock, the framework in use, PHPStan/Psalm config, and CS ruleset. Match the project's PHP floor — no enums on a project that still supports 8.0. For a new project, scaffold per rules/05: PHP ≥ 8.3 floor, committed lockfile, PHPStan at max level (baseline only for legacy), PER-CS formatting, CI gates from day one.

  1. Default style: declare(strict_types=1) in every file, full parameter/return/

property types, constructor promotion, readonly where state shouldn't mutate, enums over class constants, match over switch, exceptions over error codes, no @ suppression. (rules/01)

  1. Security posture is non-optional even when unrequested: PDO prepared statements,

context-correct output escaping, upload validation by content, no unserialize() on external data, passwordhash/sodium/randombytes for anything secret. (rules/02rules/04)

  1. Framework first. When a framework is present (e.g. Laravel, Symfony), use its

escaping, CSRF, auth, and validation mechanisms instead of hand-rolling — but verify raw-escape hatches (DB::raw, |raw, html()) aren't fed user input.

  1. Tests accompany code (PHPUnit or Pest as the project dictates); static analysis

and CS must pass before code is presented. (rules/05)

  1. Performance: OPcache assumptions belong in deploy config, not code; anything

beyond correct-by-default (eager loading, streaming, generators) requires a profile first. (rules/06)

AUDIT mode

When reviewing existing PHP code:

  1. Sweep mechanically first. Run the "Audit checklist" blocks at the end of every

relevant rules file — ordered grep/composer/phpstan commands. Start with composer audit --locked and a grep sweep for unserialize(, eval(, shellexec, string-interpolated SQL, and echo $.

  1. Then read for design: trust-boundary placement, escaping strategy (output-time or

scattered?), session lifecycle, N+1 patterns, lockfile discipline.

  1. Verify every finding — open the file, trace the data flow. An unserialize() of a

value the same app signed with HMAC is not CRITICAL. Note mitigations already present.

  1. Don't report style noise a fixer would auto-fix; mention once collectively.

Severity conventions

Severity Meaning Examples
CRITICAL Exploitable now, or data loss SQL built by interpolation from request data, unserialize($_GET…), include of user path, eval on input, uploads executed as PHP
HIGH Exploitable with preconditions, or prod-breaking XSS via unescaped output, md5() passwords, missing usestrictmode/fixation, SSRF fetch of user URL, CURLOPTSSLVERIFYPEER => false, world-readable secrets
MEDIUM Correctness/maintenance risk no lockfile committed, no composer audit in CI, loose == on security decisions, rand() for tokens in non-auth context, N+1 on hot path, no static analysis
LOW Deviation from SOTA, friction missing strict_types, untyped properties, switch where match fits, dev deps in prod image
INFO Worth knowing newer-PHP features available after floor bump, tooling consolidation

Finding format

file:line | rule violated (rules/NN §S) | severity | effort | fix

Effort: trivial · small · medium · large. Group by severity, CRITICAL first. Borderline severities state the deciding assumption; unconfirmed findings are marked "needs verification", never asserted. End with counts per severity, the sweep commands run, and explicit "checked and clean" areas.

Rules index

File Read this when...
rules/01-language-baseline.md choosing/verifying PHP version floor (support/EOL table); writing any PHP: strict_types, typed properties, enums, readonly, match, fibers, 8.4/8.5 features, comparison pitfalls incl. strpos returning false where 0 is a real match, error handling, deprecations
rules/02-injection.md code touching SQL, shell, or HTML output: PDO prepared statements, command execution, XSS and context-aware escaping, template engines, eval-family bans
rules/03-files-deserialization-ssrf.md file uploads, include/require paths, stream wrappers (LFI/RFI/phar://), unserialize and Phar object injection, XXE, server-side URL fetching (SSRF)
rules/04-sessions-auth-web-hardening.md login/session/auth code: session cookie flags and fixation, password_hash/argon2id, sodium crypto, CSRF, security headers, production php.ini hardening
rules/05-composer-tooling.md dependencies and CI: composer.lock discipline, composer audit, platform reqs, PHPStan/Psalm levels and baseline ratcheting, PER-CS, PHPUnit/Pest, CI gates
rules/06-performance-runtime.md anything slow or deploy-shaped: OPcache and preloading, JIT reality check, PHP-FPM pool sizing, N+1/caching, autoloader optimization, profiling. **Test strategy lives in sota-testing; DB depth in sota-databases.**

Top-10 non-negotiables

  1. Run a supported PHP (≥ 8.2 today, and 8.2 is security-only until 2026-12-31 —

plan the 8.3+ move now); new code targets 8.3+. (rules/01)

  1. **declare(strict_types=1) in every file; full types on every property, parameter,

and return.** Untyped is legacy, not a style choice. (rules/01)

  1. SQL only via prepared statements with bound parameters (PDO/mysqli, emulation

off); identifiers via allowlist. String-built SQL is CRITICAL, no exceptions for "internal" values. (rules/02)

  1. Escape at output, for the right context — `htmlspecialchars(…, ENT_QUOTES |

ENT_SUBSTITUTE, 'UTF-8') or the template engine's auto-escaping; raw-output escape hatches never receive user input. (rules/02`)

  1. **Never unserialize(), eval(), or include/require data you don't fully

control.** External data is JSON. Filter user paths for phar:// and friends. (rules/03)

  1. Uploads: validate by content, rename randomly, store non-executable — never trust

client filename or MIME; never let the webserver execute uploads. (rules/03)

  1. **Passwords via passwordhash() (bcrypt default, or argon2id) + passwordverify;

secrets via randombytes/sodium; compare with hashequals.** Never md5/sha1/ rand()/uniqid() for anything secret. (rules/04)

  1. Sessions hardened: usestrictmode=1, cookies Secure + HttpOnly +

SameSite, sessionregenerateid(true) on privilege change. (rules/04)

  1. **composer.lock committed; CI runs composer install (never update) and

composer audit --locked; prod installs --no-dev.** (rules/05)

  1. **PHPStan (or Psalm) gates CI at the highest level the project can hold; the

baseline only shrinks. OPcache on in prod; performance claims require a profile.** (rules/05, rules/06)