Wayfinder / Case study / Recovered specification

Source-derived document; review findings and open questions with the application owner.

Security

In this document

Security

Security boundary and actors

The system distinguishes external users, internal users, competent-authority users, administrators, notification owners, shared users, movement or shipment operators, and technical callers. External users may include exporters, importers, producers, carriers and other users granted access to a notification. Internal users may be associated with a competent authority and may have roles such as Internal, Administrator or ReadOnly. The evidence does not establish whether movement operators form a separate user population or how responsibilities are divided across these actors.

The application family includes ASP.NET MVC and Web API entry points, mediator-style requests and handlers, repositories, Entity Framework access, SQL and stored procedures, OWIN authentication, IdentityServer-related middleware, claims transformation, Autofac composition, and application filters. These components may belong to one deployment or to related applications; the complete runtime boundary and endpoint inventory are not established.

Authentication

The Web API is described as using OWIN bearer-token validation with IdentityServer middleware. Configuration refers to an authority derived from the configured site root and includes required scopes such as api1, api2 and api3 in different supplied contexts. It is unresolved whether scopes are alternatives or whether all listed scopes are required. The token issuer, accepted token formats, claim requirements, validation parameters, token lifetime, refresh behaviour and production authority endpoint are not established.

MVC authentication is associated with OWIN cookies, ASP.NET Identity, OAuth or OpenID Connect clients, access tokens, refresh tokens and claims transformation. Login is described as validating credentials, creating an identity, evaluating roles and redirecting users to role-appropriate areas. Cookie validation may inspect an ExpiresAt claim; absent or malformed expiry claims have different possible outcomes in the observed paths, and the complete identity pipeline is not supplied.

Claims may include user identifiers, subject identifiers, email addresses, access tokens, expiry values, organisation information, competent-authority information and role values such as Administrator, Internal and ReadOnly. Some identity helpers rebuild an identity from user-information and token claims, potentially discarding other original claims. The effect on roles, names, authentication type and authorization is unresolved. Missing subjects, invalid identifiers, null identities, network failures and unavailable OAuth services may result in rejected identities, exceptions or incomplete context, depending on omitted implementations.

Registration, email verification, password reset, email resend, account activation, deactivation and reactivation are represented by views, requests or handlers. The evidence does not establish password hashing and storage, reset-token expiry or association, email-delivery success, session invalidation, lockout semantics, or complete account-state transitions. Development configuration may automatically confirm some email addresses, but the effective environment controls and domain-matching rules are not established.

Authorization

Authorization intent is expressed through controller attributes, request-level authorization attributes, activity permissions, ownership filters, sharing checks, competent-authority checks, read-only filters, mediator decorators and repository authorization services. Examples include permissions for reading and editing export or import notifications, creating notifications, managing users, changing shipment counts, editing movements, managing shared users, overriding key dates, managing financial guarantees, accessing reports, deleting notifications or movements, and changing notification owners.

A role-based authorization component is described as granting access when configured roles intersect with role claims and denying unknown activities. Invalid role claims may be ignored during parsing. An authorization service reportedly permits requests when no cached authorization attribute is found. The completeness of the authorization-attribute cache, the default-deny intent, the mediator pipeline, registration and decorator order are not established.

The evidence supports the following intended or source-visible access distinctions:

  • Internal users may be checked against the notification’s competent authority.
  • External users may be checked against ownership or explicit sharing for export notifications.
  • Non-internal users are denied access to import notifications in the cited implementation.
  • Shared users may access selected notifications, subject to the sharing and ownership rules.
  • Some movement operations distinguish internal and external permissions.
  • Notification editing may be restricted by assessment status through a read-only filter or decorator.
  • Reports may be scoped to the current internal user’s competent authority.
  • Address-book operations may be scoped to the current user.
  • Certain user-administration operations require an approved or administrator-like user.

These controls are not demonstrated consistently across every controller, AJAX action, handler, repository, download, export, mutation, deletion or indirect identifier-based operation. A user-context dependency, foreign key, role field or permission attribute alone does not prove effective access control.

Ownership, sharing and identifier scope

Notification ownership transfer, shared-user addition and removal, external-user deactivation, notification deletion, movement deletion, facility removal and other mutations accept posted or request-supplied identifiers. Views commonly submit notification IDs, movement IDs, shipment numbers, user IDs, email addresses, statuses, dates, charges, selected codes and other hidden values.

The supplied evidence does not consistently show that handlers reload authoritative state, verify that a submitted entity belongs to the requested notification, check ownership or competent-authority membership, confirm that the operation remains permitted, or reconcile duplicate representations of the same identity. For example, shared-user forms may submit both user identifiers and email addresses, and several flows carry notification or entity identifiers through hidden fields or temporary state. These values are client-modifiable and should be treated as untrusted inputs at the receiving boundary; the corresponding server-side checks are not fully evidenced.

Some deletion and owner-change paths may dereference a missing lookup result or rely on stale TempData, ambient route values or posted state. These are conditional integrity and failure risks. The evidence does not establish an exploitable cross-notification access path.

Request protection and browser controls

Anti-forgery tokens are rendered in several MVC forms, including selected upload, deletion, date, facility, state, comment, sharing and financial-guarantee flows. This demonstrates token generation for those views, but does not establish that every state-changing endpoint validates the token. A token also does not establish authorization, ownership, replay protection or protection of client-controlled identifiers.

Some actions are marked [AllowAnonymous], including health-style, smoke-test or banner-like operations in the supplied material. One action appears anonymous despite an authorized controller, and a parameterless scanner health-style action is described as returning “ok”. These may be intentional public endpoints, but their deployment exposure, information sensitivity, rate limiting and compensating controls are unknown.

Client-side controls include hidden inputs, read-only fields, disabled controls, conditional panels, status-dependent links and JavaScript validation. These affect presentation and browser submission only. They do not establish server-side enforcement of read-only state, notification status, charges, shipment selection, upload requirements, permission, or eligibility.

Output encoding and client-side injection boundaries

Several views and helpers use Html.Raw, MvcHtmlString, direct InnerHtml assignment, manual HTML construction or jQuery .html() insertion. Observed values include shared-user email addresses, notification numbers, organisation and company names, authority and country values, facility names, titles, descriptions, error messages, resource text, identifiers and report or banner content.

These uses bypass normal Razor encoding or insert values as markup. They are potential HTML or script-injection boundaries if the values are user-controlled, externally sourced or insufficiently sanitized. The evidence does not establish the provenance, pre-encoding, sanitization, content-security policy or caller constraints for every value, so it does not establish a confirmed exploitable vulnerability.

Client-side code also interpolates values into JavaScript strings, builds autocomplete and waste-code markup by concatenation, parses hidden JSON, and inserts server responses into the page. Malformed or tampered values may cause parsing or script errors; unsafe values could affect the DOM. Network-error handling for several AJAX calls is absent from the inspected paths, but the final browser behaviour is unknown.

File, upload and document security

The system supports signed-document uploads, certificate files, bulk prenotification and receipt/recovery uploads, annexes, movement files, generated documents and downloads. Some upload models validate that a file exists and has content, and selected paths check a declared MIME type against an allow-list. A virus-scanning API and local or client-based scanner implementations are represented.

The scanner evidence includes Unknown, Clean, Virus and Error outcomes. One file-based implementation treats a remaining temporary file as clean and a missing file as virus, but the supplied material does not establish whether deletion means malware detection, scanner behaviour or another failure. Temporary-file cleanup, quarantine, file permissions, path isolation, filename sanitization, content inspection, maximum sizes, timeouts, scanner outages, certificate validation and retention are unresolved.

Download actions and file identifiers are visible in routes or links, but authorization, notification and movement ownership, storage protection, encryption, retention and post-deletion access are not established. Generated documents may be stored before later database or movement persistence succeeds, creating a possible file/database consistency risk. This is not confirmed to occur in production.

Database and data-access security

Repositories use Entity Framework, raw SQL, stored procedures and direct context access. Some SQL is parameterized, including selected archive, financial-guarantee and stored-procedure paths. Other inspected paths construct SQL-like filters using string interpolation or concatenate identifiers and search values. The complete query path, parameterization, escaping, allow-listing and execution context are not supplied; injection risk is therefore conditional except where unsafe interpolation is directly visible.

Authorization is visible in some notification-specific repositories but not in others, including selected transaction, audit, deletion, lookup, system-setting and import-mapping operations. Caller-side, service-layer, middleware or database-level controls may compensate. The evidence does not establish database users, grants, row-level security, ownership chaining, encryption, privileged-operation separation or protection of reporting and cache tables.

Foreign keys, row-version columns and audit tables provide structural or persistence features, but do not themselves establish authorization, confidentiality, tamper resistance, concurrency handling or complete audit coverage. Some configurations and migration evidence indicate broad schema-level permissions for an application role; the deployed permissions and object-level restrictions are not established.

Audit and accountability

The system represents audit records containing notification or movement identifiers, user identifiers, event types, screens, timestamps, original and new values, status changes and user-type information. Audit writes are visible for selected movement, assessment, guarantee, deletion, status and notification operations.

This does not establish that every sensitive mutation is audited, that audit writes are atomic with the business change, that records are immutable, or that access to audit data is restricted. Some paths save business data and audit data in separate operations. Domain events and post-save event dispatch are present in parts of the evidence, but event consumers, delivery guarantees, retry behaviour, replay protection, and failure handling are unknown.

Security failure paths

Observed or described failure paths include:

  • Authentication or authorization denial represented by security exceptions, HTTP 401 or HTTP 403 responses, redirects, or access-denied views.
  • Missing or invalid notification, movement, user, country, authority or facility records causing null, empty results, Single/SingleAsync exceptions or null dereferences.
  • Invalid or expired tokens causing rejected identities, sign-out, API errors or unhandled exceptions.
  • Anti-forgery failures being mapped to HTTP 400 and a cookie-error view in one filter.
  • Virus results or scanner failures producing dedicated error responses or views.
  • Broad exception handlers converting unrelated lookup or infrastructure failures into generic “invalid” or null results.
  • Detailed API errors using includeErrorDetail: true, potentially exposing exception information depending on deployment.
  • Missing configuration causing startup or runtime failures, including authority, scanner, database, logging, email or client-credential settings.
  • Malformed hidden JSON, posted identifiers, dates, numbers or temporary state causing parsing, binding or conversion exceptions.
  • Partial database, audit, file, email or event processing when operations are not covered by a common transaction.

The application’s external status mapping, logging, alerting, retry and recovery behaviour for these paths is not consistently evidenced. No conclusion should be drawn that a failure is safely handled merely because a corresponding error view, exception type or filter exists.

Evidence limitations

The supplied evidence contains contradictory coverage descriptions, differing framework and package accounts, incomplete or unreadable source and migration files, and tests or characterization scenarios whose execution results were not supplied. Some claims are based on views, request declarations or test setup rather than production invocation. Accordingly, the security position supported by the evidence is that multiple authentication, authorization, request-integrity, output-encoding, file-handling, audit and database-control mechanisms are present in selected areas, while their complete registration, coverage, effective enforcement and operational behaviour remain unresolved.

Content quality review

Advisory; not approval. Review status: advisory.

Overall assessment

The draft is broadly relevant to security.md and is appropriately cautious about source-level evidence, conditional risks, and unverified production behavior. It covers the major security domains expected for the purpose: authentication, authorization, ownership and identifier scope, CSRF, output encoding, uploads, SQL/data access, auditing, and failure handling.

However, it is not yet a sufficiently complete or well-prioritized security review. It is very expansive and repeats evidence limitations, while omitting or underemphasizing several material security findings present in the supplied evidence. It also sometimes groups distinct evidence contexts together without clearly identifying whether they concern the same application or deployment.

Relevance and structure

The subject matter is relevant, but the draft includes a large amount of general application and operational detail that could obscure the security conclusions. For example, extensive descriptions of notification, movement, document, and financial-guarantee workflows are useful only where they establish a security boundary, sensitive operation, identifier relationship, or failure consequence. Consider reducing repeated workflow inventories and retaining the security-relevant implications.

The draft should distinguish more explicitly between:

  • directly observed implementation;
  • test-derived behavior;
  • configuration declarations;
  • source-level concerns;
  • inferred risks; and
  • absence of supplied evidence.

It does this in many paragraphs, but not consistently. Statements such as “the system represents,” “reports may be scoped,” and “some paths check” should identify whether the basis is production code, test setup, configuration, or a secondary analysis.

The evidence contains many potentially separate applications or projects: MVC, Web API, scanning, maintenance, client, email, document-generation, and migration utilities. The draft acknowledges this, but it still presents them as one “system” in several places. A correction should make the scope explicit: the evidence supports a family of related components, not one confirmed deployed security boundary.

Material omissions

BinaryFormatter-backed TempData

The most significant omission is the custom TempData provider that serializes polymorphic objects with BinaryFormatter, compresses them, and protects them with MachineKey. The evidence specifically identifies this as a security concern. Machine-key protection does not make unsafe polymorphic deserialization safe. The draft should add a distinct subsection covering:

  • the serialization and deserialization mechanism;
  • whether attackers can influence the serialized object graph or cookie contents;
  • cookie size limits and failure behavior;
  • key consistency and rotation across nodes;
  • handling of malformed Base64, decompression, casting, and deserialization failures;
  • whether cookies are always cleared after failed loads; and
  • whether the provider returns null where MVC expects an empty dictionary.

This is more concrete than many of the conditional XSS observations currently given substantial space.

Configuration and deployment security

The draft mentions configuration gaps generally, but it omits or understates several specific findings:

  • plaintext API/client-credential secrets and database credentials in configuration;
  • development configuration with debug enabled and local endpoints;
  • uncertainty over whether the release transform is actually applied;
  • ELMAH configuration reportedly permitting remote or unauthenticated access;
  • TLS 1.1 being explicitly enabled without evidence that older protocols are disabled;
  • very large request limits and a 600-second timeout;
  • a Content Security Policy permitting unsafe-inline and broad HTTPS sources;
  • HSTS details not showing includeSubDomains or preload; and
  • potential logger duplication or inconsistent error logging configuration.

These should be presented as configuration findings with clear qualification: the evidence supports their presence in supplied configuration, but not that the values are active production secrets or effective deployed settings.

Mediator type-name dispatch

The draft discusses technical callers and middleware but does not prominently cover the API mediator path that accepts a client-supplied assembly-qualified type name, resolves it with Type.GetType, deserializes it, and sends it to the mediator without a demonstrated allow-list or complete interface validation. This is a distinct trust-boundary issue and should be described separately from ordinary authorization metadata. Its exploitability depends on exposed routes, permitted types, registrations, and deployment composition, which remain unresolved.

Spreadsheet/formula injection

The evidence notes that spreadsheet exports do not visibly neutralize formula-leading values. The draft discusses reports and downloads but does not identify this specific output-integrity risk. It should state that exported values beginning with formula characters may require neutralization, subject to the behavior of the spreadsheet library and upstream handling.

Logging and sensitive-data exposure

The draft mentions detailed API errors and audit access, but should also cover:

  • HTTP client logging of response bodies and reason phrases;
  • possible logging of exception messages, stack traces, identifiers, or sensitive payloads;
  • ELMAH exposure and access controls;
  • XML error serialization and redaction coverage;
  • whether scanner, document, banking, or identity data can enter logs; and
  • retention and operational access to those logs.

The supplied evidence supports these as review points, not confirmed disclosures.

The evidence describes analytics or tag-manager resources being loaded before affirmative consent may be established. This is primarily a privacy/compliance issue rather than a conventional application-security issue, but it is relevant if security.md includes confidentiality and privacy boundaries. It should either be added as a clearly labelled privacy-related evidence gap or explicitly excluded from the security scope.

Claims requiring correction or tighter qualification

The draft says that “selected paths check a declared MIME type against an allow-list.” This is technically too broad unless the relevant validator is identified. The evidence indicates that some validation relies only on the client-declared ContentType; it does not establish file-signature, extension, content, or malware validation. Revise to state that declared MIME-type filtering is visible in selected paths and is not proof of actual file type validation.

The statement that “a virus-scanning API and local or client-based scanner implementations are represented” should be qualified because the evidence describes multiple scanner implementations and configurations that may belong to separate components. It is safer to say that scanner abstractions and implementations are represented in the supplied material, while active registration and deployment use remain unknown.

The sentence that “reports may be scoped to the current internal user’s competent authority” is supported in several handler descriptions, but it should not be generalized to every report. One evidence set describes an EA-data report using a hard-coded England authority. Add that exception to avoid implying uniform current-user scoping.

The statement that “an authorization service reportedly permits requests when no cached authorization attribute is found” is important, but the draft should identify this as a specific permissive-default concern rather than presenting it only as a cache-completeness question. The evidence does not prove that the cache is incomplete or that an exposed request lacks metadata, so the current qualification should remain.

The statement that “non-internal users are denied access to import notifications in the cited implementation” is appropriately bounded, but “import notifications” should be tied to the cited path or handler. Other evidence describes import searches and repositories without visible equivalent checks. The draft should avoid allowing this one implementation to imply a system-wide rule.

The output-encoding section is generally careful, but it could distinguish server-side raw Razor output from client-side DOM insertion more sharply. Html.Raw, MvcHtmlString, InnerHtml, jQuery .html(), JavaScript string interpolation, and hidden JSON have different contexts and exploitability conditions. They should not be presented as one homogeneous sink class.

The database section says that “other inspected paths construct SQL-like filters using string interpolation or concatenate identifiers and search values.” This should distinguish actual SQL execution from helper-produced SQL-like expressions. The evidence explicitly leaves open whether later parameterization, allow-listing, or non-SQL use occurs. Only directly executed unsafe interpolation should be described as a stronger concern.

The draft states that “some configurations and migration evidence indicate broad schema-level permissions for an application role.” This is supported by the evidence, but should include the qualification that the deployed grants, object-level denies, row-level security, and ownership chaining were not supplied.

Missing behaviors and evidence gaps

The draft should add unresolved questions about:

  • whether the MVC application and Web API use the same identity provider and claim vocabulary;
  • whether api1, api2, and api3 are alternative or cumulative scopes;
  • whether token validation uses JWT validation, introspection, or both;
  • whether cookie expiry is enforced when ExpiresAt is absent;
  • whether claims transformation preserves role and authentication-type claims;
  • whether sign-out invalidates refresh tokens and existing sessions;
  • whether account deactivation invalidates current sessions;
  • whether password-reset and email-verification tokens have expiry, single-use, and account binding;
  • whether anonymous health and smoke-test routes are reachable externally;
  • whether Elmah and error endpoints are protected in production;
  • whether file downloads remain accessible after deletion or archive;
  • whether temporary files are isolated per request and securely deleted;
  • whether scanner “clean” means the file survived rather than that malware was positively excluded;
  • whether upload processing is bounded by application-level size, row, timeout, and concurrency limits;
  • whether audit records are protected from ordinary application-user modification; and
  • whether audit records are written atomically with the underlying mutation.

The draft mentions many of these in general terms, but the questions should be more directly connected to the concrete evidence.

Contradictions not fully surfaced

The draft correctly records the contradiction about receipt clearing during rejection and partial rejection. It should also explicitly call out these additional contradictions:

  • the 30-day versus 60-day shipment-date rule, which appears throughout the evidence and is security-relevant where date manipulation affects workflow eligibility;
  • differing external and internal receipt/completion checks;
  • different export and import movement procedure handling for conflicting outcome flags;
  • contradictory status descriptions, especially NotificationReceived transitioning concretely to AwaitingPayment while summaries describe the parent Submitted state;
  • differing permission metadata for operations that appear to mutate data;
  • the discrepancy between declared anti-forgery support and absent evidence of validation;
  • differing account or user deactivation semantics; and
  • differing framework/package descriptions that may affect middleware and security configuration.

These contradictions should be separated from ordinary evidence absence. A missing handler is an evidence gap; a source rule and test or message that disagree is a contradiction; a visible raw output sink is a source-level concern; and an unverified exploit path is not a confirmed defect.

Evidence quality and traceability

The evidence contains many source identifiers, but the draft does not cite them or otherwise provide traceability. Atelier owns identifiers and processing metadata, so the review need not invent citations. Nevertheless, the document would be stronger if each high-impact assertion were tied to the supplied evidence item or named artifact where that association is already available.

In particular, the following claims should not rely only on generalized wording:

  • plaintext secrets;
  • BinaryFormatter TempData;
  • anonymous scanner health endpoint;
  • includeErrorDetail: true;
  • broad database permissions;
  • mediator type-name dispatch;
  • SQL interpolation;
  • raw output of user-controlled or externally sourced values;
  • audit non-atomicity; and
  • file/database ordering.

The draft should also avoid implying that repeated summaries are independent corroboration. Much of the supplied material consists of overlapping second opinions and derived analyses.

  1. Add a dedicated subsection for cookie-backed TempData and BinaryFormatter, with its security implications and unresolved exploitability.
  2. Add a deployment/configuration subsection covering plaintext secrets, Elmah exposure, TLS settings, request limits, CSP, HSTS, and release-transform uncertainty.
  3. Add the dynamic mediator type-resolution path as a distinct API trust-boundary concern.
  4. Add spreadsheet formula injection as a conditional export risk.
  5. Separate declared MIME-type checking from actual file-content validation.
  6. State explicitly that report authority scoping is path-specific and that at least one report path uses a hard-coded authority.
  7. Tighten the SQL-injection wording to distinguish executed SQL from SQL-like helper strings.
  8. Reduce repeated generic evidence-limit paragraphs and replace some with prioritized unresolved questions.
  9. Distinguish source defects, contradictions, conditional risks, and absent evidence more visibly.
  10. Identify which claims concern the MVC application, the Web API, the scanning component, or other potentially separate deployments.

Conclusion

The draft is directionally sound and substantially relevant, but it should not be treated as complete. Its principal weakness is not reckless overclaiming; it is uneven prioritization. It gives considerable space to broad conditional concerns while omitting several concrete security-relevant findings, especially unsafe TempData deserialization, configuration exposure, dynamic type dispatch, and export/logging risks. These omissions should be corrected before the section is relied upon as a security assessment.