Internal Audit Report — 2026 Q2

Field Value
Document ID IA-2026-Q2
Audit period 2026-03-20 (Sweep 1) and 2026-03-20 (Sweep 2)
Report effective date 2026-04-30
Auditor Peter Sterkenburg (Founder & operator), assisted by Anthropic Claude Code (LLM-driven static-review tool)
Audit standard ISO/IEC 27001:2022 clause 9.2 (Internal audit)
Root scope reference ISMS scope statement §2

§1 Audit objective

Assess whether the PortalPilot information security management system (in-scope assets per the public scope statement §2) operates effectively against:

  1. The control objectives of ISO/IEC 27001:2022 Annex A (when published in the upcoming compliance pack release).
  2. The five SOC 2 Trust Service Criteria as documented in the equivalence map.
  3. The HubSpot Marketplace pre-submission security baseline (driver for the original Sweep 1 cadence).
  4. The customer-facing DPA commitments, particularly the 72-hour breach-notification commitment and the sub-processor-list reconciliation.

The audit's secondary objective is to surface defects in the agent-security model (Claude Code + Mistral second-opinion), since the agent itself is part of the in-scope security boundary.


§2 Scope

The audit covered the entirety of the in-scope-assets section of the public scope statement §2, namely:

Out-of-scope (per the public scope statement §3): the founder's development laptop, HubSpot Inc. as a vendor, customer-side HubSpot portal data at rest in HubSpot.


§3 Methodology

Approach

Adversarial review by the founder, augmented by Claude Code (LLM-driven static-review tool), proceeded domain-by-domain with an attacker-perspective lens. For each domain the methodology was:

  1. Code-path enumeration — list every public-reachable code path (React route, edge function, public RPC).
  2. Auth + ownership verification — for each path, verify that authentication is enforced and that data-ownership checks gate every read/write of customer-scoped data.
  3. Input-validation review — verify that every parameter accepted from the network is type-checked, range-checked, and denied-by-default for unrecognised shapes.
  4. Error-handling review — verify that errors return generic messages to the client; full diagnostic detail goes only to the structured log.
  5. Side-channel review — examine logs, audit trails, RPC error messages, and HTTP response headers for unintended information disclosure.

Sweep 2 added a fix-verification pass over Sweep 1's HIGH findings, plus extension into payments, CI pipeline, enterprise readiness, and the agent-security model itself.

Limitations of the methodology


§4 Findings register — summary

Statistics across both sweeps

Severity Sweep 1 (2026-03-20) Sweep 2 (2026-03-20) Combined Status (Closed / Open / Accepted)
Critical 0 0 0 n/a
High 7 4 11 11 / 0 / 0
Medium 15 14 29 25 / 4 / 0
Low 8 15 23 18 / 5 / 0
Info 5 3 8 0 / 0 / 8 (informational, no closure required)
Total 35 36 71 54 / 9 / 8

All eleven HIGH findings (7 from Sweep 1 + 4 from Sweep 2) closed before pre-marketplace submission. All Sweep-1 HIGH closures were re-verified in Sweep 2 with no regressions.

Top findings — closure detail

The five highest-impact findings and their closure path:

Finding Severity Annex A control affected Closure
Missing portal-ownership checks in 4 edge functions (workflows-analyze, spot-check-accounts, generate-executive-summary, generate-remediation-playbook) — any authenticated user could access another tenant's HubSpot data High A.5.15, A.8.2, A.8.3 ClosedrequirePortalAccess middleware added to all 4 edge functions; 26-edge-function audit confirmed coverage
No IP-level rate limiting on the login endpoint — credential-stuffing across many email addresses bypassed per-email lockout High A.5.15, A.8.5, A.8.20 Closed — IP-level rate limiting via checkRateLimitByUser; fail-closed on DB error
Incomplete GDPR data-deletion cascade — right to erasure left orphan rows in 49 tables High A.5.34, A.8.10, A.8.11 Closed — comprehensive deletion now covers 39 portal-keyed tables + 10 user-keyed tables
edge_function_logs RLS allowed any authenticated user to read all rows High A.5.15, A.8.3, A.8.16 Closed — RLS now restricts to has_role(auth.uid(), 'admin'::app_role)
Mollie upgradeCredit server-trust bypass — a client-supplied credit value was trusted server-side, enabling discounted subscriptions via crafted requests High A.5.15, A.8.27, A.8.32 Closed — server-side server-trust check added; client-supplied credit ignored

Open items at this report's effective date

Nine items (4 Medium + 5 Low) remain open. None are HIGH-severity. Status snapshot:

Open item Severity Annex A control Reason still open
Backups not GPG-encrypted before transit to Hetzner snapshot store Medium A.5.30, A.8.13, A.8.24 Hetzner snapshot is on the same provider; transit is intra-Hetzner-network; full disk LUKS already in place. Fix planned in Phase 2 alongside off-site backup work
CI runner shares production server Medium A.5.32, A.8.32 Acknowledged trade-off; CI is constrained to read-only operations + scoped deploy keys; Phase 2 to migrate CI to a separate Hetzner project
track-ai-usage portal enumeration possible via crafted UUID Medium A.5.15, A.8.3 Mitigated by rate limiting on the function; full ownership-gate fix queued
Service-worker cache poisoning on logout Medium A.5.15, A.8.27 UI workaround in place (forced reload on logout); architectural fix queued
Anon-key rotation cadence not formalised Low A.5.16, A.8.5 Procedure documented; cadence to be set in Q3 2026
Mixed Deno-import versions in three edge functions Low A.8.30, A.8.32 Cosmetic; tracked in dependency-cleanup backlog
Two npm dependencies on ^x.y.z rather than exact pin Low A.5.32, A.8.30 Risk-accepted; package-lock.json provides effective pinning
Encryption-key entropy spec not documented Low A.5.17, A.8.24 Documented internally during this audit period; pending public-doc reflection
CSP default-src could be tightened to self Low A.8.27, A.8.28 Cosmetic; queued in front-end hardening backlog

The full per-finding evidence and remediation rationale is held in the audit archive, available to enterprise procurement reviewers under NDA.


§5 Annex A control coverage tested

The audit tested controls across all four Annex A themes. Coverage by theme:

Theme Controls touched (approx.) Coverage characterisation
A.5 Organizational (37 controls) ~22 controls touched Auth, access control, classification, supplier relationships, incident management — comprehensively tested. Strategic / governance controls (e.g. A.5.1 policies, A.5.4 management direction) were attested rather than empirically tested
A.6 People (8 controls) 3 controls touched (A.6.3 awareness, A.6.4 disciplinary, A.6.7 remote working) Sole-trader entity makes most A.6 controls trivial-by-structure; reviewed for accuracy of structural attestation
A.7 Physical (14 controls) 0 controls touched empirically All A.7 controls transferred-to-supplier (Hetzner ISO 27001 / 27017 / 27018); reviewed by reading the Hetzner certification scope
A.8 Technological (34 controls) ~28 controls touched Endpoint, network, application, cryptography, vulnerability management, change management — comprehensively tested

Summary coverage: approximately 53 of 93 controls (~57 %) were empirically tested. The remainder were either attested-by-structure (A.6 controls under sole-trader form), transferred-to-supplier (A.7 controls under Hetzner certifications), or governance-tier (A.5.1–A.5.4 attested rather than tested).


§6 Conclusions

The PortalPilot information security management system is operating effectively. All eleven HIGH findings from Sweep 1 + Sweep 2 are closed and re-verified. Nine open items, all Medium-or-Low, are tracked in the engineering backlog with documented rationale or remediation timelines. No CRITICAL findings were surfaced in either sweep.

The most material structural risks — single-server topology, single-founder concentration, no third-party SOC 2 attestation — are inherent to NordScope's current sole-trader stage and are explicitly acknowledged in the public ISMS scope statement (§3 out-of-scope) + the SOC 2 equivalence map (Compensating measures column).

The methodology itself has known limitations (no external pen test, no formal threat-modelling tool, LLM-assisted review with empirical-validation discipline). Phase 2 third-party attestation is deferred until enterprise-customer demand justifies the audit cost.


§7 Next audit due

Audit Cadence Due Owner
Q3 2026 internal audit Quarterly 2026-07-15 Founder
Q4 2026 internal audit Quarterly 2026-10-15 Founder
Q1 2027 internal audit (anniversary review) Quarterly + annual 2027-01-15 Founder
Annual scope-statement review Annual 2027-04-30 Founder

The Q3 2026 audit will explicitly cover:

  1. Verification that this report's nine open items are either closed or have a documented status update.
  2. Coverage of any Annex A control rows added or modified since the Q2 audit.
  3. Re-test of the agent-security model in light of any changes to Claude Code, Mistral, or the project's hook configuration.
  4. Sub-processor list reconciliation against the public DPA Annex I.

§8 Auditor declaration

I, Peter Sterkenburg, in my capacity as founder and sole operator of NordScope, performed the internal audit described in this report between 2026-03-20 and 2026-04-30. The audit was assisted by Anthropic Claude Code (an LLM-driven static-review tool); every LLM-flagged finding was empirically validated by the founder before being recorded as a real finding in the register, and every claimed closure was independently re-verified by the founder in Sweep 2.

This is an internal audit performed under ISO/IEC 27001:2022 clause 9.2. It is not a third-party attestation, certification, or examination by a CPA firm. Procurement reviewers should treat this report as alignment evidence, in the same family as the SOC 2 equivalence map and the public ISMS scope statement.

Peter Sterkenburg, 2026-04-30


Document history

Version Date Author Change
v1.0 2026-04-30 Peter Sterkenburg Initial publication; covers Sweep 1 (2026-03-20) + Sweep 2 (2026-03-20) re-framed into ISO clause 9.2 form

Linked from NordScope's internal security runbook (NDA counterpart) under the "Annual security tasks" section. The full per-finding evidence base is held in NordScope's audit archive and made available to enterprise procurement reviewers on request.