|
|
@@ -1117,6 +1117,25 @@ with a `BOOTSTRAP_ADMIN` audit row.
|
|
|
the behaviour in. Tests: 150 / 430 (was 149 / 424). First fix
|
|
|
from `doc/REVIEW_01.md`.
|
|
|
|
|
|
+- [x] **R01-N11 — Whitelist column in `AuditRepository::distinctColumn`**
|
|
|
+ (`4ae1817`). The private helper interpolated its `$col` argument
|
|
|
+ directly into SQL (`"SELECT DISTINCT {$col} FROM audit_log ORDER BY
|
|
|
+ {$col} ASC"`). Both internal callers (`distinctActions`,
|
|
|
+ `distinctEntityTypes`) pass literal strings, so it was
|
|
|
+ non-exploitable today, but the contract was implicit — any future
|
|
|
+ caller wiring user input through the helper would hand over a SQL
|
|
|
+ injection vector. Added an explicit
|
|
|
+ `in_array($col, ['action', 'entity_type'], true)` whitelist at the
|
|
|
+ top of `distinctColumn()`; anything else throws
|
|
|
+ `\InvalidArgumentException` before the SQL is prepared. The phpdoc
|
|
|
+ was tightened to the literal-string union (`'action'|'entity_type'`)
|
|
|
+ so static analysers carry the contract too. New
|
|
|
+ `tests/Repositories/AuditRepositoryTest.php` (4 cases) covers the
|
|
|
+ happy paths for both supported columns and two reflection-based
|
|
|
+ regression guards (rejects `user_email`, rejects an injection
|
|
|
+ attempt). Tests: 163 / 417 (was 159 / 413). Fifth fix from
|
|
|
+ `doc/REVIEW_01.md`.
|
|
|
+
|
|
|
- [x] **New sprint form: drop weeks input + task list row hover**
|
|
|
(`3728106`). The `/sprints/new` form no longer collects an
|
|
|
`n_weeks` value — the week count is derived from `start_date` /
|
|
|
@@ -1233,6 +1252,7 @@ before acting — nothing here is load-bearing once it grows stale.
|
|
|
## 13. Git history (as of this writing)
|
|
|
|
|
|
```
|
|
|
+4ae1817 Fix R01-N11: whitelist column in AuditRepository::distinctColumn
|
|
|
d16bff4 Fix R01-N15: add noreferrer to external task URL link
|
|
|
48a351c Docs: mark R01-N01 fixed, refresh SPEC §9 / §11 / §13
|
|
|
857df15 Fix R01-N01: hash-only LOCAL_ADMIN_PASSWORD_HASH (no plaintext fallback)
|