Skip to content

Commit 64e97f3

Browse files
Claude/integrate security tools h nyd u (#8)
Co-authored-by: Claude <noreply@anthropic.com>
1 parent 6abdcfa commit 64e97f3

3 files changed

Lines changed: 228 additions & 5 deletions

File tree

COMPATIBILITY.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
# php-aegis Compatibility Strategy
22

3+
> **Note**: This document describes the planned compatibility strategy. The `php-aegis-compat` package is not yet implemented. See the [roadmap](ROADMAP_PRIORITY.md) for status.
4+
35
## The Problem
46

57
php-aegis requires PHP 8.1+, but WordPress officially supports PHP 7.4+. This limits adoption in the WordPress ecosystem where many hosts still run PHP 7.4 or 8.0.
68

79
## Strategy: Dual-Package Approach
810

9-
Instead of downgrading the main library, we provide a separate compatibility package.
11+
Instead of downgrading the main library, we will provide a separate compatibility package.
1012

1113
```
12-
hyperpolymath/php-aegis # PHP 8.1+ (main, recommended)
13-
hyperpolymath/php-aegis-compat # PHP 7.4+ (polyfill, limited)
14+
hyperpolymath/php-aegis # PHP 8.1+ (main, recommended) ✅ Available
15+
hyperpolymath/php-aegis-compat # PHP 7.4+ (polyfill, limited) 📋 Planned
1416
```
1517

1618
### Why Not Downgrade?

HANDOVER_SANCTIFY.md

Lines changed: 216 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -486,13 +486,227 @@ exit;
486486

487487
---
488488

489+
## Additional Findings (Report 4: sinople-theme Full Integration)
490+
491+
### 14. Successful Integration Pattern
492+
493+
**What Worked**: Full integration with WordPress theme including:
494+
- Function wrappers: `sinople_aegis_html()`, `sinople_aegis_attr()`, `sinople_aegis_json()`
495+
- Validation wrappers: `sinople_aegis_validate_*()` functions
496+
- RDF/Turtle feed endpoint using `TurtleEscaper` (unique value!)
497+
- Graceful fallback to WordPress functions when php-aegis unavailable
498+
- Unit tests for the integration
499+
500+
**Key Success**: TurtleEscaper proved its unique value by enabling a `/feed/turtle/` endpoint.
501+
502+
### 15. sanctify-php False Positives Identified
503+
504+
**Issues to address**:
505+
506+
1. **UnsafeRedirect false positive**: When `exit;` is on the next line
507+
```php
508+
// This triggers false positive:
509+
wp_redirect($url);
510+
exit;
511+
512+
// sanctify-php expects:
513+
wp_redirect($url); exit;
514+
```
515+
516+
2. **MissingTextDomain false positive**: Flags WordPress core functions
517+
```php
518+
// This may be flagged incorrectly:
519+
__('Text', 'theme-domain'); // OK
520+
_e('Text', 'theme-domain'); // OK
521+
esc_html__('Text'); // May flag - but sometimes domain is optional
522+
```
523+
524+
**Recommendation**: Add configuration options:
525+
```yaml
526+
# sanctify.yml
527+
rules:
528+
UnsafeRedirect:
529+
allow_next_line_exit: true
530+
MissingTextDomain:
531+
ignore_core_functions: true
532+
```
533+
534+
### 16. PHP 8.1+ Syntax Verification Needed
535+
536+
**Concern**: Parser may not handle modern PHP syntax.
537+
538+
**Test cases to verify**:
539+
```php
540+
// Nullsafe operator (PHP 8.0+)
541+
$value = $object?->property?->method();
542+
543+
// Match expression (PHP 8.0+)
544+
$result = match($type) {
545+
'html' => Sanitizer::html($input),
546+
'js' => Sanitizer::js($input),
547+
default => $input,
548+
};
549+
550+
// Constructor property promotion (PHP 8.0+)
551+
public function __construct(
552+
private readonly string $name,
553+
) {}
554+
555+
// First-class callable syntax (PHP 8.1+)
556+
$fn = Sanitizer::html(...);
557+
```
558+
559+
### 17. Guix Export Documentation
560+
561+
**Issue**: Guix package export documentation is incomplete.
562+
563+
**Recommendation**: Add to sanctify-php docs:
564+
```scheme
565+
;; guix.scm
566+
(use-modules (guix packages)
567+
(guix git-download)
568+
(guix build-system haskell))
569+
570+
(package
571+
(name "sanctify-php")
572+
(version "0.1.0")
573+
(source (git-reference
574+
(url "https://github.com/hyperpolymath/sanctify-php")
575+
(commit (string-append "v" version))))
576+
(build-system haskell-build-system)
577+
(synopsis "PHP security static analyzer")
578+
(license license:agpl3+))
579+
```
580+
581+
---
582+
583+
## php-aegis Self-Identified Issues (Report 4)
584+
585+
These issues were discovered during sinople-theme integration:
586+
587+
| Issue | Status | Resolution |
588+
|-------|--------|------------|
589+
| `Headers::secure()` missing `permissionsPolicy()` | ✅ Fixed | Added in this PR |
590+
| `php-aegis-compat` package doesn't exist | 📋 Planned | Create separate repo |
591+
| Not published on Packagist | 📋 Planned | Publish after v0.2.0 |
592+
| WordPress mu-plugin adapter not implemented | 📋 Planned | Phase 7 roadmap |
593+
594+
---
595+
596+
## Additional Findings (Report 5: Sinople Theme - Critical Vulnerability Fixed)
597+
598+
### 18. TurtleEscaper Fixed Real Vulnerability
599+
600+
**Critical Finding**: The theme was using `addslashes()` for RDF Turtle escaping - this is SQL escaping, NOT Turtle escaping. This was a real RDF injection vulnerability.
601+
602+
**Before (vulnerable)**:
603+
```php
604+
// DANGEROUS: addslashes() is SQL escaping, not Turtle escaping!
605+
$turtle = '"' . addslashes($label) . '"@en';
606+
```
607+
608+
**After (fixed)**:
609+
```php
610+
use PhpAegis\TurtleEscaper;
611+
$turtle = TurtleEscaper::literal($label, language: 'en');
612+
```
613+
614+
**This validates TurtleEscaper as the #1 unique value proposition of php-aegis.**
615+
616+
### 19. Security Fixes Applied in Real Integration
617+
618+
| Severity | Issue | Fix Applied |
619+
|----------|-------|-------------|
620+
| CRITICAL | `addslashes()` for Turtle | `TurtleEscaper::literal()` |
621+
| CRITICAL | IRI interpolation | `Validator::url()` + error handling |
622+
| HIGH | URL validation via `strpos()` | `parse_url()` host comparison |
623+
| HIGH | Unsanitized Micropub input | `sanitize_text_field()` + `wp_kses_post()` |
624+
| MEDIUM | No security headers | `Headers::secure()` equivalent |
625+
| MEDIUM | No rate limiting | 1-min rate limit for Webmentions |
626+
| LOW | Missing `strict_types` | Added to all files |
627+
628+
### 20. New Detection Rules for sanctify-php
629+
630+
**RDF Turtle as Distinct Output Context**:
631+
632+
sanctify-php should recognize Turtle output contexts and flag:
633+
```haskell
634+
-- RDF Turtle detection rules
635+
turtleRules = [
636+
-- Dangerous: SQL escaping in Turtle context
637+
("turtle_addslashes", "addslashes\\s*\\([^)]+\\).*['\"]@[a-z]{2}",
638+
"Use TurtleEscaper::literal() instead of addslashes() for Turtle"),
639+
640+
-- Dangerous: String interpolation in Turtle IRI
641+
("turtle_iri_interp", "<.*\\$[a-zA-Z_].*>",
642+
"Use TurtleEscaper::iri() for Turtle IRIs"),
643+
644+
-- Dangerous: Raw variable in Turtle string
645+
("turtle_string_raw", "\"\\$[a-zA-Z_][^\"]*\"@[a-z]",
646+
"Use TurtleEscaper::string() for Turtle literals")
647+
]
648+
```
649+
650+
**WordPress REST API Pattern Recognition**:
651+
```haskell
652+
-- WordPress REST API rules
653+
restRules = [
654+
("rest_missing_permission", "register_rest_route.*permission_callback.*__return_true",
655+
"REST routes should verify permissions"),
656+
657+
("rest_raw_param", "\\$request\\[.*\\](?!.*sanitize)",
658+
"Sanitize REST API parameters")
659+
]
660+
```
661+
662+
**WordPress Hook Detection** (reduce false positives):
663+
```haskell
664+
-- Functions defined via add_action/add_filter are called by WordPress
665+
wpHookFunctions = extractFunctionsFrom [
666+
"add_action\\s*\\([^,]+,\\s*['\"]([^'\"]+)",
667+
"add_filter\\s*\\([^,]+,\\s*['\"]([^'\"]+)"
668+
]
669+
-- These should not be flagged as "unused functions"
670+
```
671+
672+
### 21. php-aegis Enhancement Requests
673+
674+
From this integration:
675+
676+
| Request | Priority | Notes |
677+
|---------|----------|-------|
678+
| WordPress nonce validator | Medium | `Validator::wpNonce($nonce, $action)` |
679+
| WordPress capability checker | Medium | `Validator::wpCapability($cap)` |
680+
| TurtleEscaper case sensitivity docs | Low | Language tags should be lowercase |
681+
| SPDX identifier validator | Low | `Validator::spdx($identifier)` |
682+
| Headers + WordPress integration docs | Medium | How to use with `wp_headers` filter |
683+
684+
---
685+
686+
## Final Summary: Integration Value Matrix
687+
688+
| Tool | WordPress Value | Non-WP Value | Unique Capability |
689+
|------|----------------|--------------|-------------------|
690+
| **php-aegis** | Low (WP has `esc_*`) | **High** | RDF/Turtle escaping |
691+
| **sanctify-php** | **High** (finds WP issues) | **High** | Taint tracking |
692+
693+
### Key Learnings Across 5 Reports
694+
695+
1. **TurtleEscaper is the killer feature** - Fixed real vulnerabilities in semantic web themes
696+
2. **GHC barrier is critical** - Confirmed in every sanctify-php integration attempt
697+
3. **WordPress has comprehensive APIs** - php-aegis basic escaping is redundant
698+
4. **php-aegis shines in framework gaps** - Security headers, extended validators, RDF/Turtle
699+
5. **sanctify-php needs WordPress awareness** - Hook detection, REST API patterns
700+
701+
---
702+
489703
## Contact
490704

491705
For questions about this integration or to coordinate between repos:
492706
- php-aegis: https://github.com/hyperpolymath/php-aegis
493707
- sanctify-php: https://github.com/hyperpolymath/sanctify-php
494-
- Integration tested in: wp-sinople-theme, Zotpress
708+
- Integration tested in: wp-sinople-theme, Zotpress, sinople-theme (×2)
495709

496710
---
497711

498-
*Generated from real-world WordPress integration experience (Reports 1, 2 & 3).*
712+
*Generated from real-world WordPress integration experience (Reports 1-5).*

src/Headers.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,13 @@ public static function secure(): void
3333
self::contentSecurityPolicy([
3434
'default-src' => ["'self'"],
3535
]);
36+
self::permissionsPolicy([
37+
'geolocation' => [],
38+
'camera' => [],
39+
'microphone' => [],
40+
'payment' => [],
41+
]);
42+
self::removeInsecureHeaders();
3643
}
3744

3845
/**

0 commit comments

Comments
 (0)