Skip to content

History / Security

Revisions

  • Bring the response document onto the wiki with the rest It was the only security write-up still living in the repository, at docs/security-review-2026-08.md — which is why the link Ed sent the reporter had /blob/ in it. There was never a round-one wiki page; the wiki's whole history only ever held the round-two and round-three pages. Two things in it had rotted since it was sent, and both are now fixed here and flagged in place rather than silently corrected: - it linked to security/findings-2026-08, a branch since merged and deleted - all eight commit ids in its table were pre-rebase and are orphaned; the table now carries the ids that exist on main, with a note that F5 sits out of sequence because it reached main as a cherry-pick The page opens by saying what it is — a record of what was said at the time, not a live document — and points at the round pages for the current position, because its own Outstanding section is now historical and mostly closed. Linked from Security.md, the round-two developer guide and the sidebar.

    @edmozley edmozley committed Aug 12, 2026
  • Correct the outstanding count, and add the guard that was missed Ed asked whether the Security page's summary — "two significant items remain open" — was accurate. It was not. Checking it turned up a third: a fail-open access guard in the task service, the last of the round-two list's "S3's cousins", now fixed in 980b0939. Both round-three pages gain the finding, the plain-English one as item 8 and the developer guide as 6b with the lock-wait reproduction. Security.md now lists the two genuinely open items separately from the two unscheduled features, rather than rolling everything into one sentence ending "and the rest" — which was the phrasing that let a miscount hide.

    @edmozley edmozley committed Aug 12, 2026
  • Document round three of the security work Two new pages for the nine findings deferred when round two merged, following the same pair as before: plain English for an operator, and a developer guide that gives each finding its risk, a reproducible proof of concept, the mitigation and why that mitigation actually closes it. The existing round-two pages now say what has been superseded and what has not, rather than leaving a reader to work out that their outstanding sections are partly historical. Security.md carries both new links, and the sidebar lists all four. Care taken to keep the same framing Erlend asked for: the outstanding sections lead, they name CSRF and lms/content as open in main today, and the round-three guide records where a mitigation is conditional rather than absolute — the CSP layer on the branding directory is skipped entirely without mod_headers, which was measured on a stock WAMP rather than assumed.

    @edmozley edmozley committed Aug 12, 2026
  • Mark the security work merged, and keep the open findings visible Erlend signed the branch off on 2026-08-12 and it has fast-forwarded into main at 86f8d257, so the "awaiting sign-off" and "not yet merged" banners on both hardening pages were wrong. His one substantive request was about framing rather than code: the deferred items must not read as closed. S2 is four live cross-tenant bugs reachable in main today, not a hardening backlog. Both pages now say that plainly, and the Security page — which described none of this and was the page an evaluator would actually land on — now carries the disclosure history and points at the outstanding list. Also corrects the default-admin bullet on Security: the published password is still admin/freeitsm, but since S5 the account is seeded with must_change_password so it cannot survive first sign-in, and Database Verification flags older installs still using it.

    @edmozley edmozley committed Aug 12, 2026
  • Absorb the README's deep-dive content ahead of the README slim-down The project README is being reduced to a landing page; every fact it held that the wiki lacked is merged here first (615 lines across 33 pages): the full email-threading & reply-flow design onto Tickets, directory layout + module-page pattern + file-locations reference onto Architecture, per-endpoint tables onto API Reference, MFA login flow + LDAP subsection + injection/audit notes onto Security, the icon library and editor internals onto Network Mapper, Branding + landing-page and help/search internals + debug-tool depth onto System, planned objects onto CMDB, custody/locations/warranty onto Assets, and more. Also corrects stale claims found during the audit: the Knowledge audience table still said customer-visible articles had no reader (the portal Knowledge section shipped), a pre-#903 Portal-Privacy ambiguity row, the Workflows trigger-wiring section (catalogue spans every module now), the superseded System module-access bullet, the Multi-Tenancy users page marked "Planned" for a shipped feature, and the locale count (21 languages incl. Ukrainian, not 20). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

    @edmozley edmozley committed Jul 21, 2026
  • RBAC wiki: verified against the code, and two stale claims corrected Checked every claim the Roles pages make against what the code actually does — not by reading the wiki back to myself, but by generating the truth from capabilities.php / the manifests and comparing: 16 modules ✓ 76 capabilities ✓ 143 guarded endpoints ✓ every module has a <module>.manage umbrella ✓ the umbrella satisfies every capability in its module ✓ 9 personal-preference tabs declare no capability ✓ an undefined key grants nothing ✓ module 'system' resolves to is_admin ✓ the registry is derived from the manifests ✓ every per-module capability count and every 'sensitive' badge ✓ Two things were stale, both now fixed: 1. The setting-key list in settings_keys.php was described as "a residual list of modules not yet converted, which shrinks to nothing". It doesn't: every module IS converted, and what remains is the System module's keys — permanently, by design, because System is deliberately administrator-only. Corrected in the wiki and in the code comment. 2. The "guard writes, never reads" rule appeared WITHOUT its credentials exception on both Roles & Permissions and Security. Only the dev guide carried it. Since that exception exists precisely because the rule was applied too comfortably — get_mailboxes was a "read", and it shipped the plaintext OAuth secret to every analyst — stating the rule without it is the dangerous half. Also documented two manifest features that had gone in late and never been written up: a tab may carry a plain 'label' instead of 'label_key' where a module isn't translated, and renderSettingsTabBar() takes the tab-switcher's function name (Problem Management's is pmsTab(), and its panels are id="tab-x" not "x-tab"). A converter that assumes the conventions renders a tab bar whose tabs open nothing. Plus the full field reference for a manifest tab, and the table of shared endpoints that need per-key authorisation — a recurring shape, not a one-off.

    @edmozley edmozley committed Jul 14, 2026
  • RBAC: the manifest is now the single declaration, and document D005 Roles — Developer Guide: the recipe changed. The capability registry, the module list and the setting-key map are all DERIVED from <module>/settings/manifest.php now, so adding a capability is a constant plus a manifest entry — there is no capRegistry() to hand-edit and no settings_keys.php row to promote. Calls out the one seam derivation doesn't cross (a Cap:: constant no manifest claims, which is a capability nobody can hold — so any guard using it 403s everyone but admins, permanently and invisibly to the admin who bypasses the check). Adds a section on D005, the endpoint audit, and the discipline behind it: type safety catches a MISSPELLED permission, nothing catches one nobody wrote. Lists the five holes that were each found by hand, by accident. And the rule that keeps the tool useful — if you add an auth mechanism, teach it, because its first run gave five criticals of which four were false alarms, and a scanner that cries wolf is ignored within a week. Security: adds the auditing section so the tool is discoverable from the security page, not just the developer guide.

    @edmozley edmozley committed Jul 13, 2026
  • RBAC: bring the wiki up to date with per-tab capabilities Both Roles pages predated the per-tab decision and described a system that no longer exists: rbacCapabilities() (now capRegistry), bare-string guards (now Cap:: constants), "one manage per module, split later" (we went per-tab), and a rename that orphans grants and needs a data migration (there's an alias map now). Neither mentioned the settings manifest, the shared-endpoint key ownership, the sensitive badge, the umbrella, or the security fix. Roles & Permissions — rewritten around the per-tab model: why a tab is the unit (vCenter credentials sit next to a lookup list), the umbrella, sensitive badging, and a full "how it's enforced" section covering all three mechanisms — panels not rendered rather than hidden, hard guards on every write endpoint, and per-KEY authorisation on the shared settings endpoint (including the #829 hole it closed). Plus what is deliberately NOT guarded, and why gating a read breaks the module. Roles — Developer Guide — rewritten as the extension guide: why capabilities are constants (a mistyped string 403s silently and is invisible to admins, who bypass the check — so the typo becomes a privilege escalation), adding/renaming/removing a capability, and the full six-step recipe for converting a module, worked against Asset Management. Now carries the traps that actually bit: a get_* endpoint that isn't a read (get_vcenter performs the sync and Servers calls it), endpoints with no guard at all, and the reminder that converting a module is an audit of it. Plus the three-actor HTTP test matrix and a checklist. Security — the Authorisation section was wrong, not just stale: it claimed the System module "cannot be disabled" and is always accessible to active analysts, which stopped being true when is_admin shipped. Rewritten as the three layers, each with its gate and its default, and the note that hiding a button is never the control. Raising the PHP floor — made the constants-to-enums bridge concrete rather than asserted. Shows the actual migration: call sites are a symbol rename an IDE can do and the compiler verifies (a missed one FATALS; you cannot half-finish it), against hunting 200 string literals where a miss keeps working and a typo 403s in silence. The real work is confined to one file. Also states the honest caveat: constants make the typo loud, an enum makes the wrong thing impossible.

    @edmozley edmozley committed Jul 13, 2026
  • Add AI Providers page (shared provider layer + OpenRouter); refresh AI references across wiki

    @edmozley edmozley committed Jun 4, 2026
  • Add SSO/OIDC page + Keycloak (Docker) setup subpage

    @edmozley edmozley committed May 30, 2026
  • Initial wiki: home, 18 module pages, installation, architecture, security, API reference, browser extension, sidebar

    @edmozley edmozley committed May 13, 2026