You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CHANGELOG.md
+36Lines changed: 36 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -7,6 +7,42 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
8
8
## [Unreleased]
9
9
10
+
## [1.3.10] - 2026-01-14
11
+
12
+
### Fixed
13
+
-**PHP Security Rules**
14
+
-`php-user-controlled-file-write`: Fixed a shell variable interpolation bug in the inline grep patterns that prevented detection when the file path was derived from PHP superglobals (e.g., `$_GET`, `$_POST`). The rule now reliably flags direct file writes with user-controlled paths.
15
+
-`spo-003-insecure-deserialization`: Hardened the pattern definitions to avoid accidental expansion of shell special variables while scanning for insecure deserialization of superglobal input.
16
+
17
+
### Internal
18
+
- Added an opt-in `DEBUG_PATTERN=1` environment flag for `dist/bin/check-performance.sh` that prints the resolved grep include arguments, patterns, and paths for pattern-based rules to aid future debugging.
19
+
20
+
### Documentation
21
+
- Updated `PROJECT/1-INBOX/RULES-2026-01-14.md` to:
22
+
- Reflect that `php-user-controlled-file-write` is hardened as of v1.3.10.
23
+
- Promote `spo-003-insecure-deserialization` to a Tier 1 PHP rule with clear rationale and examples.
24
+
- Document the `DEBUG_PATTERN=1` flag as a supported internal tool for auditing Tier 1 pattern behavior.
25
+
26
+
## [1.3.9] - 2026-01-14
27
+
28
+
### Added
29
+
-**Tier 1 Security Rules (PHP)** - Direct file writes and hardcoded credentials
30
+
- New rule: `php-user-controlled-file-write` (**CRITICAL**, security)
31
+
- Detects `file_put_contents()`, `fopen()`, and `move_uploaded_file()` calls where the target path is derived directly from PHP superglobals (e.g., `$_GET`, `$_POST`)
Copy file name to clipboardExpand all lines: PROJECT/1-INBOX/BACKLOG.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,7 +1,7 @@
1
1
# Backlog - Issues to Investigate
2
2
3
3
### Checklist - 2025-01-14
4
-
-[ ] Continue with Tier 1 rules
4
+
-[ ] Continue with Tier 1 rules - First 5 completed
5
5
-[ ] Fix tty output for HTML reports (The commit added great new features (init, update, tab completion) with proper TTY detection. However, the original HTML generation code (lines 5848-5863) still writes to /dev/tty unconditionally)
6
6
-[ ] Make a comment in main script to make rules in external files going forward
7
7
-[ ] Breakout check-performance.sh into multiple files and external rule files
Copy file name to clipboardExpand all lines: PROJECT/1-INBOX/RULES-2026-01-14.md
+33-6Lines changed: 33 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -74,7 +74,7 @@ passthru($user_input);
74
74
75
75
---
76
76
77
-
-[] ### 4. Direct file write with user-controlled path
77
+
-[x] ### 4. Direct file write with user-controlled path
78
78
79
79
```php
80
80
// CRITICAL - Arbitrary file write → RCE
@@ -87,11 +87,14 @@ fwrite($handle, $data); // when $handle from user input
87
87
88
88
**False positive rate:** Low (~10%). The pattern of user input → file path is specific.
89
89
90
-
**Current coverage:** Not covered.
90
+
**Current coverage:**
91
+
- PHP: `php-user-controlled-file-write` (Tier 1 rule, implemented in `check-performance.sh` v1.3.9; detection hardened in v1.3.10)
92
+
93
+
**Status:** Implemented in scanner (PHP) as of v1.3.9; detection bug fixed in v1.3.10.
91
94
92
95
---
93
96
94
-
-[] ### 5. Hardcoded credentials in PHP
97
+
-[x] ### 5. Hardcoded credentials in PHP
95
98
96
99
```php
97
100
// CRITICAL - Exposed secrets
@@ -105,7 +108,31 @@ $password = 'admin123';
105
108
106
109
**False positive rate:** Medium (~25%). Example code and tests may trigger this, but the risk of missing a real exposure is too high.
107
110
108
-
**Current coverage:** Client-side JS only (`headless-api-key-exposure`). PHP not covered.
111
+
**Current coverage:**
112
+
- Client-side JS: `headless-api-key-exposure` (existing rule for browser bundles)
113
+
- PHP: `php-hardcoded-credentials` (new Tier 1 rule, implemented in `check-performance.sh` v1.3.9)
114
+
115
+
**Status:** Implemented in scanner (PHP + client-side JS coverage) as of v1.3.9.
116
+
117
+
---
118
+
119
+
-[x] ### 6. Insecure data deserialization from superglobals
120
+
121
+
```php
122
+
// CRITICAL - Object injection / RCE via unserialize/json_decode/maybe_unserialize
123
+
$data = unserialize($_POST['payload']);
124
+
$json = json_decode($_GET['json'], true);
125
+
$value = maybe_unserialize($_REQUEST['data']);
126
+
```
127
+
128
+
**Why always critical:** Deserializing attacker-controlled input enables object injection and arbitrary code execution via magic methods, especially in large plugin ecosystems.
129
+
130
+
**False positive rate:** Low–medium (~15%). Some admin tools may intentionally deserialize trusted payloads, but usage with raw `$_GET` / `$_POST` / `$_REQUEST` is a strong red flag.
131
+
132
+
**Current coverage:**
133
+
- PHP: `spo-003-insecure-deserialization` (Tier 1 rule, implemented in `check-performance.sh` v1.3.10)
134
+
135
+
**Status:** Implemented in scanner (PHP) as of v1.3.10; focuses on deserialization that starts from superglobals to keep false positives manageable.
109
136
110
137
---
111
138
@@ -114,7 +141,6 @@ $password = 'admin123';
114
141
These are also effectively zero-tolerance in modern WordPress/PHP code and should be implemented as dedicated scanner rules:
- Add PHP patterns to match Node.js coverage (including dynamic include/require, eval/create_function, unserialize, `preg_replace` with `/e`, and `assert` with strings)
302
+
- Add PHP patterns to match Node.js coverage (including dynamic include/require, eval/create_function, `preg_replace` with `/e`, and `assert` with strings; insecure `unserialize` from superglobals is covered by `spo-003-insecure-deserialization` as of v1.3.10)
277
303
- Build should fail on any match
278
304
- Baseline exceptions are **strongly discouraged**; if used, they MUST include explicit justification, be reviewed by a human, and still appear as warnings (e.g., "BASELINED CRITICAL ISSUE")
279
305
- These are "stop the line" issues
306
+
- Scanner internals: when debugging Tier 1 patterns, `DEBUG_PATTERN=1` can be set when running `check-performance.sh` to log the resolved grep patterns and include arguments without changing behavior.
"description": "Detects API keys, secrets, tokens, or passwords hardcoded into PHP source files.",
316
+
"detection_type": "direct",
317
+
"pattern_type": "php",
318
+
"mitigation_detection": false,
319
+
"heuristic": false,
320
+
"file": "php-hardcoded-credentials.json"
321
+
},
308
322
{
309
323
"id": "php-shell-exec-functions",
310
324
"version": "",
@@ -319,6 +333,20 @@
319
333
"heuristic": false,
320
334
"file": "php-shell-exec-functions.json"
321
335
},
336
+
{
337
+
"id": "php-user-controlled-file-write",
338
+
"version": "1.0.0",
339
+
"enabled": true,
340
+
"category": "security",
341
+
"severity": "CRITICAL",
342
+
"title": "Direct file write with user-controlled path",
343
+
"description": "Detects file writes where the target path is derived directly from PHP superglobals (user-controlled input). This is a common pattern for arbitrary file write vulnerabilities.",
0 commit comments