Security verdict¶
20 checked, 4 not met, 21 declared, 0 not checked — 45 controls in the baseline.
Each control below is defined on
the security baseline, which also says what
each of the four states means. declared is not a pass.
| Control | What it checks | State, scope and what is left |
|---|---|---|
KYV-1 |
A secret an untrusted caller presents is compared in constant time and refused when it is unset — and where this extension mints it rather than taking core's or a merchant's, it carries at least 128 bits from a cryptographic random source. | declared — 1 bearer-secret surface over 3 mint, compare and refuse sites (2 × mint, 1 × constant-time compare, 0 × compare, 0 × refusal); 2 further entries say what the derivation reached that is not a secret: the HTTP Basic key on the two api/ routes — core's own oc_api credential, read at system/library/api_gateway.php:850-881 from HTTP_AUTHORIZATION, REDIRECT_HTTP_AUTHORIZATION, PHP_AUTH_USER/PHP_AUTH_PW and apache_request_headers() in that order, and compared at api_gateway.php:948 with hash_equals against a dummy of equal length where the username is unknown. Compared in constant time at system/library/api_gateway.php:948. No refusal of an unset value sits in this extension's own code. Minted by core, so no entropy is asserted here: nothing in this baseline rests on core's own token helper. |
1.2.1 |
Store data meets markup safely where the danger is decidable — an unquoted attribute, a URL the template composed itself, a style, hand-built XML — and every store-derived subtree a template of this extension renders is written down beside the code. Beyond those two, nothing is claimed, and the page says so. |
declared — machine-pass on the sinks: 2 sink sites asserted here, 2 not admitted; attested over the inventory: 85 store-derived subtrees over 18 templates; unverified beyond it: everything else:extensions/delivery_date/src/admin/view/template/sale/planner.twig:109 — style="width: {{ cell.width }}%;" puts a value in a CSS context, which nothing in Twig escapes forextensions/delivery_date/src/admin/view/template/sale/planner.twig:179 — style="width: {{ section.occupancy.width }}%;" puts a value in a CSS context, which nothing in Twig escapes formodule_delivery_date_status — setting. Rendered by admin/view/template/module/delivery_date.twig.module_delivery_date_lead_basis — setting. Rendered by admin/view/template/module/delivery_date.twig.module_delivery_date_released_statuses — setting. Rendered by admin/view/template/module/delivery_date.twig.module_delivery_date_review_status_id — setting. Rendered by admin/view/template/module/delivery_date.twig.module_delivery_date_hold_minutes — setting. Rendered by admin/view/template/module/delivery_date.twig.version_warning — the store's OpenCart release, through Compatibility. Rendered by admin/view/template/module/delivery_date.twig, admin/view/template/module/delivery_date_calendar.twig, admin/view/template/module/delivery_date_calendars.twig.order_statuses — database — core's oc_order_status in the admin's language. Rendered by admin/view/template/module/delivery_date.twig.copy_panel — rendered partial over the merchant's own storefront wording, per language. Rendered by admin/view/template/module/delivery_date.twig.copy — the merchant's stored wording overrides beside this extension's shipped defaults. Rendered by admin/view/template/module/copy_panel.twig.language_readout — rendered partial over oc_language. Rendered by admin/view/template/module/delivery_date.twig.resolution — rendered from oc_language, through LanguageReadout. Rendered by admin/view/template/module/language_readout.twig.languages — database — core's oc_language, unfiltered. Rendered by admin/view/template/module/copy_panel.twig, admin/view/template/module/delivery_date_week.twig.config_language_id — setting — the store's default language. Rendered by admin/view/template/module/delivery_date_week.twig.timezone_link — a link to core's own setting screen, carrying the admin session token. Rendered by admin/view/template/module/delivery_date.twig, admin/view/template/module/delivery_date_calendar.twig.text_timezone — the store's configured timezone, into a language string. Rendered by admin/view/template/module/delivery_date.twig, admin/view/template/module/delivery_date_calendar.twig.calendars — database — delivery_date_calendar rows for this store, the baseline first. Rendered by admin/view/template/module/delivery_date.twig, admin/view/template/module/delivery_date_calendars.twig.calendar_id — database — the calendar the screen is editing. Rendered by admin/view/template/module/delivery_date_calendar.twig.name — database — the calendar's own name, the slot names, and on the storefront the chosen window's label. Rendered by admin/view/template/module/delivery_date_calendar.twig, admin/view/template/module/delivery_date_week.twig, catalog/view/template/checkout/delivery_date.twig.status — database — the calendar's own status, and an order's status on the planner. Rendered by admin/view/template/module/delivery_date_calendar.twig, admin/view/template/sale/planner_orders.twig.inherit_days — database — whether this method calendar takes the store's week. Rendered by admin/view/template/module/delivery_date_calendar.twig.lead_days — database — the calendar's own lead time, and a product's own override on the product tab. Rendered by admin/view/template/module/delivery_date.twig, admin/view/template/module/delivery_date_calendar.twig, admin/view/template/module/delivery_date_product.twig.cutoff — database — the calendar's own cutoff time. Rendered by admin/view/template/module/delivery_date.twig, admin/view/template/module/delivery_date_calendar.twig.horizon_days — database — how far ahead the calendar offers. Rendered by admin/view/template/module/delivery_date.twig, admin/view/template/module/delivery_date_calendar.twig.slots — database — delivery_date_slot rows with their per-language names, or the posted week where the form is unsaved. Rendered by admin/view/template/module/delivery_date_week.twig, admin/view/template/module/delivery_date_calendars.twig, admin/view/template/module/delivery_date_preview.twig, catalog/view/template/checkout/delivery_date.twig, admin/view/template/sale/order_reassign.twig.offers — database — which slots each weekday offers, and at what cap. Rendered by admin/view/template/module/delivery_date_week.twig.limits — database — the per-day ceiling for each weekday. Rendered by admin/view/template/module/delivery_date_week.twig.closures — database — the date ranges the calendar is closed for. Rendered by admin/view/template/module/delivery_date_week.twig.weekdays — the seven weekdays named in the admin's own language. Rendered by admin/view/template/module/delivery_date_week.twig.week_readonly — database — whether this method calendar inherits its week and so cannot be edited here. Rendered by admin/view/template/module/delivery_date_week.twig.methods — the store's enabled shipping extensions, each with the calendar assigned to it. Rendered by admin/view/template/module/delivery_date_calendar.twig, admin/view/template/module/delivery_date_calendars.twig, admin/view/template/sale/planner.twig.method — database — the shipping method a calendar or an order carries. Rendered by admin/view/template/module/delivery_date_calendar.twig, admin/view/template/module/delivery_date_calendars.twig, admin/view/template/sale/planner.twig, admin/view/template/sale/planner_print.twig.reference — database — the shipping-method codes a calendar answers for, and the planner's own filter off the request. Rendered by admin/view/template/module/delivery_date_calendar.twig, admin/view/template/sale/planner.twig.free — the shipping methods no calendar has claimed yet. Rendered by admin/view/template/module/delivery_date_calendar.twig.warnings — database — what the calendars, their slots and the store's methods contradict about each other. Rendered by admin/view/template/module/delivery_date_calendars.twig.global — a summary of the baseline calendar's week, slots and capacity as sentences. Rendered by admin/view/template/module/delivery_date_calendars.twig.days — database — the days the preview or the storefront rail resolved, each with its slots. Rendered by admin/view/template/module/delivery_date_preview.twig, admin/view/template/module/delivery_date_calendars.twig, catalog/view/template/checkout/delivery_date.twig.explanation — why each previewed day resolved as it did, as language strings carrying the calendar's own numbers. Rendered by admin/view/template/module/delivery_date_preview.twig.preview — a link to this extension's own preview route, carrying the admin session token. Rendered by admin/view/template/module/delivery_date_week.twig.preview_html — rendered partial over the previewed days. Rendered by admin/view/template/module/delivery_date_previewbox.twig.preview_now — request — post[preview_now], the moment the merchant moved the clock to. Rendered by admin/view/template/module/delivery_date_previewbox.twig.previewbox — rendered partial holding the preview pane. Rendered by admin/view/template/module/delivery_date.twig, admin/view/template/module/delivery_date_calendar.twig.week — rendered partial holding the week grid. Rendered by admin/view/template/module/delivery_date.twig, admin/view/template/module/delivery_date_calendar.twig.user_token — the admin session token, rendered into the planner's own JavaScript URLs. Rendered by admin/view/template/sale/planner.twig.date — request — get[date] on the planner, narrowed to a real Y-m-d, and the day of a previewed or offered window. Rendered by admin/view/template/sale/planner.twig, admin/view/template/module/delivery_date_preview.twig, catalog/view/template/checkout/delivery_date.twig.orders — database — core's oc_order joined to this extension's booking rows, with customer names and shipping addresses. Rendered by admin/view/template/sale/planner.twig, admin/view/template/sale/planner_orders.twig, admin/view/template/sale/planner_print.twig, admin/view/template/sale/planner_unscheduled.twig.order_id — database — the order a planner row or an order-page block is about. Rendered by admin/view/template/sale/planner.twig, admin/view/template/sale/planner_orders.twig, admin/view/template/sale/planner_print.twig, admin/view/template/sale/order_reassign.twig.sections — database — the day's windows, each with the orders booked into it. Rendered by admin/view/template/sale/planner.twig, admin/view/template/sale/planner_print.twig.matrix — database — the week grid of window against day, with counts and caps. Rendered by admin/view/template/sale/planner.twig.columns — the days the planner grid is showing. Rendered by admin/view/template/sale/planner.twig.selected_index — which of those columns the requested date falls on. Rendered by admin/view/template/sale/planner.twig.named — database — the window names the grid's rows are labelled with. Rendered by admin/view/template/sale/planner.twig.total — a count of the day's orders, into a language string. Rendered by admin/view/template/sale/planner.twig, admin/view/template/sale/planner_print.twig.today — the store's own clock, in the store's timezone. Rendered by admin/view/template/sale/planner.twig.previous — a planner link for the day before, carrying the admin session token and the current filter. Rendered by admin/view/template/sale/planner.twig.next — a planner link for the day after, carrying the admin session token and the current filter. Rendered by admin/view/template/sale/planner.twig.reset — a planner link back to today, carrying the admin session token. Rendered by admin/view/template/sale/planner.twig.print — a planner link to the print sheet, carrying the admin session token and the current filter. Rendered by admin/view/template/sale/planner.twig.export — a planner link to the CSV, carrying the admin session token and the current filter. Rendered by admin/view/template/sale/planner.twig.picking — core's own sale/order.shipping link, empty where this admin has no access to it. Rendered by admin/view/template/sale/planner.twig.picking_orders — database — the order ids the picking form posts. Rendered by admin/view/template/sale/planner.twig.closed — whether the calendar closes the day the planner is showing. Rendered by admin/view/template/sale/planner.twig.empty — whether the day is open but has no orders on it. Rendered by admin/view/template/sale/planner.twig, admin/view/template/sale/planner_print.twig.unscheduled — database — orders with no window booked, and on the checkout the sentence for a shopper who has chosen none. Rendered by admin/view/template/sale/planner.twig, admin/view/template/sale/order_delivery.twig, catalog/view/template/checkout/delivery_date.twig.unscheduled_link — a planner link to that list, carrying the admin session token. Rendered by admin/view/template/sale/planner.twig.table — rendered partial over the order rows. Rendered by admin/view/template/sale/planner.twig, admin/view/template/sale/planner_unscheduled.twig.title — the day and the filter the print sheet is for, into a language string. Rendered by admin/view/template/sale/planner_print.twig.base — the store's own admin URL, so the print sheet can reach its stylesheet. Rendered by admin/view/template/sale/planner_print.twig.bootstrap_css — the path core serves Bootstrap from. Rendered by admin/view/template/sale/planner_print.twig.stylesheet — the path core serves the admin stylesheet from. Rendered by admin/view/template/sale/planner_print.twig.lang — setting — the admin language's own code, into the sheet's . Rendered by admin/view/template/sale/planner_print.twig.direction — setting — the admin language's own text direction. Rendered by admin/view/template/sale/planner_print.twig.day — database — the day an order is booked for, and a previewed or offered day. Rendered by admin/view/template/sale/order_delivery.twig, admin/view/template/module/delivery_date_preview.twig, catalog/view/template/checkout/delivery_date.twig.window — database — the window an order is booked into. Rendered by admin/view/template/sale/order_delivery.twig.was — database — the window the order was booked into before it was moved. Rendered by admin/view/template/sale/order_delivery.twig.reassign — a link to this extension's own planner.form route, carrying the admin session token and the order id; empty where the booking is not firm or the user group lacks modify on the planner. Rendered by admin/view/template/sale/order_delivery.twig.reassign_date — database — the day the order is booked for, or today on the store's own clock where it has none. Rendered by admin/view/template/sale/order_reassign.twig.availability — a link to this extension's own availability route, in the storefront's language. Rendered by catalog/view/template/checkout/delivery_date.twig.save — a link to this extension's own save route; on the admin screens, to its own save routes with the session token. Rendered by catalog/view/template/checkout/delivery_date.twig, admin/view/template/module/delivery_date.twig, admin/view/template/module/delivery_date_calendar.twig.visible — how many of the offered days the rail shows before the More button. Rendered by catalog/view/template/checkout/delivery_date.twig.more — whether there are further days behind that button. Rendered by catalog/view/template/checkout/delivery_date.twig.marker — the day the rail opens on. Rendered by catalog/view/template/checkout/delivery_date.twig.chosen — the window this session has taken, out of the session. Rendered by catalog/view/template/checkout/delivery_date.twig.reason — why no day could be offered, as a language string carrying the calendar's own numbers. Rendered by catalog/view/template/checkout/delivery_date.twig, admin/view/template/module/delivery_date_preview.twig.danger — whether the notice is a refusal rather than a restatement. Rendered by catalog/view/template/checkout/delivery_date.twig, catalog/view/template/checkout/delivery_date_notice.twig.api_panel — settings and database — whether the API is on, and core's own oc_api rows. Rendered by admin/view/template/module/api_panel.twig, admin/view/template/module/delivery_date.twig.Unverified beyond it: the other 590 of 637 template expressions in 22 templates, and any $data subtree nobody enumerated. The inventory is an inventory and not a bound: completeness over the whole expression surface is unverifiable, so this residual is permanent, and it is published rather than left to be inferred from what is missing. |
1.2.2 |
A URL a template builds for itself, rather than taking one whole from the link helper, has every value in it URL-encoded — so nothing a store holds can add a parameter of its own or change where the link goes. | not met — 45 url attributes carrying a template expression, of 47 sink sites asserted:extensions/delivery_date/src/admin/view/template/module/delivery_date_week.twig:31 — src="{{ language.extension ? 'extension/' ~ language.extension ~ '/admin/language/' : 'language/' }}{{ language.code }}/{{ language.code }}.png" composes a URL in the template rather than taking one whole from the link helper, and not every value in it is URL-encoded |
1.2.3 |
No template expression is interpolated into a <script> element, so store data cannot end a string literal and start running. |
not met — 22 .twig files:extensions/delivery_date/src/admin/view/template/customer/personal_data.twig:154 — {{ erase }} is interpolated inside a <script> elementextensions/delivery_date/src/admin/view/template/customer/purge.twig:71 — {{ remove }} is interpolated inside a <script> elementextensions/delivery_date/src/admin/view/template/module/delivery_date_week.twig:128 — {{ form_id }} is interpolated inside a <script> elementextensions/delivery_date/src/admin/view/template/module/delivery_date_week.twig:136 — {{ preview }} is interpolated inside a <script> elementextensions/delivery_date/src/catalog/view/template/checkout/delivery_date.twig:63 — {{ save }} is interpolated inside a <script> elementextensions/delivery_date/src/catalog/view/template/checkout/delivery_date.twig:92 — {{ visible }} is interpolated inside a <script> elementextensions/delivery_date/src/catalog/view/template/checkout/delivery_date.twig:116 — {{ availability }} is interpolated inside a <script> element |
1.2.4 |
Every way this extension builds a database statement is written down beside the code, so how a value reaches a query is a published answer rather than something to go looking for. | declared — 3 ways of building a statement, over 96 statements run and 40 values escaped:escaped literal: every value this extension puts in a statement — Through $this->db->escape(), or an (int) cast where the value is numeric. The API's reads in catalog/model/api/delivery_date.php are built the same way: ids and the store filter cast to (int), the date filters cut and escaped, the order a literal.interpolated identifier: the table name in the installer's SHOW TABLES / SHOW COLUMNS / SHOW INDEX probes, and in Schema's CREATE TABLE statements — DB_PREFIX concatenated with a table name out of Schema's own constant list, at admin/model/module/delivery_date.php:901-942. Nothing from the request reaches it.whole-clause concatenation: the planner's order listing — The planner model assembles its WHERE out of parts it writes itself, each value escaped or cast as it goes in; the ORDER BY is a literal. No clause is taken from a caller.15 of the 96 statements are handed over already built, so what a rule reading the call site alone can see stops there; which mechanism built them is what the lines above say. |
1.2.5 |
Nothing runs a command through the shell — no backtick, no exec() — so no value a store holds can become part of one. |
checked — 76 .php files |
1.3.1 |
No screen binds a rich-text editor whose HTML this extension would then render back out, because nothing here sanitises HTML and no sanitiser ships with it. | checked — 22 .twig files |
1.3.2 |
Nothing runs code it assembled while running — no eval(), and no include of a path a variable decided. |
not met — 76 .php files:extensions/delivery_date/src/system/library/copy.php:392 — require runs a PHP file whose path is decided while running, which is code execution the source does not name |
1.5.1 |
Every XML parser is left at the restrictive default: nothing turns on external entity resolution, which is what would turn reading a spreadsheet into reading your server's files. | checked — 76 .php files |
3.2.1 |
Every route declares the response type it sets, as the code sets it, so nothing is left for a browser to re-interpret as something it is not. | declared — 15 of 28 routes set a Content-Type of their own: 6 × application/json 1 × application/json, with no charset (customer/personal_data.php:230) 1 × application/json, with no charset (customer/personal_data.php:272), sent as an attachment named for the person and the day (customer/personal_data.php:299) 1 × application/json, with no charset (customer/personal_data.php:359) 1 × application/json, with no charset (customer/purge.php:168) 1 × application/json, with no charset (sale/planner.php:500) 1 × application/json, with no charset (sale/planner.php:575) 2 × application/json; charset=utf-8, with X-Content-Type-Options: nosniff and Access-Control-Allow-Origin: null 1 × none set, and no output written 2 × none — it returns markup to core's checkout rather than writing a response 9 × none — nothing sets a Content-Type, so the store's default stands 1 × none — nothing sets a Content-Type, so the store's default stands, and the sheet is a whole HTML document 1 × text/csv; charset=utf-8 — beside a Content-Disposition naming delivery- |
3.2.2 |
Every place a script hands a value to the page as markup rather than as text is written down beside the code, with what it puts there. | declared — 17 call sites in 6 templates, each declared with what it writes there: 3 × .append(3 × .html(5 × .prepend(3 × .replaceWith(3 × innerHTML |
3.3.1 |
A cookie this extension sets carries the Secure attribute at the call that sets it, so a browser cannot send it back over plain HTTP. |
checked — 76 .php files |
3.4.2 |
A cross-origin header is a fixed value this code chose — never a wildcard, and never the origin the caller asked for. | checked — 76 .php files |
3.5.1 |
Every route that changes something says what stands between it and a request another website caused a visitor's browser to make. | declared — 7 routes of 28 reaches a model write; the 7 admin ones among them stand behind the user_token core checks before dispatch, and 21 admin routes are gated that way in all:No storefront route of this extension reaches a model write. |
3.5.2 |
No route grants a cross-origin caller anything, so nothing here is left depending on a browser's preflight to refuse one. | checked — 76 .php files |
3.5.3 |
A route that writes refuses a request that is not a POST, so a link somebody follows cannot make the change on their behalf. |
not met — 76 .php files:extensions/delivery_date/src/admin/controller/customer/personal_data.php:321 — PersonalData::grant() writes through a model and never reads REQUEST_METHOD, so a GET anybody can cause does the same thing a POST doesextensions/delivery_date/src/admin/controller/customer/purge.php:147 — Purge::remove() writes through a model and never reads REQUEST_METHOD, so a GET anybody can cause does the same thing a POST doesextensions/delivery_date/src/admin/controller/module/delivery_date.php:581 — DeliveryDate::save() writes through a model and never reads REQUEST_METHOD, so a GET anybody can cause does the same thing a POST doesextensions/delivery_date/src/admin/controller/module/delivery_date.php:1622 — DeliveryDate::calendarSave() writes through a model and never reads REQUEST_METHOD, so a GET anybody can cause does the same thing a POST doesextensions/delivery_date/src/admin/controller/module/delivery_date.php:1752 — DeliveryDate::calendarDelete() writes through a model and never reads REQUEST_METHOD, so a GET anybody can cause does the same thing a POST doesextensions/delivery_date/src/admin/controller/module/delivery_date.php:2179 — DeliveryDate::install() writes through a model and never reads REQUEST_METHOD, so a GET anybody can cause does the same thing a POST doesextensions/delivery_date/src/admin/controller/module/delivery_date.php:2383 — DeliveryDate::uninstall() writes through a model and never reads REQUEST_METHOD, so a GET anybody can cause does the same thing a POST does |
4.1.1 |
A response carrying a body says what that body is, and the route table records the Content-Type each route sets rather than the one it ought to. |
declared — 15 of 28 routes set a Content-Type of their own: 6 × application/json 1 × application/json, with no charset (customer/personal_data.php:230) 1 × application/json, with no charset (customer/personal_data.php:272), sent as an attachment named for the person and the day (customer/personal_data.php:299) 1 × application/json, with no charset (customer/personal_data.php:359) 1 × application/json, with no charset (customer/purge.php:168) 1 × application/json, with no charset (sale/planner.php:500) 1 × application/json, with no charset (sale/planner.php:575) 2 × application/json; charset=utf-8, with X-Content-Type-Options: nosniff and Access-Control-Allow-Origin: null 1 × none set, and no output written 2 × none — it returns markup to core's checkout rather than writing a response 9 × none — nothing sets a Content-Type, so the store's default stands 1 × none — nothing sets a Content-Type, so the store's default stands, and the sheet is a whole HTML document 1 × text/csv; charset=utf-8 — beside a Content-Disposition naming delivery- |
5.2.1 |
An upload is accepted on the server's terms — what the bytes are, not what the caller said they were — and every surface that takes one is declared. | declared — 0 upload surfaces across 28 routes |
5.2.2 |
An uploaded file is stored under a name the server chose, so nothing the caller named decides where it lands. | declared — 0 upload surfaces across 28 routes |
5.3.1 |
Every file this extension writes says whether a browser can fetch it, and nothing it writes where a browser can reach is program code. | declared — 5 write sites, 3 of them fetchable by a browser:system/library/diary.php:437 — kyvero.log in the store's own log directory — the DIR_LOGS this class is handed, with no part of the name coming from a request — one record appended per write, at system/library/diary.php:437system/library/diary.php:470 — the same kyvero.log, opened r+ to trim it back under the 1 MiB cap, at system/library/diary.php:470system/library/diary.php:495 — the same kyvero.log, rewritten to what a trim kept — oldest-first, on a line boundary, under an exclusive non-blocking lock — at system/library/diary.php:495 |
5.3.2 |
Every path this extension writes to is written down beside the code, with where the name in it came from. | declared — 5 write sites, each declared with its file:line and pinned against the token stream both ways:1 × a memory stream, opened per export and discarded with the request 3 × log file 1 × the day's rows: order id, customer, address, window and status, quoted by fputcsv() |
6.2.6 |
A field that takes a password or a key is masked, so it is not left readable on the screen or in a screenshot of it. | checked — 22 .twig files |
6.2.7 |
A masked field does not refuse a paste or shut a password manager out of it. | checked — 22 .twig files |
6.3.2 |
No credential is written into the source — no default account, and no password or key a reader of the shipped files could use. | checked — 76 .php files |
8.1.1 |
Every route the extension answers is written down beside the code, with what guards it — and the gate refuses a route nobody wrote down and a written-down route nothing answers. | declared — 28 routes: 21 admin, 7 catalog, each declared beside the code |
8.2.1 |
An admin route that changes something tests the permission itself, in a condition that can refuse — and a route that only reads says so, standing behind the check OpenCart makes before dispatch. | declared — 21 admin routes: 13 pin a permission themselves, 0 at one same-class hop, 0 at two (the hop ceiling), 8 unpinned:extensions/delivery_date/src/admin/controller/customer/purge.php:83 — Purge::index() pins no permission of its own; core checks access on extension/delivery_date/customer/purge before dispatch. No model write is reachable from it.extensions/delivery_date/src/admin/controller/module/delivery_date.php:314 — DeliveryDate::index() pins no permission of its own; core checks access on extension/delivery_date/module/delivery_date before dispatch. No model write is reachable from it.extensions/delivery_date/src/admin/controller/module/delivery_date.php:1259 — DeliveryDate::calendars() pins no permission of its own; core checks access on extension/delivery_date/module/delivery_date before dispatch. No model write is reachable from it.extensions/delivery_date/src/admin/controller/module/delivery_date.php:1398 — DeliveryDate::calendar() pins no permission of its own; core checks access on extension/delivery_date/module/delivery_date before dispatch. No model write is reachable from it.extensions/delivery_date/src/admin/controller/sale/planner.php:60 — Planner::index() pins no permission of its own; core checks access on extension/delivery_date/sale/planner before dispatch. No model write is reachable from it.extensions/delivery_date/src/admin/controller/sale/planner.php:271 — Planner::unscheduled() pins no permission of its own; core checks access on extension/delivery_date/sale/planner before dispatch. No model write is reachable from it.extensions/delivery_date/src/admin/controller/sale/planner.php:323 — Planner::print() pins no permission of its own; core checks access on extension/delivery_date/sale/planner before dispatch. No model write is reachable from it.extensions/delivery_date/src/admin/controller/sale/planner.php:383 — Planner::export() pins no permission of its own; core checks access on extension/delivery_date/sale/planner before dispatch. No model write is reachable from it. |
8.2.2 |
A storefront route that reaches a record says which caller may reach which records, and what selects one — so reaching somebody else's is a question with a written answer. | declared — 7 triples over 6 of 7 catalog routes; the admin half is one line on the shared page:extension/delivery_date/checkout/delivery_date.picker — the shopper's own session, signed in or not: The rail shows the windows this storefront offers for the method the shopper's own checkout quoted. Selected by none — not a record; the shipping method is read from $this->session->data['shipping_method'] and never from the requestextension/delivery_date/checkout/delivery_date.availability — the shopper's own session, signed in or not: It answers the same rail the checkout would have drawn for this session, and nobody else's. Selected by none — not a record; it re-renders the picker and reads no request keyextension/delivery_date/checkout/delivery_date.notice — the shopper's own session, signed in or not: It restates the window this session chose, and can name no other. Selected by none — not a record; the chosen window is read out of the sessionextension/delivery_date/checkout/delivery_date.save — the shopper's own session, signed in or not: A shopper can take a window this storefront is currently offering them; the choice lands in their own session and in no row of anybody else's. Selected by none — not a record; post[dd_date] and post[dd_slot] name a window, and a pair the availability sweep did not offer is refused rather than storedextension/delivery_date/api/gateway.fail — a holder of one of core's oc_api credentials: Absent, unknown, duplicated, disabled, wrong-keyed and address-not-listed are one refusal with one code and one message, so the envelope partitions nothing. Selected by none — not a record; this route renders a refusal and reads nothingextension/delivery_date/api/v1/booking — a holder of one of core's oc_api credentials: The credential cannot be scoped. A booking carries no name, address or contact detail — those are core's, on core's order — only the day, the window as the customer was told it and the shipping method; the hold's lease, touched_at, is never selected. Selected by opencart_order_idextension/delivery_date/api/v1/booking — a holder of one of core's oc_api credentials, walking the collection: filter_store_id is a convenience for a caller who wants one store, not a boundary: the same credential may simply leave it off. Selected by none — not a record; the filters and the cursor are a page of a walk rather than a record selector |
8.3.1 |
What bounds a caller to their own records comes from the server — a session, a stored row, the store id — and never from a value the caller supplied. | declared — 6 distinct bounds, each named by the triple it scopes: bounded by nothing — an OpenCart API user opens every store in the installation, and this resource does not narrow that bounded by config_store_id and the session's own quoted method bounded by config_store_id, the session's own quoted method, and the shopper's own order_id so their held window does not count against them bounded by nothing — a filter is the caller narrowing their own read, never the store narrowing what they may see bounded by nothing — the refusal is the same for every caller bounded by the session key this extension writes on save |
9.1.1 |
A secret that carries its own claim — an identity inside the string rather than a row to look up — is only believed after the signature beside it has been checked. | declared — 0 self-contained surfaces of 1 bearer-secret surface |
9.1.2 |
Every hashing algorithm is a literal in the source, from a fixed allowlist, so nothing arriving in a request can choose a weaker one. | checked — 76 .php files |
9.1.3 |
The key a signed secret is checked against comes from somewhere this extension was configured with, never from anything inside the secret itself. | declared — 1 bearer-secret surface, from core — never from anything inside the secret presented:system/library/api_gateway.php:948 — core |
9.2.1 |
A secret that carries its own expiry is accepted only inside it, and the declaration says which ones carry one. | declared — 0 surfaces of 1 bearer-secret surface could carry a validity span inside the secret itself; the rest are a reference to a row, whose expiry is a column on it rather than a claim the caller presents: No secret this extension accepts carries its own validity span. |
11.3.1 |
Nothing encrypts with a broken mode or padding — no ECB, no PKCS#1 v1.5. | checked — 76 .php files |
11.3.2 |
Where anything is encrypted, the cipher is a literal in the source from a short allowlist, so nothing arriving in a request can choose a weaker one. | checked — 76 .php files |
11.4.1 |
Every hash this extension computes is written down with what it is for, so a hash naming a cache entry is not read as one standing in front of a secret. | declared — 0 hash uses over 0 calls to 0 hash functions: This extension computes no hash. |
12.1.1 |
No outbound request asks for a TLS version below 1.2, and none pins itself to one at all. | checked — 76 .php files |
12.2.1 |
An outbound request is made over TLS with the certificate verified, and never falls back to cleartext. | checked — 76 .php files |
12.2.2 |
An outbound request trusts your server's own certificate store: nothing here bundles a certificate authority of its own or turns verification off. | checked — 76 .php files |
14.2.1 |
A credential is not carried in a URL, where a browser history, a referrer header and a proxy log each keep their own copy of it. | declared — 0 bearer-secret surfaces of 1 travel in a URL |
14.3.1 |
Nothing is left behind in the browser's own storage for the next person at that computer to read. | checked — 22 .twig files |
15.2.1 |
The extension bundles no third-party library, so there is nothing inside it for you to keep patched other than our own code. | checked — 76 .php files |
15.3.1 |
What reaches a page is an enumerated set of values rather than whole database rows handed over wholesale, and every one of them is written down. | declared — 85 store-derived subtrees reaches a template of this extension, each one written down; what a model row holds beyond them does not:module_delivery_date_status — settingmodule_delivery_date_lead_basis — settingmodule_delivery_date_released_statuses — settingmodule_delivery_date_review_status_id — settingmodule_delivery_date_hold_minutes — settingversion_warning — the store's OpenCart release, through Compatibilityorder_statuses — database — core's oc_order_status in the admin's languagecopy_panel — rendered partial over the merchant's own storefront wording, per languagecopy — the merchant's stored wording overrides beside this extension's shipped defaultslanguage_readout — rendered partial over oc_languageresolution — rendered from oc_language, through LanguageReadoutlanguages — database — core's oc_language, unfilteredconfig_language_id — setting — the store's default languagetimezone_link — a link to core's own setting screen, carrying the admin session tokentext_timezone — the store's configured timezone, into a language stringcalendars — database — delivery_date_calendar rows for this store, the baseline firstcalendar_id — database — the calendar the screen is editingname — database — the calendar's own name, the slot names, and on the storefront the chosen window's labelstatus — database — the calendar's own status, and an order's status on the plannerinherit_days — database — whether this method calendar takes the store's weeklead_days — database — the calendar's own lead time, and a product's own override on the product tabcutoff — database — the calendar's own cutoff timehorizon_days — database — how far ahead the calendar offersslots — database — delivery_date_slot rows with their per-language names, or the posted week where the form is unsavedoffers — database — which slots each weekday offers, and at what caplimits — database — the per-day ceiling for each weekdayclosures — database — the date ranges the calendar is closed forweekdays — the seven weekdays named in the admin's own languageweek_readonly — database — whether this method calendar inherits its week and so cannot be edited heremethods — the store's enabled shipping extensions, each with the calendar assigned to itmethod — database — the shipping method a calendar or an order carriesreference — database — the shipping-method codes a calendar answers for, and the planner's own filter off the requestfree — the shipping methods no calendar has claimed yetwarnings — database — what the calendars, their slots and the store's methods contradict about each otherglobal — a summary of the baseline calendar's week, slots and capacity as sentencesdays — database — the days the preview or the storefront rail resolved, each with its slotsexplanation — why each previewed day resolved as it did, as language strings carrying the calendar's own numberspreview — a link to this extension's own preview route, carrying the admin session tokenpreview_html — rendered partial over the previewed dayspreview_now — request — post[preview_now], the moment the merchant moved the clock topreviewbox — rendered partial holding the preview paneweek — rendered partial holding the week griduser_token — the admin session token, rendered into the planner's own JavaScript URLsdate — request — get[date] on the planner, narrowed to a real Y-m-d, and the day of a previewed or offered windoworders — database — core's oc_order joined to this extension's booking rows, with customer names and shipping addressesorder_id — database — the order a planner row or an order-page block is aboutsections — database — the day's windows, each with the orders booked into itmatrix — database — the week grid of window against day, with counts and capscolumns — the days the planner grid is showingselected_index — which of those columns the requested date falls onnamed — database — the window names the grid's rows are labelled withtotal — a count of the day's orders, into a language stringtoday — the store's own clock, in the store's timezoneprevious — a planner link for the day before, carrying the admin session token and the current filternext — a planner link for the day after, carrying the admin session token and the current filterreset — a planner link back to today, carrying the admin session tokenprint — a planner link to the print sheet, carrying the admin session token and the current filterexport — a planner link to the CSV, carrying the admin session token and the current filterpicking — core's own sale/order.shipping link, empty where this admin has no access to itpicking_orders — database — the order ids the picking form postsclosed — whether the calendar closes the day the planner is showingempty — whether the day is open but has no orders on itunscheduled — database — orders with no window booked, and on the checkout the sentence for a shopper who has chosen noneunscheduled_link — a planner link to that list, carrying the admin session tokentable — rendered partial over the order rowstitle — the day and the filter the print sheet is for, into a language stringbase — the store's own admin URL, so the print sheet can reach its stylesheetbootstrap_css — the path core serves Bootstrap fromstylesheet — the path core serves the admin stylesheet fromlang — setting — the admin language's own code, into the sheet's direction — setting — the admin language's own text directionday — database — the day an order is booked for, and a previewed or offered daywindow — database — the window an order is booked intowas — database — the window the order was booked into before it was movedreassign — a link to this extension's own planner.form route, carrying the admin session token and the order id; empty where the booking is not firm or the user group lacks modify on the plannerreassign_date — database — the day the order is booked for, or today on the store's own clock where it has noneavailability — a link to this extension's own availability route, in the storefront's languagesave — a link to this extension's own save route; on the admin screens, to its own save routes with the session tokenvisible — how many of the offered days the rail shows before the More buttonmore — whether there are further days behind that buttonmarker — the day the rail opens onchosen — the window this session has taken, out of the sessionreason — why no day could be offered, as a language string carrying the calendar's own numbersdanger — whether the notice is a refusal rather than a restatementapi_panel — settings and database — whether the API is on, and core's own oc_api rows |
16.2.5 |
No log line names a credential — no token, secret, signature or password is written into the file the error log screen renders. | checked — 76 .php files |
16.4.1 |
Everything written to the error log is escaped first, so nothing a store holds can forge a record or close the box a merchant reads the log in. | checked — 76 .php files |
16.5.1 |
No error message carrying internal detail — a database driver puts the failing statement in one — is thrown onward or rendered to a response. | checked — 76 .php files |