MapKraken ← MapKraken

Security at MapKraken

Territory Mapper is a territory-management application for Salesforce, published by MapKraken Labs LLC.

This page describes how Territory Mapper handles your data, what it stores, what it does not, and which security controls are in place today. It is written to be checked. Where a control does not exist, this page says so rather than implying otherwise — there is a section for exactly that, and it is not short.

Territory Mapper is pre-release. It is not yet listed on the Salesforce AppExchange and has no production subscribers. Several of the controls an enterprise security team expects are in progress rather than in place, and they are listed in What we do not claim yet. We would rather you read that section first than find it later.


1. Architecture

Territory Mapper has three tiers.

A managed package installs in your Salesforce org and holds the territory model, the assignment logic and the administrative setup. A map application — a browser application served from a content delivery network — runs inside your Salesforce org in a Canvas frame. A geospatial service, hosted by MapKraken on Amazon Web Services, performs the spatial work: turning a set of selected census boundaries into a dissolved territory polygon, and answering the map's queries about geography.

Your CRM records stay in Salesforce. The geospatial service holds census geography — public reference data — together with the identifiers and territory names it needs to associate a polygon with one of your territories. Section 2 lists exactly which.

   ┌─ your Salesforce org ─────────────────────────────┐
   │                                                   │
   │   Territory Mapper managed package                │
   │   territory model · assignment · setup            │
   │                                                   │
   │   ┌─ Canvas frame ────────────────┐               │
   │   │   the map application         │               │
   │   └───────────┬───────────────────┘               │
   └───────────────┼───────────────────────────────────┘
                   │
        signed handshake, verified server-side
                   │
                   ▼
   ┌─ MapKraken geospatial service (AWS, us-east-1) ───┐
   │                                                   │
   │   spatial operations · territory geometry         │
   │   census geography (public reference data)        │
   │                                                   │
   └───────────────────────────────────────────────────┘

Two directions of traffic are worth naming, because a security team will ask about both. The map application reads and writes your Salesforce data as the signed-in user, over Salesforce's own APIs, with that user's field-level security and sharing rules enforced by the platform. Separately, the geospatial service reads your territory hierarchy back from Salesforce using a per-org credential your administrator authorises at install.


2. What we store — and what we do not

The geospatial service persists eight things. This is the complete list, read from the running database rather than from a design document.

WhatWhy it is there
Your Salesforce Org IdIdentifies which org a territory belongs to; it is also the partition key for your data
Your Territory Model IdsAssociates geometry with the right territory model
Your Territory record IdsAssociates a polygon with a territory
Your territory namesLabels the polygon on the map
The dissolved territory polygons themselvesThe product
The integration user's usernameIdentifies the account the service authenticates as when it reads your hierarchy
Your org's My Domain login URLThe endpoint the service authenticates against
The connected-app consumer key for the integrationPart of the credential your administrator authorises at install

What is not stored, stated as specifically as we can make it. We checked every column of every table, not our expectations:

Territory names are free text that you control. They are stored exactly as entered and are not inspected or validated. If you put personal information in a territory name, it will be persisted. We mention this because it is the one field on the list where what gets stored is your choice rather than ours.

How long we keep it. See §7. The honest answer is short and it is not the one you want.


3. Tenant isolation

Each subscriber org's territory data is held in a separate set of database tables, partitioned by your Salesforce Org Id. On every data route, the org identity used to select those tables is taken from a cryptographically verified token and never from anything the caller supplies; a request that names one org while carrying a token for another is rejected, not served.

The partition is enforced in the application layer. It is not enforced by the database itself: there is no row-level security and no per-org database role. We state this plainly because a security team will find it, and because "application-layer" is a materially different guarantee from "database-enforced."

We do not yet claim complete tenant isolation. One isolation defect is open and tracked, identified by our own security review: the token the Salesforce side presents to the geospatial service is signed with one shared secret rather than a per-subscriber key. That means the service can verify that a token is genuine, but not that it belongs to the subscriber it names. (A second defect, an unauthenticated path to the same outcome, was found in the same review and closed on 2026-08-19.)

So the service currently serves no external subscriber, and a second active subscriber credential cannot be inserted. The one organisation provisioned on it is our own Salesforce Developer Edition org. There are no external subscribers and no paying subscribers today, and we say that rather than write "a single subscriber", which would invite you to picture a customer.

That second statement is enforced, not merely intended. Since 2026-08-23 the credential table carries a uniqueness constraint scoped to active credentials, so a second active one cannot exist; we re-probed it live against the running database on 2026-08-24 — the constraint is present, it is unique, it applies to active rows, and there is exactly one active row. Onboarding a second organisation fails at the database, by design, until per-org signing keys ship. That work is designed and scheduled to the day it is first needed. The full position, including the wording we give a security reviewer, is written down and we will share it on request. See also What we do not claim yet.


4. Encryption

In transit.

HTTPS is enforced on the tier that serves subscribers. Since 2026-08-21 a plaintext request to the geospatial service is redirected rather than served: http:// returns a 301, the load balancer listens on 443 only — the plaintext and auxiliary listeners were removed — and the content delivery network in front of it redirects to HTTPS and reaches its origin over HTTPS only. Four independent probes confirm it.

🔴 Changed 2026-10-07 — this passage understated the control, and we are publishing the change for the same reason we publish the overstatements (167-F4). It used to say: "Two non-production stages still accept a plaintext viewer connection rather than refusing it … masked by an availability fault rather than closed by a control," with refusal "dated 2026-09-05."

Measured against the running system on 2026-10-07, every stage we run redirects plaintext. A census of all 17 content-delivery distributions in the hosting account found none configured to accept a plaintext viewer connection. Probed as well as read: a plaintext request to the production geospatial service returns a 301 redirect and the service behind it answers an authenticated request — it is live, not timing out, so there is no availability fault left there to do any masking.

One remainder, stated precisely. On a single non-production stage the hop from the content delivery network to its origin is still plaintext. That stage serves no content, carries no subscriber data, and is not reachable by a subscriber. It is listed in What we do not claim yet and it is the last plaintext leg in the estate.

At rest.

🔴 Changed 2026-10-07 — this section claimed a control the production database does not have, and saying so is the whole point of publishing a page like this (166-F17). What it used to say: "The service database is encrypted at rest … the database your data reaches is encrypted at rest under a customer-managed key with annual rotation," with the unencrypted remainder described as "a frozen legacy demonstration instance." Measured against the running service on 2026-10-07, that was wrong twice.

The production database is NOT encrypted at rest. Our staging database is. Measured, not inferred:

instanceencrypted at rest?what it is
prd-koop-postgis🔴 No — StorageEncrypted: false, no keyThe database the production service reads and writes. The live task definition sets PG_HOST to it, and the service is running
sit-koop-postgis✅ Yes — customer-managed key, annual rotation, since 2026-08-24Our staging database

So the 2026-08-24 migration was real, and it was a migration of staging. It took 7 minutes 43 seconds with the data proven byte-identical across the cutover — 17 row counts, 4 checksums and 2 geometry areas compared before and after. What was wrong was calling its result "the database your data reaches."

🔴 And the second error was the label. The unencrypted instance was described as "a frozen legacy demonstration instance." It is the production database. It is frozen in the sense that we deliberately stopped changing it pending this work, and today it holds demonstration data only — we have no external and no paying subscribers, and the one provisioned org is our own Developer Edition org (§3) — but "frozen legacy demonstration instance" describes something decommissioned, and this is not that. An unencrypted production database is the kind of thing a page like this exists to state plainly.

What is true today, stated without rounding:

**All of this is in What we do not claim yet. 🔴 The previous wording of this section is quoted above rather than deleted, because a trust page that silently rewrites a claim it got wrong is asking to be trusted on exactly the thing it just got wrong** — the same rule this page's 2026-08-24 entry applied to itself.


5. Authentication and access control

How a request is proven to come from your org.

The map application is launched by Salesforce inside a Canvas frame. Salesforce signs the launch payload, and the geospatial service verifies that signature server-side — checking the signature itself with a constant-time comparison, pinning the signing algorithm, and rejecting a payload outside a five-minute window. Your org's identity is read from the verified payload and carried through to the database table name; it is never read from caller-supplied input on a data route.

Every data route on the geospatial service requires a verified bearer token. A request without one is refused. Cross-origin policy is not the control and is not relied on as one.

No token, org identifier or territory data travels in a URL on any hop. They travel in signed payloads and request bodies, so they do not land in browser history, referrer headers or access logs.

What runs as you, and what does not.

Authorization at the geospatial service is per-org, not per-user. A session token proves which org a request belongs to. It does not carry the user's Territory Mapper permissions, so inside the map, the service does not distinguish a read-tier user from a manager. Capability is governed by Salesforce permissions on the Salesforce side and by org scope on the map side. Adding per-user authorization to the service is planned. If per-user enforcement inside the map is a requirement for you, it is not there today.

Session lifetime. A map session lasts 8 hours and does not refresh.


6. Secrets and key management

Credentials used by the geospatial service are held in AWS Secrets Manager and supplied to the service at container start by the AWS platform.

🔴 Changed 2026-10-08 — this paragraph claimed a restriction that production does not have, and we are publishing the change for the same reason we publish the overstatements. It used to end: "The application process itself holds no permission to read Secrets Manager at runtime." Measured against the task definition actually in service, that was not true of production. The production service's own identity carries a permission to read one secret — the credential for the review organisation — and so the application process can read that one secret at runtime.

What is true, stated precisely. The sensitive credentials — the signing keys and the database credential — are read by a separate platform identity that the application process does not hold, and are placed into the service's environment before the process starts. The one secret the service's own identity can fetch for itself is the review-organisation credential, which is neither a database credential nor a signing key. On our non-production stage the service identity holds no secret-retrieval permission at all. ⚠️ And because credentials are delivered through the process environment, a credential is readable by anything that can read that environment — we say so rather than let the delivery path be read as an isolation boundary it is not.

Secret injection is the delivery path, and we have proved it is load-bearing — an end-to-end test completes a Canvas login on an image that has nothing to fall back on. On 2026-08-08 we inspected a container image directly and confirmed it carried no environment file, no private key material, and a clean result from a secret scanner run across the whole application directory.

We do not claim that the image running today carries no embedded credentials. Re-inspecting our registry on 2026-08-20, we found that our image build had begun including an environment file again after that clean build, and that the images now running include one. We found this ourselves, we are stating it rather than waiting until it was fixed, and correcting the build is our highest-priority open item. Two things a security team should weigh alongside it: the credentials involved are the ones already covered by our written credential-exposure disclosure, and nothing automatically detected the regression — which is the more important finding, and is why image scanning is now on the list in What we do not claim yet.

Source-history secret scanning. A full-history scan of all four of our repositories with gitleaks 8.30.1 on 2026-08-06 produced seven hits: two false positives, one already redacted, and four in deleted or superseded files. No live credential is exposed by our source history. The tool version and the exact command are recorded so the result can be reproduced rather than taken on trust.

We do not operate automated secret rotation. Rotation is manual today. Automating it is planned.


7. Logging and retention

Application logs. The geospatial service writes application logs to Amazon CloudWatch with a thirty-day retention period. Every log group in our hosting account carries an explicit retention period and none is unbounded. Sampling found operational events and no personal data; we have not completed a formal audit of log contents and do not claim one.

The Salesforce-side failure log. Territory Mapper records assignment failures in your org so they can be worked rather than lost. That log has a real, enforced policy:

Each record holds Salesforce record ids, the object's API name, a failure category, the service's own error text, a latitude and longitude, a geocode accuracy value, a territory model id and a correlation id. No names, no addresses, and no account fields beyond coordinates the record already holds.

Data held by the geospatial service — the retention policy, and the two things it does not do. This is the section a procurement team will stop on, so it is written without softening:

Application logs cannot be deleted per subscriber — they are shared log groups. They expire at 30 days.

Audit logging and alerting. We do not currently operate infrastructure audit logging, security monitoring or alerting on the hosting account. The two halves are in different states and we would rather split them than average them. Audit logging is decided and dated: 2026-08-31. The destination the trail writes to already exists; what is missing is the trail itself. Alerting is not dated. Metric filters, alarms and a path that pages a person are an accepted risk with no date against them, and we are not going to imply otherwise. We do not claim monitoring we do not have.


8. Vulnerability management

What actually runs, stated as what runs rather than what we intend:

ControlState
Secret scanning in CI◐ Configured. gitleaks is wired into GitHub Actions in all three application repositories and blocks a secret committed to a scanned branch. ⚠️ Updated 2026-08-25 — one of the two stated limits is fixed, the other is not, and a third was found while fixing the first. ✅ The branch list is fixed, and as of 2026-08-25 it is VERIFIED, not merely changed: the enumerated filter was removed rather than extended — extending a list is what let it rot in the first place — and the workflows have now been observed running on GitHub Actions against the actual task branches, which had never happened before. ⚠️ One of the four runs FAILED, and we are reporting that rather than the headline: territorymap-koop exited non-zero on two hits, both test fixtures containing no key material (a -----BEGIN PRIVATE KEY----- envelope wrapped around the literals MIIE and nope, the second one asserting that such input is rejected). It is a true positive by rule and a false positive by substance, it is filed as 44-F16 rather than quietly allowlisted — and it is the first live proof that this gate genuinely blocks a build rather than merely reporting. 🔴 The clean-checkout limit stands and cannot be fixed here: a file excluded from source control is invisible to any repository scan, because the scan runs on a checkout of committed history. The control that closes it inspects the built container image, and we have not built it yet. 🔴 And read "all three application repositories" precisely, because it is doing quiet work: our infrastructure repository has no secret scanning at all, and it is the one holding deployment templates. We are stating the denominator rather than letting the phrase imply full coverage ✅ Updated 2026-08-25 (later): the second limit is now CLOSED — the built container image is scanned. A CI job exports the image’s flattened filesystem and runs two independent checks: a secret scan of the application code, and an assertion that no .env or *.pem file exists in it. Both failure paths were proved deliberately before the gate was trusted. This closes the gap that source-side scanning is structurally unable to cover — a file excluded from source control can still be copied into an image, and only looking inside the built image finds it. ⚠️ Two limits we state rather than imply away. The job scans a representative build of the image, not the exact artefact published to our registry — verifying the published artefact remains a manual step. And the scan covers application code only: the scanner excludes vendored third-party dependency directories by default, so a clean result is a statement about the code we write, not about every byte in the image. Where the tool does not report enough to substantiate a coverage figure, the job now prints that the coverage is undeterminable rather than printing a number (44-F18). 🔴 Unchanged: our infrastructure repository still has no secret scanning at all, and it is the one holding deployment templates. We continue to state the denominator rather than let the phrase imply full coverage
Full-history secret scan✅ Performed 2026-08-06 across all four repositories, tool version and command recorded, result reproducible (§6)
Dependency vulnerability review◐ ~~Performed manually against the published advisory database. It is not a CI gate, and we do not claim one~~ ⚠️ Updated 2026-08-25 — a CI gate now exists and RAN, and the honest statement is narrower than "we have one." dependency-audit.yml runs in all four repositories, installs with npm ci never npm install (an npm install audits a tree the lockfile would never deploy), and compares against a committed baseline. ✅ Verified on GitHub Actions 2026-08-25: every baseline reproduced exactly, zero drift. 🔴 But read the coverage, not the green check: it measured 4 of 25 declared roots. The other 21 have no committed lockfile, so they are unauditable — npm audit exits ENOLOCK — and the job is configured not to treat that as fatal, so it passes while measuring nothing. In our infrastructure repository that is 20 of 20 roots skipped and a green tick (44-F15). It is also report-only by design, so today it reports and does not block
Container image scanning✖️ Not enabled
Defined patch cadence✖️ Not yet defined
Dynamic application security testing (DAST)◐ Performed 2026-08-25 against our staging environment, in two passes the same day. An industry-standard DAST scanner was run against all three in-scope staging hosts (the API host, the web application, and the tile-serving host); dated reports are retained for both passes. No high or critical findings, across either pass. The findings were header-level hardening items — a permissive cross-origin policy, a missing HSTS header, a missing MIME-sniffing header, a missing content-security-policy/anti-framing header on the web application, and a handful of other missing modern browser-isolation headers — each triaged individually rather than accepted at the tool's default rating, and no injection-class issue (SQL injection, cross-site scripting, SSRF, path traversal, command or template injection) was found by any of the ~140 active rules per target. One finding is flagged for follow-up rather than dismissed: the web application persists its session client-side and does not currently restrict which pages may frame it, which is a narrower version of a well-known browser attack (UI redress / "clickjacking") against an already-signed-in user — under review for a fix. ⚠️ We state the limits rather than imply full coverage: the scan was unauthenticated, so it demonstrates that authenticated routes correctly reject unauthenticated callers and nothing about behaviour within an authenticated session. The authenticated pass is planned and requires a real application session plus explicit sign-off before it runs. Production was not scanned
Third-party penetration test✖️ Not performed
Automated build, test and lint gates in CI✖️ Not in place for the application repositories

Territory Mapper's own security review is internal, evidence-based and adversarial — every claim on this page traces to a measurement, and the gaps on it were found by that review rather than reported to us. That is what we have instead of a certification, and we would rather say so than dress it up.


9. Incident response

We do not yet operate a formal incident-response program. What we commit to today:

We will not claim a documented incident-response plan, an on-call rotation, or a tested runbook, because we do not have them. Establishing them is planned.


10. Subprocessors

Third parties that process data on our behalf, or that receive end-user requests directly. This list was derived by reading our infrastructure and our application source, not by listing what we expected to find.

SubprocessorService providedWhat it receivesLocation
Amazon Web Services, Inc.Compute, database, object storage and content delivery for the geospatial service and the map applicationAll data the geospatial service holds (§2)United States — us-east-1
OpenStreetMap FoundationDefault basemap tilesRequested directly by the end user's browser: their IP address and the map area being viewed. No Salesforce dataProvider-operated global CDN
Stadia MapsOptional basemap styles, user-selectableAs aboveProvider-operated global CDN
EsriOptional satellite imagery basemap, user-selectableAs aboveProvider-operated global CDN
OpenStreetMap Foundation — NominatimPlace-name search for the map's city-search boxRequested directly by the end user's browser: the text they type into the search box and their IP address. No Salesforce data, no record data, no identityProvider-operated, EU

Two things worth being precise about.

Basemap tiles are requested by the end user's browser, directly from the provider. They do not pass through MapKraken infrastructure. The provider therefore sees the viewer's IP address and which part of the map they are looking at. It receives no Salesforce data, no territory data and no identity. Three of the four are user-selectable from the map's layer control; OpenStreetMap is the default. If your security policy restricts which external tile providers may be contacted from within Salesforce, tell us — the set is a configuration decision and it is not yet fixed.

The map's city-search box sends what the user types to a third party. Typing a place name into the map's search control issues a request to the OpenStreetMap Foundation's Nominatim service carrying that text and the viewer's IP address. It is how the search box finds a city. It carries no Salesforce data, no record data and no identity, and it fires only when a user actually types in that box. 🔴 It is listed above because it is a real third-party contact, and because the same search control is present on our public marketing demo, where a visitor has no account with us at all. If your security policy restricts which external services may be contacted from within Salesforce, tell us — like the tile providers, this is a configuration decision and is not yet fixed.

🔴 Changed 2026-10-07. This table previously listed four subprocessors and did not include Nominatim, while the paragraph below said "Nothing else." That was wrong, and the search box had been contacting it all along (136-F1). The omission was ours; the behaviour was not new. We are recording the change here rather than correcting the list silently.

The census boundary tiles the product draws territories from are served from our own infrastructure, not a third party. They are public U.S. Census Bureau reference data and carry no subscriber content.

Salesforce is not listed as a subprocessor. Your Salesforce org is your platform, under your contract with Salesforce; Territory Mapper is a tenant of it, not a processor for it.

Nothing else, and this sentence is now scoped the way it should always have been. We verified against the application source that there is no analytics service, no error-tracking or crash-reporting service, no font CDN, no session-recording tool and no email service in the shipped product. There is no telemetry to disclose because there is none. ⚠️ The parties listed above are the complete set of third parties the product contacts — the four basemap providers and the place-name search. A bare "nothing else" is what let a missing row stand, so it is written here as a claim about telemetry, which is what we actually verified, while the table above is the claim about third-party contact.

What this table does not yet state. The contracting jurisdiction for each subprocessor, and our position on international data transfer, are not published here. Every subprocessor above is named, and what each receives is stated; the legal framing around them is not settled and we would rather leave it blank than draft it ourselves. If either matters to your assessment, ask — the underlying facts are the ones in this table and they will not change when the framing arrives.


11. Compliance

Every answer in this section is no or not yet. That is the whole section, and it is why it is short.

SOC 2 — no. MapKraken Labs does not hold a SOC 2 report, and no audit is under way. We are a small organisation and a Type II report is a meaningful undertaking; it is on the roadmap, without a date we would ask you to rely on. What we offer instead, today: this page, a completed security questionnaire, and direct access to the people who built the system. If a SOC 2 report is a hard procurement requirement, it is not something we can satisfy now, and we would rather you know that in the first conversation than the fourth.

Data Processing Agreement — not yet. A DPA template is not yet available. One will be provided before any production subscriber agreement is signed. If your procurement process requires a specific DPA form, we will work from yours.

Accessibility (VPAT / ACR) — no. MapKraken has not produced a VPAT or an Accessibility Conformance Report, and we do not claim WCAG conformance. The product has low-cost hedges rather than a conformance programme. We treat accessibility work as a scoped engagement rather than a baseline claim, and we will scope it honestly against your requirement — including the parts of a map interface where conformance is genuinely hard, which we would rather discuss than paper over.

Data residency. All MapKraken-operated infrastructure runs in Amazon Web Services us-east-1, in the United States. There is no non-U.S. deployment option today.


12. What we do not claim yet

Collected in one place, so you do not have to assemble it from the sections above. Each of these is either absent or incomplete today. None of them is written in a way that lets a reader mistake a plan for a control.

State today
Encryption at rest on the service database🔴 NOT ENABLED IN PRODUCTION — Changed 2026-10-07 (166-F17). This row read ◐ "Enabled 2026-08-24"; measured against the running service, prd-koop-postgis is StorageEncrypted: false and is what the production service connects to. ✅ Staging (sit-koop-postgis) is encrypted under a customer-managed key with annual rotation since 2026-08-24, migrated with the data proven byte-identical. 🔴 The published date for production, 2026-10-05, has passed (166-F18); this row carries no date until the owner sets one, and the absence is deliberate. Twelve pre-cutover snapshots remain unencrypted, deletion date 2026-08-31 also passed
HTTPS-only on the geospatial service✅ Enforced on every stage — Changed 2026-10-07. Plaintext is redirected, not served, and a census of all 17 distributions in the account found none accepting a plaintext viewer connection (§4). One remainder: on a single non-production stage that serves no content, the hop from the delivery network to its origin is still plaintext
Complete tenant isolation◐ Partitioned and enforced in the application layer; one isolation defect is open — the Salesforce → service token is signed with a shared secret, not a per-subscriber key. No external subscriber is served today — the one provisioned org is our own Developer Edition org — and a second active subscriber credential cannot be inserted, enforced by a database constraint deployed 2026-08-23 and re-probed live 2026-08-24, until per-org signing keys ship (§3; the full position is available on request)
Per-subscriber signing keys✖️ Not built. Designed; scheduled to the arrival of a second subscriber, which the constraint above cannot happen without
Database-enforced isolation✖️ No row-level security, no per-org database role
Per-user authorization inside the map✖️ Authorization at the geospatial service is per-org (§5)
Data retention and deletion◐ A policy exists for the geospatial service and a 30-day deletion window is enforced by a scheduled sweep — but there is no self-service delete control, deletion is a request we carry out, uninstall deletes nothing, and existing backups are not edited (§7)
Audit logging, monitoring and alerting✖️ None that can raise an alert, and the committed date for the audit trail has passed — stated plainly 2026-10-07. There is no audit trail on the hosting account; it was committed for 2026-08-31 and that date went by without it being started, which we are recording rather than re-dating. The destination it will write to already exists. One alarm exists, on a licensing metric; it has no notification target, and the account has no notification topics, so nothing can page anyone today. Alarms, metric filters and paging remain undated and are an accepted risk (§7)
Automated secret rotation✖️ Manual today
A running image free of embedded credentials✖️ Not true today. A clean build was achieved and the build later regressed; found by our own re-inspection on 2026-08-20 and stated in §6. Correcting the build is our highest-priority open item
Dependency scanning as a CI gate◐ ~~✖️ Manual review only~~ Changed 2026-08-25: the gate exists and has run — but it is report-only and it audits 4 of 25 roots. Where a lockfile is committed it works and its baselines reproduced exactly on Actions; where one is not — 21 roots, including all 20 in the infrastructure repository — it skips the root and still passes (44-F15). We are stating the denominator rather than letting a green check imply coverage ⚠️ Updated 2026-08-25 (later): the gate’s recorded baseline is now current, and the remaining gap is narrower but real. The baseline was re-measured from a clean, reproducible install after remediation — the service’s advisory count fell 22 → 11 overall and 13 → 0 for dependencies that ship in the running product. Until that re-measurement, the stored baseline overstated the tree and would have pre-authorised eleven advisories that no longer exist. 🔴 The coverage gap is NOT closed and we are not implying otherwise: the gate still audits 4 of 25 roots, because a root without a committed lockfile is skipped rather than failed — and that still includes all 20 roots in the infrastructure repository. A green result here means “the roots we can measure are at their recorded baseline”, not “every dependency is reviewed”. We are stating the denominator rather than letting a green check imply coverage
Secret scanning on every push◐ Configured in all three application repositories. ✅ Branch coverage fixed AND VERIFIED 2026-08-25 — the enumerated branch filter was removed, and the workflows were then observed firing on GitHub Actions against the real task branches (task/25, task/26, task/24, task/37), the first time this has ever been demonstrated rather than asserted. ⚠️ One repository's run went red on two keyless test fixtures (44-F16) — which is the gate proving it blocks. 🔴 Still not "every push" in two respects, both stated rather than smoothed over: it cannot see files excluded from source control (§8), and our infrastructure repository has no secret scanning at all — so the phrase "all three application repositories" is the accurate scope, not a full-coverage claim ✅ Updated 2026-08-25 (later): the gate is now proven to BLOCK, not merely to run. It failed a real build, the failure was triaged to two test fixtures containing no key material, and it was resolved with narrowly scoped exceptions carrying their written justification — deliberately not a blanket exclusion of the test directory, which is the kind of over-broad filter that previously let coverage rot unnoticed. We verified the exceptions did not blind the rule: a genuine private key placed in the same file is still detected. ⚠️ Both limits stay stated: it cannot see files excluded from source control (§8) — now mitigated by the image scan above — and our infrastructure repository has no secret scanning at all, so “all three application repositories” remains the accurate scope, not a full-coverage claim
Container image scanning✖️ Not enabled — and it is what would have caught the regression above
Dynamic application security testing (DAST)◐ Performed 2026-08-25 against our staging environment, in two passes the same day. An industry-standard DAST scanner was run against all three in-scope staging hosts (the API host, the web application, and the tile-serving host); dated reports are retained for both passes. No high or critical findings, across either pass. The findings were header-level hardening items — a permissive cross-origin policy, a missing HSTS header, a missing MIME-sniffing header, a missing content-security-policy/anti-framing header on the web application, and a handful of other missing modern browser-isolation headers — each triaged individually rather than accepted at the tool's default rating, and no injection-class issue (SQL injection, cross-site scripting, SSRF, path traversal, command or template injection) was found by any of the ~140 active rules per target. One finding is flagged for follow-up rather than dismissed: the web application persists its session client-side and does not currently restrict which pages may frame it, which is a narrower version of a well-known browser attack (UI redress / "clickjacking") against an already-signed-in user — under review for a fix. ⚠️ We state the limits rather than imply full coverage: the scan was unauthenticated, so it demonstrates that authenticated routes correctly reject unauthenticated callers and nothing about behaviour within an authenticated session. The authenticated pass is planned and requires a real application session plus explicit sign-off before it runs. Production was not scanned
Third-party penetration test✖️ Not performed
Formal incident-response programme✖️ Commitments in §9 only
SOC 2✖️ Not certified, no audit under way
DPA✖️ Not yet available
VPAT / ACR✖️ Not produced
A published safe harbour for security research✖️ Not published. It is a legal commitment and it is with counsel; §13 says what we ask of you in the meantime and does not imply permission we have not granted
Subprocessor jurisdictions and the international-transfer position✖️ Not published (§10). Every subprocessor is named and what each receives is stated; only the legal framing is absent

Why this section exists. A trust page that lists only controls is a marketing page. Every item above was found by our own review, is tracked with an owner, and is written here in the same words we use internally. If any of them is a blocker for you, say so — we would rather lose the evaluation early than pass it on a misreading.


13. Security contact

Report a vulnerability to security@mapkraken.com. It is a monitored mailbox, read by a person, and mail sent to it is authenticated — mapkraken.com publishes SPF, DKIM and DMARC, so a reply from us can be verified as ours and a forgery of us can be rejected as not.

What to include: what you found, where, and the steps to reproduce it. A proof-of-concept helps. If you believe the issue is being actively exploited, say so in the subject line.

What to expect: acknowledgement within two business days, an assessment and a remediation plan, and credit in our disclosure record if you want it. That record exists as of 2026-08-24, and it is empty — nothing has been reported to us yet. It is not published at a public address; ask and we will tell you what is in it. We do not operate a paid bug bounty.

Testing in good faith — we have not published a safe-harbour position yet, and we are not going to imply one. A statement that we will not pursue legal action over good-faith research is a legal commitment, and ours is with counsel rather than written by us. Until it is published here, please treat this section as describing where to send a report, not as a grant of permission to test. Two requests in the meantime, and they are the ones that would be in any such statement anyway: do not access, modify or exfiltrate another subscriber's data or degrade the service for others, and do not test against a subscriber's Salesforce org — it is theirs, not ours. If you want to test and the absent safe harbour is what is stopping you, write to the address above and ask; we would rather have that conversation than not get the report.

Everything else: the same address reaches us.


Last updated: 2026-10-08 · Owner: MapKraken Labs LLC

This page changes whenever our security posture changes. It is derived from an internal review document that carries the evidence for every claim on it, and it is re-verified against that document rather than edited independently. A claim that stops being true is removed the same day it stops being true.

Last updated: 2026-10-08 · Owner: MapKraken Labs LLC

This page is derived from an internal review document that carries the evidence for every claim on it, and is re-verified against that document rather than edited independently.