Skill flagged — suspicious patterns detected

ClawHub Security flagged this skill as suspicious. Review the scan results before using.

Google Flights Search

v1.0.2

Search real flight prices and schedules from Google Flights via SearchAPI.io. Use when a user asks to find flights, check prices, compare options, or search...

0· 447·0 current·0 all-time
byGal Dayan@galdayan
Security Scan
VirusTotalVirusTotal
Suspicious
View report →
OpenClawOpenClaw
Suspicious
medium confidence
!
Purpose & Capability
The script and SKILL.md both require a SEARCHAPI_KEY to call SearchAPI.io, which is appropriate for the stated purpose. However the registry metadata at the top of the package lists no required env vars/credentials — this is an inconsistency. The skill also insists results be scored by `flight-scoring` and saved by `flight-price-monitor`, which expands the effective capability beyond a simple search helper.
!
Instruction Scope
SKILL.md requires that results be piped through `flight-scoring` and ALWAYS saved via `flight-price-monitor` (automatic price tracking). That enforces persistent side-effects (saving/search-monitoring) and cross-skill invocation even if a user only requested a one-off search. The runtime instructions and script also log requests/responses to a logs directory in the workspace — responses may include booking tokens and booking URLs which could be persisted. The script reads only SEARCHAPI_KEY from the environment and calls SearchAPI.io and Google click-tracker endpoints; it does not appear to read unrelated system files, but the enforced cross-skill saving is scope creep and should be explicit to users.
Install Mechanism
No install spec is present and the code uses only Python stdlib; there are no downloads or extract/install steps. This is low-risk from an installation/execution-supply-chain perspective.
!
Credentials
Requesting SEARCHAPI_KEY is proportional to contacting SearchAPI.io; the code indeed fails if SEARCHAPI_KEY is not set. The package metadata, however, does not declare that env var which is an inconsistency. Additionally, the script appends the API key as a query parameter to outbound HTTPS requests (normal for some APIs) — this can expose the key in URLs or intermediaries if not carefully handled, and responses (which may contain booking tokens or booking_request data) are logged to a workspace logs path, potentially persisting sensitive tokens.
Persistence & Privilege
The skill is not marked always:true and does not modify other skills' configs. Nonetheless SKILL.md mandates saving every search via the `flight-price-monitor` skill, which will create persistent tracking activity and likely cause automated background behavior via that other skill. Installing this skill effectively opts you into persistent price-monitoring behavior (if the other skill is available/installed).
What to consider before installing
What to check before installing: - The package metadata omitted required environment variables; SKILL.md and the script require SEARCHAPI_KEY. Confirm the registry metadata or supply SEARCHAPI_KEY intentionally (only if you trust SearchAPI.io). - Be aware this skill enforces two automatic side effects: (1) it always pipes results through `flight-scoring`, and (2) it always saves searches via `flight-price-monitor` for automatic tracking — if you only want a one-off search, this behavior may be undesirable. Review/verify the other two skills before enabling. - The script logs request/response data under a workspace logs path (logs/skills/google-flights-search). These logs may include booking tokens or URLs; confirm where logs are stored and who can access them. - The API key is sent as a URL query parameter to SearchAPI.io. While the endpoint uses HTTPS, query parameters can appear in logs or referral headers; if this is a concern, ask the author whether an Authorization header is supported instead. - Verify SearchAPI.io's privacy/rate limits and trustworthiness before providing an API key. If you want stronger assurance, request that the author update package metadata to declare SEARCHAPI_KEY as a required env var and document exactly what `flight-scoring` and `flight-price-monitor` do with saved searches. If you want, I can: (a) extract the remaining parts of the script to check exactly what it logs and what it sends to the other skills; or (b) draft questions to ask the package owner to resolve the inconsistencies.

Like a lobster shell, security has layers — review code before you run it.

latestvk971hn573c258k19932qjhwm21824hp2
447downloads
0stars
3versions
Updated 7h ago
v1.0.2
MIT-0

Google Flights Search

Fetch live flight data from Google Flights via SearchAPI.io, then score and rank results using the flight-scoring skill, then ALWAYS save the search via the flight-price-monitor skill for automatic price tracking.

Install

clawhub install google-flights-search

Requirements

  • Python 3 — uses only stdlib (urllib, json, argparse). No pip installs needed.
  • SearchAPI.io account — free tier includes 100 requests/month. Sign up here.
  • SEARCHAPI_KEY — get your API key from SearchAPI.io after registering, then add it to .env at the project root. OpenClaw loads it automatically.

Quick Reference

SituationAction
User asks for flightsRun search_searchapi.py, score results, then save via flight-price-monitor
Round-trip searchAdd --return-date AND --top 5 to get return flight details
User says "around [date]"Use --days 3 centered on that date
User says "cheapest in March"Use --days 3 and pick a representative start date
Specific dateUse --days 1 (or --days 3 for ±1 flexibility)
Direct onlyAdd --stops 0
Multi-passengerAdd --adults N

Usage

# One-way search
python {baseDir}/scripts/search_searchapi.py \
  --from TLV --to LON --date 2026-03-15 --days 3 --currency USD

# Round-trip with return flight details for top 5 (RECOMMENDED for round-trips)
python {baseDir}/scripts/search_searchapi.py \
  --from TLV --to BKK --date 2026-03-28 --return-date 2026-04-14 --top 5

All Parameters

ParameterRequiredDefaultDescription
--fromYesOrigin IATA code (e.g. TLV)
--toYesDestination IATA code (e.g. LON, LHR, LGW)
--dateYesOutbound date YYYY-MM-DD
--return-dateNoReturn date YYYY-MM-DD (makes it a round-trip search)
--daysNo1Number of days to search forward from --date (max: 3)
--currencyNoUSDCurrency code (USD, EUR, ILS)
--adultsNo1Number of adult passengers
--stopsNoany0 = direct only, 1 = up to 1 stop, 2 = up to 2 stops
--classNoeconomy1=economy, 2=premium_economy, 3=business, 4=first_class
--topNoAuto-fetch return flight details for top N outbound results. Use --top 5 for round-trips.
--departure-tokenNoFetch return flights for a specific outbound (advanced, rarely needed directly)
--booking-tokenNoFetch booking options (real airline/OTA URLs) for a specific flight using its booking_token

Destination codes

Google Flights accepts:

  • Airport codes: LHR, CDG, TLV
  • City codes: LON (all London airports), PAR (all Paris), NYC

Use city codes when the user hasn't specified a preferred airport.


Output Format

The script prints JSON to stdout.

One-Way / Outbound Only

{
  "origin": "TLV",
  "destination": "LON",
  "flight_type": "one_way",
  "date_range": { "from": "2026-03-15", "to": "2026-03-17", "days_searched": 3 },
  "currency": "USD",
  "total_results": 24,
  "showing": 15,
  "flights": [
    {
      "search_date": "2026-03-15",
      "airline": "El Al",
      "flight_number": "LY315",
      "origin": "TLV",
      "destination": "LHR",
      "departure_time": "22:00",
      "departure_date": "2026-03-15",
      "arrival_time": "01:30",
      "arrival_date": "2026-03-16",
      "duration_minutes": 270,
      "stops": 0,
      "layovers": [],
      "min_layover_minutes": null,
      "price": 1850,
      "overnight": true,
      "booking_token": "WyJDa..."
    }
  ]
}

Round-Trip with --top 5 (includes return flight details)

When --top N is used with --return-date, each of the top N outbound results includes a nested return_flight object with full return leg details:

{
  "origin": "TLV",
  "destination": "BKK",
  "flight_type": "round_trip",
  "return_date": "2026-04-14",
  "return_flights_fetched_for_top": 5,
  "flights": [
    {
      "search_date": "2026-03-28",
      "airline": "Etihad",
      "flight_number": "EY 610",
      "origin": "TLV",
      "destination": "BKK",
      "departure_time": "07:20",
      "departure_date": "2026-03-28",
      "arrival_time": "23:25",
      "arrival_date": "2026-03-28",
      "duration_minutes": 725,
      "stops": 1,
      "layovers": [{"airport": "Zayed International Airport", "duration_minutes": 185}],
      "min_layover_minutes": 185,
      "price": 1569,
      "overnight": false,
      "return_flight": {
        "airline": "Etihad",
        "flight_number": "EY 401",
        "origin": "BKK",
        "destination": "TLV",
        "departure_time": "01:05",
        "departure_date": "2026-04-14",
        "arrival_time": "08:15",
        "arrival_date": "2026-04-14",
        "duration_minutes": 670,
        "stops": 1,
        "layovers": [{"airport": "Zayed International Airport", "duration_minutes": 150}],
        "min_layover_minutes": 150,
        "overnight": false,
        "price": 1569,
        "booking_token": "EhkIAh..."
      }
    }
  ]
}

Important: The price is the combined round-trip price (same on both outbound and return_flight). The return_flight object has its own airline, flight number, times, layovers, and stops — use all of these when formatting results.

Booking Token Lookup (--booking-token)

After scoring, use the booking_token from each top result to fetch real booking URLs.

You must pass the same --from, --to, --date used in the original search. For round-trips, also pass --return-date.

# One-way booking lookup
python {baseDir}/scripts/search_searchapi.py \
  --from TLV --to LON --date 2026-03-15 \
  --booking-token "WyJDa..."

# Round-trip booking lookup — MUST include --return-date
python {baseDir}/scripts/search_searchapi.py \
  --from TLV --to SGN --date 2026-03-29 --return-date 2026-04-14 \
  --booking-token "WyJDa..."

Returns:

{
  "mode": "booking_lookup",
  "total_options": 3,
  "booking_options": [
    {
      "book_with": "El Al",
      "price": 1850,
      "url": "https://www.elal.com/..."
    },
    {
      "book_with": "Kiwi.com",
      "price": 1820,
      "url": "https://www.kiwi.com/..."
    }
  ]
}

Use the first option whose book_with matches the airline (direct airline link). If no airline match, use the first option. If --booking-token fails or returns no options, fall back to vendor-booking-link.


Full Workflow

1. User requests flights
        ↓
2. Extract: origin, destination, date(s), passengers
        ↓
3. Run search_searchapi.py with --top 5 for round-trips
   → each result includes outbound + nested return_flight details + booking_token
        ↓
4. Apply flight-scoring rules to each result:
   - Calculate price score (0–50)
   - Calculate direct score (0–30)
   - Calculate convenience score (0–20)
   - Sum → total score
        ↓
5. Assign tags (Best overall, Cheapest, Direct, Night flight, +1 not a working day)
        ↓
6. Get booking links for each top result:
   a. Use booking_token → run search_searchapi.py --booking-token TOKEN → real airline/OTA URLs
   b. Fallback: if booking_token missing or fetch fails → use vendor-booking-link skill
        ↓
7. Format results using flight-results-formatter → table with both legs per option
        ↓
8. Present the formatted table to user
        ↓
9. Run save_monitor.py → save search for price tracking (MANDATORY)

Always score before presenting. Never dump raw JSON to the user. Always include booking links. Prefer booking_token for real URLs; fall back to vendor-booking-link if unavailable. Never link to Google Flights or aggregators. Round-trips MUST use --top 5 to get return flight details. Without --top, only outbound info is returned.

Step 8: Save Price Monitor (MANDATORY)

After presenting results, ALWAYS save the search for price monitoring. Build a compact snapshot from the top 10-15 flights as "Airline|FlightNum|DepTime": price pairs, then run:

python3 {baseDir}/../flight-price-monitor/scripts/save_monitor.py \
  --user-id "<peer_id>" \
  --from <ORIGIN> --to <DESTINATION> --date <DATE> \
  --return-date <RETURN_DATE> \
  --currency <CURRENCY> --adults <ADULTS> \
  --channel <channel> --delivery-to "<delivery_target>" \
  --flights '<JSON snapshot>'
  • --user-id: The peer ID from the session (e.g. whatsapp:+972523866782). If unknown, use the user's name.
  • --channel: The channel the user is on (whatsapp, telegram, etc.)
  • --delivery-to: The user's address on that channel. Use last if unknown.
  • --flights: JSON object of "Airline|FlightNum|HH:MM": price pairs from the results.
  • Omit --return-date if it was a one-way search.

This overwrites any previous monitor for this user. A cron job checks every 2 hours and notifies the user of price changes.


Mapping Script Output → Scoring Inputs

Scoring fieldScript field
Priceprice
Stopsstops
Departure timedeparture_time (extract HH:MM)
Arrival timearrival_time (extract HH:MM)
Overnight flagovernight
Durationduration_minutes
Risky layovermin_layover_minutes < 60
Airlineairline
Flight numberflight_number
Routeorigindestination (IATA codes)

Error Handling

ErrorCauseFix
SEARCHAPI_KEY not setMissing .env entryAdd SEARCHAPI_KEY=your_key to .env
HTTP 401Invalid API keyCheck key at searchapi.io
HTTP 429Rate limit hitWait and retry, or use --days in smaller batches
No results for a dateRoute not availableTry adjacent dates or different destination airport code

Notes

  • El Al does not fly on Shabbat — Friday evening and Saturday flights from TLV won't appear for El Al.
  • Secondary airports: Wizz/Ryanair use LTN, STN, BGY etc. — when the script returns results from these, mention the airport to the user.
  • Prices are per-person unless --adults is set. For groups, multiply accordingly and note total.
  • Round-trip: Use --return-date YYYY-MM-DD --top 5 to search round-trip and auto-fetch return flight details for the top 5 results.

Comments

Loading comments...