Back to skill

Security audit

OpenLayers Maps

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly a coherent OpenLayers helper, but its scaffold generator can create browser pages that execute unsafe embedded GeoJSON content and mutable third-party JavaScript.

Review before installing if you expect to generate HTML from untrusted GeoJSON or host generated pages under a real application domain. The skill is not trying to steal data or persist access, but its scaffold output should be fixed to escape embedded JSON and pin OpenLayers to a reviewed version before production or shared use.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/openlayers_scaffold.py:134
Finding

Stored JavaScript Injection Through Embedded GeoJSON Content

Content
View full analysis
` element. JSON serialization makes the data valid JavaScript syntax but does not make it safe for embedding in an HTML script element. In particular, `json.dumps` does not escape the HTML parser-sensitive sequence ``. A malicious GeoJSON property can therefore terminate the existing script element and introduce a new attacker-controlled script element. For example, a property containing the following value would survive JSON serialization: ```json { "type": "Feature", "properties": { "name": "" }, "geometry": { "type": "Point", "coordinates": [0, 0] } } ``` The browser's HTML parser recognizes the closing `` sequence regardless of whether it appears inside what JavaScript treats as a string literal. Consequently, the injected script executes when the generated HTML page is opened. ### Attack Path 1. An attacker creates or modifies a GeoJSON file containing a property value with a `` breakout payload. 2. The victim obtains the file and invokes the documented scaffold command: ```bash python3 scripts/openlayers_scaffold.py geojson \ --out ./openlayers-geojson.html \ --geojson ./untrusted.geojson ` ...[truncated 1217 chars]
Remediation
View remediation
{escaped_geojson_payload} ``` Before embedding the serialized JSON, escape characters that can affect HTML parsing. At minimum, replace `<` with its JSON Unicode escape: ```python geojson_payload = json.dumps( geojson_obj, ensure_ascii=True, indent=2, ).replace("<", "\\u003c") ``` For defense in depth, also escape `>`, `&`, U+2028, and U+2029 where applicable. Alternatively, load the GeoJSON as a separate resource rather than embedding it in the generated page. Add regression tests that generate a page from GeoJSON properties containing: ```text ``` The test should verify that the generated HTML contains no literal `` sequence originating from the GeoJSON payload and that no injected element is created when the page is parsed. ]]>

T08 · Insecure Dependencies

Warning
Location
scripts/openlayers_scaffold.py:18
Finding

Mutable Third-Party JavaScript Loaded From a Public CDN

Content
View full analysis
``` ```javascript import Map from "https://cdn.jsdelivr.net/npm/ol@latest/Map.js"; import View from "https://cdn.jsdelivr.net/npm/ol@latest/View.js"; import TileLayer from "https://cdn.jsdelivr.net/npm/ol@latest/layer/Tile.js"; import OSM from "https://cdn.jsdelivr.net/npm/ol@latest/source/OSM.js"; import { fromLonLat } from "https://cdn.jsdelivr.net/npm/ol@latest/proj.js"; ``` The GeoJSON template uses the same mutable dependency pattern for its stylesheet and modules: ```javascript import Map from "https://cdn.jsdelivr.net/npm/ol@latest/Map.js"; import View from "https://cdn.jsdelivr.net/npm/ol@latest/View.js"; import TileLayer from "https://cdn.jsdelivr.net/npm/ol@latest/layer/Tile.js"; import VectorLayer from "https://cdn.jsdelivr.net/npm/ol@latest/layer/Vector.js"; import OSM from "https://cdn.jsdelivr.net/npm/ol@latest/source/OSM.js"; import VectorSource from "https://cdn.jsdelivr.net/npm/ol@latest/source/Vector.js"; import GeoJSON from "https://cdn.jsdelivr.net/npm/ol@latest/format/GeoJSON.js"; import Fill from "https://cdn.jsdelivr.net/npm/ol@latest/style/Fill.js"; import Stroke from "https://cdn.jsdelivr.net/npm/ol@latest/style/Stroke.js"; import Style from "https://cdn.jsdelivr.net/npm/ol@latest/style/Style.js"; import CircleStyle from "https://cdn.jsdelivr.net/npm/ol@latest/style/Circle.js"; import { fromLonLat } from "https://cdn.jsdelivr.net/npm/ol@latest/proj.js"; ``` ### Technical Analysis Every generated page retrieves and executes OpenLayers modules f ...[truncated 2090 chars]
Remediation
View remediation
``` ```javascript import Map from "https://cdn.jsdelivr.net/npm/ol@10.6.1/Map.js"; ``` Apply the exact version consistently to all imports. Do not use mutable selectors such as `latest`, broad version ranges, or floating tags. The preferred production design is to: 1. Declare OpenLayers at an exact version in the application's package manifest. 2. Commit and enforce a package-manager lockfile. 3. Download dependencies during a controlled build. 4. Bundle the required modules into locally served, immutable assets. 5. Review dependency updates before changing the pinned version. 6. Use automated dependency vulnerability and provenance checks. Where CDN delivery remains necessary, use immutable versioned URLs and integrity validation wherever the delivery format supports it. A strict Content Security Policy should also restrict scripts and connections to explicitly approved sources. Because integrity handling for a graph of direct ESM imports is limited, local bundling is safer than relying on numerous remote module imports. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (6)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
75% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · references/patterns.md (reported line 16)May include surrounding context.

md
- OpenLayers view coordinates are often in the view projection, not raw lon/lat.
- For display on the default web map, transform geographic coordinates with `fromLonLat([lng, lat])`.
- For GeoJSON reads, pass `dataProjection` for the source data and `featureProjection` for the map view when they differ.
- Do not assume every incoming dataset is WGS84 without checking context.

## Debugging Sequence

Vague Triggers

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

Line L003 says to use the skill for 'web GIS map implementation' and 'OpenLayers debugging' alongside more specific triggers. While some phrases are specific, 'web GIS map implementation' is broad enough to match many generic mapping tasks, which makes invocation boundaries less clear in a manifest-scoped trigger description.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
79% confidence
Finding

The script generates HTML that loads JavaScript, CSS, and map tiles from jsDelivr and OpenStreetMap, which causes network requests when the scaffold is opened. Although the file docstring says it generates local debugging scaffolds, there is no explicit user-facing warning in the CLI help or runtime output that the generated page will contact external services.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The minimal template sets <html lang="en">, which forces an English locale in the generated output. The skill does not provide any option to choose or override the language, and no justification for an English-only constraint is present.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The GeoJSON template also sets <html lang="en">, enforcing English in generated pages without user opt-in. No alternative locale selection or documented rationale is provided in this skill file.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.