Back to skill

Security audit

Air France - KLM

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its flight-tracking purpose, but it should be reviewed because it handles API credentials with overly broad network scope and under-discloses a third-party aircraft lookup.

Review before installing. Use a dedicated, low-privilege AFKL API key, keep the credential state directory private, and consider hardening the HTTP helper to only send credentials to https://api.airfranceklm.com. Be aware that aircraft registration values may be sent to Planespotters and cached locally; remove or disable that enrichment if you want AFKL-only network traffic.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/afkl_http.mjs:37
Finding

AFKL Credentials Can Be Forwarded to an Arbitrary Network Destination

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (22)

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · README.md (reported line 35)May include surrounding context.

md
- Preferred: env vars `AFKL_API_KEY` (and optional `AFKL_API_SECRET`)
- Or files in your state dir (`CLAWDBOT_STATE_DIR` or `./state`):
  - `afkl_api_key.txt` (chmod 600)
  - `afkl_api_secret.txt` (chmod 600, optional)

2) Query flight status:
- Run: `node skills/airfrance-afkl/scripts/afkl_flightstatus_query.mjs --carrier AF --flight 7 --origin JFK --dep-date 2026-01-29`

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILL.md (reported line 19)May include surrounding context.

md
- Preferred: env vars `AFKL_API_KEY` (and optional `AFKL_API_SECRET`)
- Or files in your state dir (`CLAWDBOT_STATE_DIR` or `./state`):
  - `afkl_api_key.txt` (chmod 600)
  - `afkl_api_secret.txt` (chmod 600, optional)

2) Query flight status:
- Run: `node skills/airfrance-afkl/scripts/afkl_flightstatus_query.mjs --carrier AF --flight 7 --origin JFK --dep-date 2026-01-29`

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/afkl_http.mjs (reported line 28)May include surrounding context.

js
- Preferred: env vars `AFKL_API_KEY` (and optional `AFKL_API_SECRET`)
- Or files in your state dir (`CLAWDBOT_STATE_DIR` or `./state`):
  - `afkl_api_key.txt` (chmod 600)
  - `afkl_api_secret.txt` (chmod 600, optional)

2) Query flight status:
- Run: `node skills/airfrance-afkl/scripts/afkl_flightstatus_query.mjs --carrier AF --flight 7 --origin JFK --dep-date 2026-01-29`

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill explicitly relies on sensitive capabilities: reading credentials from environment variables or local files and making outbound network requests to a third-party API, but it does not declare any tool scope or permission boundaries. In an agent environment, this weakens least-privilege controls and can allow the skill to be run with broader access than necessary, increasing the blast radius if the implementation or surrounding tooling is compromised.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · SKILL.md (reported line 18)May include surrounding context.

md
2) Provide API credentials (do not print them):
- Preferred: env vars `AFKL_API_KEY` (and optional `AFKL_API_SECRET`)
- Or files in your state dir (`CLAWDBOT_STATE_DIR` or `./state`):
  - `afkl_api_key.txt` (chmod 600)
  - `afkl_api_secret.txt` (chmod 600, optional)

2) Query flight status:

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · SKILL.md (reported line 19)May include surrounding context.

md
2) Provide API credentials (do not print them):
- Preferred: env vars `AFKL_API_KEY` (and optional `AFKL_API_SECRET`)
- Or files in your state dir (`CLAWDBOT_STATE_DIR` or `./state`):
  - `afkl_api_key.txt` (chmod 600)
  - `afkl_api_secret.txt` (chmod 600, optional)

2) Query flight status:

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · references/fields.md (reported line 7)May include surrounding context.

md
## Identifiers
- `id` (e.g. `20260130+AF+0007`) — can be fetched directly:
  - `GET https://api.airfranceklm.com/opendata/flightstatus/{id}`

## Status
- `flightStatusPublic` / `flightStatusPublicLangTransl`

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/afkl_flightstatus_query.mjs (reported line 38)May include surrounding context.

js
## Identifiers
- `id` (e.g. `20260130+AF+0007`) — can be fetched directly:
  - `GET https://api.airfranceklm.com/opendata/flightstatus/{id}`

## Status
- `flightStatusPublic` / `flightStatusPublicLangTransl`

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/afkl_watch_flight.mjs (reported line 245)May include surrounding context.

js
## Identifiers
- `id` (e.g. `20260130+AF+0007`) — can be fetched directly:
  - `GET https://api.airfranceklm.com/opendata/flightstatus/{id}`

## Status
- `flightStatusPublic` / `flightStatusPublicLangTransl`

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/afkl_watch_flight.mjs (reported line 265)May include surrounding context.

js
## Identifiers
- `id` (e.g. `20260130+AF+0007`) — can be fetched directly:
  - `GET https://api.airfranceklm.com/opendata/flightstatus/{id}`

## Status
- `flightStatusPublic` / `flightStatusPublicLangTransl`

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The helper sends the API key and optional API secret as HTTP headers in a network request, which transmits sensitive authentication data off the local system. The file contains no confirmation, visible log, or warning to inform users that credentials will be sent to the provided URL.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The helper defaults to locale 'fr-FR', which drives user-visible weekday/date formatting in all generated notifications. This enforces a specific language/locale choice without offering configuration or documenting that the skill is region/language-specific.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The watcher expands beyond the stated Air France–KLM flight-status purpose by performing third-party aircraft intelligence lookups and persisting the results locally. This creates unnecessary data egress and enlarges the trust boundary to an unrelated external service, which increases privacy, integrity, and supply-chain risk without being essential to core flight tracking.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This code sends aircraft registration data to Planespotters, an additional external service not clearly justified by the skill's declared AF/KLM tracking role. Even if the transmitted data is limited, the undeclared integration can expose user-derived tracking context and makes results dependent on an unvetted third party.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
95% confidence
Finding

The code transmits aircraft registration identifiers to api.planespotters.net via a direct fetch call. This is dangerous because it exfiltrates operational data to a third party outside the skill's primary API scope, creating privacy and dependency risks if the service is compromised, misleading, or unauthorized for this workflow.

Content

Scanner excerpt · scripts/afkl_watch_flight.mjs (reported line 76)May include surrounding context.

js
try {
    for (const t of tried) {
      try {
        const url = `https://api.planespotters.net/pub/photos/reg/${encodeURIComponent(t)}`;
        const resp = await fetch(url, { headers: { 'accept': 'application/json' } });
        const text = await resp.text();
        const j = JSON.parse(text);

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The manifest says this skill tracks Air France flights using the Air France–KLM Open Data APIs for flight status, alerts, and related analysis. This script instead performs lookups against the public Planespotters API and builds aircraft metadata from that source, which is a materially different external dependency and behavior than the manifest describes.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
78% confidence
Finding

The script transmits user-provided aircraft registration data to a third-party public API outside the primary Air France–KLM data source. Even though the data is not highly sensitive, this expands the trust boundary, creates dependency on an unvetted external service, and may leak user query patterns or operational interests without explicit consent.

Content

Scanner excerpt · scripts/aircraft_intel.mjs (reported line 60)May include surrounding context.

js
let intel = { reg: primary };
try {
  // Planespotters API: https://api.planespotters.net/pub/photos/reg/{reg}
  for (const r of regs) {
    try {
      const url = `https://api.planespotters.net/pub/photos/reg/${encodeURIComponent(r)}`;

External Transmission

Medium
Category
Data Exfiltration
Confidence
87% confidence
Finding

The code constructs and performs a live HTTPS request to api.planespotters.net using the supplied registration, sending data outside the skill's stated AF/KLM API boundary. In this flight-monitoring context, that is more concerning because the skill is expected to operate on airline APIs, so undisclosed third-party lookups can expose usage patterns and weaken data-governance guarantees.

Content

Scanner excerpt · scripts/aircraft_intel.mjs (reported line 63)May include surrounding context.

js
// Planespotters API: https://api.planespotters.net/pub/photos/reg/{reg}
  for (const r of regs) {
    try {
      const url = `https://api.planespotters.net/pub/photos/reg/${encodeURIComponent(r)}`;
      const j = await fetchJson(url);
      const photo = (j.photos && j.photos[0]) || null;
      const ac = photo && photo.aircraft || null;

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The manifest describes using AFKL Open Data APIs for flight tracking, alerts, analysis, and polling, but does not mention secret discovery from process environment variables or filesystem state files. While this may be operationally useful, credential-loading from env and host-local files is an additional capability not justified by the end-user-facing purpose as written.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

This code loads AFKL API credentials from files in a state directory and from environment variables, which is access to sensitive credentials. There is no confirmation prompt, user-facing log, or warning in this file that credentials will be read from local storage.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
75% confidence
Finding

The code reads and writes a JSON cache file under a state directory or /tmp, introducing local persistence that is not mentioned in the manifest. While caching can be an implementation detail, persistent aircraft-intel storage is not obviously required from the narrow description centered on Air France flight-status API usage.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

The script sends the provided registration to a third-party public API and persists returned data to a local cache file. While comments describe the implementation, there is no user-visible notice, prompt, or runtime disclosure that input will be transmitted externally and stored on disk.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.env_credential_access, suspicious.potential_exfiltration

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/afkl_http.mjs:8

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/aircraft_intel.mjs:32

Sensitive-looking file read is paired with a network send.

Warn
Code
suspicious.potential_exfiltration
Location
scripts/afkl_http.mjs:31