Source-derived document; review findings and open questions with the application owner.
09 — Security and Trust Boundaries
In this document
Purpose and security context
The application supports users and administrators who manage notifications, movements, assessments, sharing, and related records. Security controls therefore protect several kinds of information and action: authenticated identity, notification ownership, internal-user administration, movement updates, assessment decisions, and access to user or organisation data. The supplied evidence shows security declarations at multiple layers, but it does not establish a single complete, end-to-end permission model. In particular, request attributes, controller attributes, middleware, decorators, and downstream handlers are visible in different source ranges and their combined runtime effect is not fully demonstrated. E0011E0001E0257
A useful current-system boundary is the following:
Provenance gap: This passage has no artifact/source citation.
Preparing diagram…
View Mermaid diagram source
flowchart LR
U[Browser or external caller] --> W[Web/API controllers]
W --> A[Authentication and claims]
A --> D[Authorization attributes, filters, decorators]
D --> M[Mediator requests and handlers]
M --> P[Repositories, domain objects, persistence]
D -. unresolved enforcement path .-> H[Handlers or downstream services]
The diagram records observed relationships between controllers, authentication, authorization declarations, mediator requests, and handlers. The dashed edge indicates that the evidence does not show exactly where all authorization checks are enforced.
Provenance gap: This passage has no artifact/source citation.
Actors and trust boundaries
Application users and administrators are evidenced as distinct concepts rather than as a complete actor taxonomy. The source includes external-user status, internal-user status and role, approvals, ownership transfer, sharing, and authorization checks. Internal-user administration includes requests to set external status, set approvals, update internal role, and update internal status. These request definitions carry user identifiers or status/role values, but the request-contract evidence does not prove that the requested changes are persisted or that every caller is authorized. E0001E0114
Application request handlers execute operations such as movement receipt and rejection, consent, and financial-guarantee decisions. The handlers visibly load records, invoke domain methods, save through a context or repository, and return results in several cases. The human or external caller behind a handler is not established by the supplied source. E0010E0317E0460
The principal technical trust boundary is between an incoming request and the server-side identity and resource selected for mutation. Several controllers accept identifiers from posted models, including notification IDs, notification numbers, user IDs, and target notification numbers. The visible controller code does not always demonstrate that those values are reconciled with the authenticated subject, the record originally displayed, or the current record state. Downstream authorization or handler checks may provide that protection, but the relevant implementations are not consistently included. E0105E0358E0460
Authentication and identity
The API startup code composes an OWIN ASP.NET Web API application with IdentityServer middleware, bearer-token validation, claims transformation, and Web API dispatch. Bearer validation is configured with an authority derived from application configuration and the scopes api1 and api3. This establishes intended bearer authentication and configured scope values; it does not establish whether both scopes are required, either is sufficient, or how the validation library interprets them. E0011
The API’s UserContext selects a user identifier from the first identity it processes. If that identity is bearer-authenticated, it reads the sub claim; otherwise it reads NameIdentifier and returns immediately. Consequently, a principal containing multiple identities may be resolved from the first non-bearer identity without considering a later bearer identity. The code also calls .Equals on AuthenticationType without visible null protection. The impact depends on the identity ordering and composition produced in deployment, which are not shown. E0358
Claims transformation retrieves the user identified by the incoming sub claim and passes the result to identity creation without a visible null check. An unknown or stale subject may therefore cause an exception rather than a controlled authentication failure, although the exact runtime result depends on the Identity implementation and pipeline. E0358
The MVC login flow obtains an OAuth access token, creates an identity, signs the user in, examines role claims, and redirects through a local-URL check. Users with internal or readonly role claims are directed to the administrative home area, while other users are directed to the applicant home area. This demonstrates a redirect safeguard and role-sensitive navigation, not a complete role-based authorization policy; the evidence does not establish that internal and readonly have different effective permissions. E0368
Authorization enforcement
Authorization is declared in several forms. Request contracts use attributes such as CanManageExternalUsers, CanApproveNewInternalUser, CanManageExistingInternalUser, CanReadExportNotification, CanEditExportNotification, and CanAuthorizeActivity. Movement mutation requests also carry notification read-only authorization metadata. These declarations establish intended permissions on request types, but the request-definition evidence does not show how the attributes are interpreted or enforced. E0001E0145
The request-handler module registers an event-dispatch decorator, a request-authorization decorator, and a notification-read-only authorization decorator in a documented nesting order. This supports the existence of an authorization pipeline around handlers. The supplied code does not show the decorator implementations, so it cannot establish whether checks are fail-closed, which identity is used, or how authorization failures are returned. E0257
A separate authorization manager maps permission names to allowed UserRole values. It reads role claims, parses them case-insensitively, and grants access when configured roles intersect with the user’s roles. Unknown activities remain denied in the visible implementation. This is direct evidence of a role-based decision component, but not evidence that every controller or request passes through it. E0114
There are important controller-level exceptions and apparent fail-open paths. Most notification-editing controllers visibly combine [Authorize] with [NotificationReadOnlyFilter], but WasteGenerationProcessController.Index(Guid id) is marked [AllowAnonymous] despite controller-level authorization. The effect is unresolved because the filter implementation is not supplied. Separately, AuthorizationService is reported to return true when no request authorization attribute is found, and an action-name allowlist bypass is reportedly not scoped by controller or area. These may be intentional public routes or configuration defects; they require verification before their production impact can be classified. E0017E0105
RegisterAdmin is class-level [Authorize] but is not visibly restricted to an administrator role before creating an internal-role user. UpdateApplicantDetails selects the target account from a posted model ID without a visible comparison to the current user and is not visibly administrator-only. These are source-level authorization gaps in the methods shown, not proven vulnerabilities, because global policies or downstream controls may exist outside the excerpt. E0358
Resource identity and posted-state risks
Deletion of an export notification illustrates the boundary between client-provided identity and server-side authority. The controller looks up notification details from a posted notification number, then posts a notification ID to the delete request. The visible code does not prove that the posted ID equals the looked-up notification, belongs to the current operator, or remains deletable at POST time. The handler or AuthorizeActivity implementation may enforce these conditions, but that evidence is not included. E0105
The same controller has a visible null-handling risk: if the notification lookup returns null, the not-deletable branch is skipped and notificationDetails.NotificationId is subsequently accessed. An unknown number may therefore produce a null-reference failure rather than a controlled not-found response. E0105
Producer removal similarly uses posted state. The GET action checks whether a producer is the only site of export, while the POST relies on model.IsOnlySiteOfExport; the supplied evidence does not show that the POST recomputes this condition server-side. This creates a verification point where client-provided state could influence a security-relevant business decision. E0017
Sharing also relies on TempData["SharedUsers"], directly cast to a list in the share and confirmation flows. Missing or expired TempData may cause null-dependent behavior, including use of model.SharedUsers.Select(...). This is an availability and workflow-integrity concern; the evidence does not establish whether TempData is guaranteed or whether the downstream request rechecks ownership and user eligibility. E0017
Configuration and operational boundaries
The API configuration reportedly contains plaintext API secrets and a database connection string containing a database user identifier. This is evidence of sensitive values being present in the configuration source, not proof that the values are active credentials, exposed externally, or committed in production. Their deployment source, rotation process, and secret-management controls are open. E0011
Visible audit coverage is selective. Assessment and financial-guarantee status changes record source status, destination status, user ID, and, for financial guarantees, UTC time. Other controller and handler operations are not shown to have equivalent audit records. The evidence cannot establish system-wide audit completeness. E0010E0008
Current behavioural requirements
The following identifiers describe behaviours that the current implementation either visibly provides or must preserve when verified. They are not a target redesign.
Provenance gap: This passage has no artifact/source citation.
-
SEC-REQ-001 — Authenticate protected API calls.
Requests entering the API must be processed through the configured bearer-token validation path and configured authority/scope checks. The evidence establishes configuration, but the exact scope rule remains unresolved. E0011 -
SEC-REQ-002 — Apply declared request permissions.
Requests carrying authorization metadata must be subject to the configured request-authorization mechanism before their protected operation is executed. The decorator registration and permission declarations are observed; enforcement semantics require confirmation. E0001E0257 -
SEC-REQ-003 — Bind mutations to an authorized resource.
A posted notification, movement, producer, or user identifier must be checked against the authenticated subject, permitted competent authority, ownership rules, and current resource state before mutation. The supplied controllers do not establish that every path performs all of these checks. E0105E0162 -
SEC-REQ-004 — Fail safely for unresolved identity and resource lookups.
Unknown users, notification numbers, or expired workflow state must produce controlled authorization, validation, or not-found outcomes rather than unhandled null dereferences. Current evidence identifies contrary risks that require correction or explicit downstream guarantees. E0358E0105E0017
Characterisation scenarios — candidates for verification
SEC-SCN-001 — Anonymous access exception
Provenance gap: This passage has no artifact/source citation.
- Given an unauthenticated caller requests
WasteGenerationProcessController.Index(Guid id), - When the request passes through the controller and
NotificationReadOnlyFilter, - Then record whether the action is allowed, denied, or redirected, and identify which component makes that decision.
Provenance gap: This passage has no artifact/source citation.
SEC-SCN-002 — Cross-user profile update
Provenance gap: This passage has no artifact/source citation.
- Given an authenticated non-administrator user and another user’s identifier,
- When
UpdateApplicantDetailsreceives the other user’s identifier, - Then the update is rejected unless an explicit authorization rule permits it.
Provenance gap: This passage has no artifact/source citation.
SEC-SCN-003 — Unknown notification deletion
Provenance gap: This passage has no artifact/source citation.
- Given a notification number that cannot be resolved,
- When
DeleteExportNotificationControllerprocesses the request, - Then it returns a controlled not-found or validation response and does not dereference a null notification result.
Provenance gap: This passage has no artifact/source citation.
SEC-SCN-004 — Unannotated request
Provenance gap: This passage has no artifact/source citation.
- Given a request type with no cached authorization attribute,
- When the authorization service evaluates it,
- Then confirm whether the current allow-by-default result is intentional and whether the request is publicly reachable.
Provenance gap: This passage has no artifact/source citation.
Open question for Harten: Inspect NotificationReadOnlyFilter, AuthorizeActivity, the mediator authorization decorators, RequestAuthorizationAttributeCache, relevant handler implementations, route registration, and deployment identity configuration. These artifacts would establish the effective authorization order, scope semantics, global policies, ownership checks, and whether the source-level risks above are reachable runtime behaviours.
Provenance gap: This passage has no artifact/source citation.
Contains public sector information licensed under the Open Government Licence v3.0. Original public repository. This independent Harten analysis was not commissioned, approved or endorsed by DEFRA or the Environment Agency.
Analysed source-archive hash is recorded; its exact upstream Git commit has not been established. The generated material does not establish complete requirements, operational security or functional equivalence.