|
1 | 1 | // SPDX-License-Identifier: PMPL-1.0-or-later |
2 | | -= php-aegis — Show Me The Receipts |
| 2 | +// SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk> |
| 3 | += php-aegis — PHP Security Toolkit — Show Me The Receipts |
3 | 4 | :toc: |
4 | 5 | :icons: font |
5 | 6 |
|
6 | | -The README makes claims. This file backs them up. |
| 7 | +The README makes claims. This file backs them up. php-aegis is a PHP 8.1+ |
| 8 | +security toolkit: input validation, context-aware sanitization, security headers, |
| 9 | +and (uniquely) W3C-compliant RDF/Turtle escaping. Named after the mythological |
| 10 | +shield of Zeus. |
| 11 | + |
| 12 | +== Claim: Zero-dependency, type-safe, context-aware output escaping |
7 | 13 |
|
8 | 14 | [quote, README] |
9 | 15 | ____ |
10 | | -See link:POSITIONING.md[POSITIONING.md] for detailed guidance. |
| 16 | +A PHP security and hardening toolkit providing input validation, sanitization, |
| 17 | +and security utilities. Zero Dependencies — core library has no external |
| 18 | +dependencies. Type Safety — full strict_types enforcement throughout. |
| 19 | +Context-Aware Sanitization — HTML, JS, CSS, URL, and JSON output escaping. |
11 | 20 | ____ |
12 | 21 |
|
13 | | -== File Map |
| 22 | +Every source file opens with `declare(strict_types=1)`. The `Validator` class |
| 23 | +(`src/Validator.php`) uses only PHP built-ins — `filter_var`, `preg_match`, |
| 24 | +`parse_url` — with no Composer runtime dependencies. `Sanitizer::html()` calls |
| 25 | +`htmlspecialchars($input, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8')` with explicit |
| 26 | +charset enforcement. `Sanitizer::js()` escapes to Unicode escape sequences |
| 27 | +(`\uXXXX`) for characters outside the safe printable ASCII set. `Sanitizer::css()` |
| 28 | +strips everything outside alphanumeric and safe CSS punctuation. The `Headers` |
| 29 | +class (`src/Headers.php`) calls PHP's `header()` function and `Headers::secure()` |
| 30 | +is a single-call method that sets CSP, HSTS, X-Frame-Options, Referrer-Policy, |
| 31 | +Permissions-Policy, and removes `X-Powered-By` and `Server` headers in one |
| 32 | +invocation. |
| 33 | + |
| 34 | +**Caveat:** "Zero dependencies" applies to the runtime library. The dev toolchain |
| 35 | +(PHPUnit, PHPStan, php-cs-fixer) are Composer dev-dependencies. The library does |
| 36 | +not handle SQL injection prevention (use PDO prepared statements), CSRF (use |
| 37 | +framework tokens), authentication, or encryption — these are explicit non-goals |
| 38 | +documented in the README's "What php-aegis Does NOT Do" section. |
| 39 | + |
| 40 | +- Validator: `src/Validator.php` |
| 41 | +- Sanitizer: `src/Sanitizer.php` |
| 42 | +- Headers: `src/Headers.php` |
| 43 | +- Tests: `tests/` (PHPUnit) |
| 44 | + |
| 45 | +== Claim: RDF/Turtle escaping — a unique differentiator with no other PHP library equivalent |
| 46 | + |
| 47 | +[quote, README] |
| 48 | +____ |
| 49 | +RDF/Turtle Escaping — unique W3C-compliant semantic web security (no other PHP |
| 50 | +lib does this). Best for: Semantic web applications (RDF/Turtle escaping — |
| 51 | +unique to php-aegis). |
| 52 | +____ |
| 53 | + |
| 54 | +`TurtleEscaper` (`src/TurtleEscaper.php`) implements W3C Turtle 1.1 string and |
| 55 | +IRI escaping. `TurtleEscaper::string()` escapes the characters required by the |
| 56 | +Turtle grammar: backslash, double-quote, newlines, carriage returns, tabs, and |
| 57 | +the extended escape sequences `\t \b \n \r \f`. `TurtleEscaper::iri()` validates |
| 58 | +IRI structure and percent-encodes characters that are invalid in IRIs. |
| 59 | +`TurtleEscaper::literal()` wraps a string in Turtle literal syntax with optional |
| 60 | +language tag (`"value"@en`) or datatype (`"value"^^xsd:type`). |
| 61 | +`TurtleEscaper::triple()` builds a complete subject-predicate-object triple |
| 62 | +string ending with ` .`. Without this escaping, user-supplied strings injected |
| 63 | +into Turtle documents would break the RDF serialisation or permit injection of |
| 64 | +arbitrary triples — a real attack surface in IndieWeb and Linked Data |
| 65 | +applications. |
| 66 | + |
| 67 | +**Caveat:** The IndieWeb integration work (Micropub, IndieAuth, Webmention |
| 68 | +helpers) is on the roadmap but not yet complete. The `src/IndieWeb/` directory |
| 69 | +exists but implementation and validation depth are noted in the README as needing |
| 70 | +to catch up to the design documentation. |
| 71 | + |
| 72 | +- Implementation: `src/TurtleEscaper.php` |
| 73 | +- IndieWeb stubs: `src/IndieWeb/` |
| 74 | +- Related: `HANDOVER_SANCTIFY.md` (integration notes with sanctify-php) |
| 75 | + |
| 76 | +== Dogfooded Across The Account |
14 | 77 |
|
15 | 78 | [cols="1,2"] |
16 | 79 | |=== |
| 80 | +| Technology | Also Used In |
| 81 | + |
| 82 | +| **PHP 8.1+ security tooling** | https://github.com/hyperpolymath/sanctify-php[sanctify-php] |
| 83 | + (static analysis companion), https://github.com/hyperpolymath/proof-of-work[proof-of-work] |
| 84 | + (spam prevention), the NUJ and LCB websites (production PHP deployments) |
| 85 | +| **WordPress adapter pattern** | `src/WordPress/` adapter (23 functions + MU-plugin) |
| 86 | + mirrors the adapter architecture in https://github.com/hyperpolymath/project-wharf[project-wharf] |
| 87 | + (`adapters/wordpress-wharf/`) |
| 88 | +| **Semantic web / RDF** | RDF tooling appears in |
| 89 | + https://github.com/hyperpolymath/rrecord-verity[rrecord-verity] and the |
| 90 | + IndieWeb stack across the account |
| 91 | +| **PHPStan + PHPUnit** | Standard PHP quality tooling in this repo and |
| 92 | + https://github.com/hyperpolymath/sanctify-php[sanctify-php] |
| 93 | +|=== |
| 94 | + |
| 95 | +== File Map |
| 96 | + |
| 97 | +[cols="1,3"] |
| 98 | +|=== |
17 | 99 | | Path | What's There |
18 | 100 |
|
19 | | -| `src/` | Source code |
20 | | -| `test(s)/` | Test suite |
| 101 | +| `src/Validator.php` |
| 102 | +| Input validation. All methods static. Covers: email, URL, HTTPS-URL, IPv4, |
| 103 | + IPv6, UUID, slug, JSON, integer (with range), domain, hostname, semver, |
| 104 | + ISO 8601, hex colour, null-byte detection, safe filename check, printable-ASCII |
| 105 | + check. Uses `filter_var` and `preg_match` with no external deps. |
| 106 | + |
| 107 | +| `src/Sanitizer.php` |
| 108 | +| Context-aware output escaping. All methods static. Contexts: HTML |
| 109 | + (`htmlspecialchars` + UTF-8), JS (Unicode escape sequences), CSS (allowlist |
| 110 | + chars only), URL (`rawurlencode`), JSON (`json_encode` with flags), filename |
| 111 | + (strip path separators and null bytes). |
| 112 | + |
| 113 | +| `src/Headers.php` |
| 114 | +| Security headers. `Headers::secure()` is the single-call hardening method. |
| 115 | + Individual methods: `contentSecurityPolicy()`, `strictTransportSecurity()`, |
| 116 | + `frameOptions()`, `referrerPolicy()`, `permissionsPolicy()`, |
| 117 | + `removeInsecureHeaders()`. |
| 118 | + |
| 119 | +| `src/TurtleEscaper.php` |
| 120 | +| W3C Turtle 1.1 escaping. Methods: `string()`, `iri()`, `literal()`, |
| 121 | + `triple()`. Unique in the PHP ecosystem. |
| 122 | + |
| 123 | +| `src/IndieWeb/` |
| 124 | +| IndieWeb helpers (Micropub, IndieAuth, Webmention). Partially implemented. |
| 125 | + |
| 126 | +| `src/RateLimit/` |
| 127 | +| Rate limiting (documented in roadmap; not yet release-complete). |
| 128 | + |
| 129 | +| `src/WordPress/` |
| 130 | +| WordPress integration: 23 adapter functions and an MU-plugin for drop-in |
| 131 | + use in WordPress environments. |
| 132 | + |
| 133 | +| `composer.json` |
| 134 | +| Project manifest. `require` section is empty (zero runtime deps). |
| 135 | + `require-dev`: phpunit, phpstan, php-cs-fixer. |
| 136 | + |
| 137 | +| `phpstan.neon` |
| 138 | +| PHPStan configuration. Level 8 (strict) analysis. |
| 139 | + |
| 140 | +| `phpunit.xml` |
| 141 | +| PHPUnit test configuration. |
| 142 | + |
| 143 | +| `manifests/` |
| 144 | +| Container and deployment manifests. |
| 145 | + |
| 146 | +| `docs/` |
| 147 | +| Design documents, positioning guide, validation findings. |
| 148 | + |
| 149 | +| `PRIORITY.adoc` |
| 150 | +| Ordered list of remaining work before public release. |
| 151 | + |
| 152 | +| `HANDOVER_SANCTIFY.md` |
| 153 | +| Integration guide for teams using both php-aegis and sanctify-php. |
| 154 | + |
| 155 | +| `PHP_AEGIS_ANALYSIS_SUMMARY.md` |
| 156 | +| Analysis summary of current feature completeness. |
| 157 | + |
| 158 | +| `PHP_AEGIS_DEVELOPMENT_PLAN.md` |
| 159 | +| Development plan with phase milestones. |
| 160 | + |
| 161 | +| `validation/FINDINGS-AND-RECOMMENDATIONS.md` |
| 162 | +| Validation evidence document. Use alongside `PRIORITY.adoc` to judge |
| 163 | + release readiness. |
| 164 | + |
| 165 | +| `.machine_readable/6a2/` |
| 166 | +| A2ML checkpoint files: STATE, META, ECOSYSTEM, AGENTIC, NEUROSYM, PLAYBOOK. |
21 | 167 | |=== |
22 | 168 |
|
23 | | -== Questions? |
| 169 | +== Checking It |
| 170 | + |
| 171 | +[source,bash] |
| 172 | +---- |
| 173 | +# Install dev deps |
| 174 | +composer install |
| 175 | +
|
| 176 | +# Run tests |
| 177 | +just test |
| 178 | +# or: vendor/bin/phpunit |
| 179 | +
|
| 180 | +# Static analysis (PHPStan level 8) |
| 181 | +just analyze |
| 182 | +# or: vendor/bin/phpstan analyse src |
| 183 | +
|
| 184 | +# Check code style |
| 185 | +just lint |
| 186 | +# or: vendor/bin/php-cs-fixer fix --dry-run |
| 187 | +---- |
| 188 | + |
| 189 | +== Honest Status |
24 | 190 |
|
25 | | -Open an issue or reach out directly — happy to explain anything in more detail. |
| 191 | +v0.1.1 is feature-complete for the core: validation, sanitization, headers, |
| 192 | +and Turtle escaping. The remaining work before a public Packagist release |
| 193 | +is concentrated in test completeness, publication validation evidence, and |
| 194 | +the IndieWeb/rate-limiting roadmap items. See `PRIORITY.adoc` for the |
| 195 | +ordered task list and `validation/FINDINGS-AND-RECOMMENDATIONS.md` for the |
| 196 | +evidence gap analysis. |
0 commit comments