Birdfolio
Analysis
Birdfolio mostly matches its bird-tracking purpose, but it stores data externally and has a card-rendering path that can run untrusted card content, so it should be reviewed before installing.
Findings (5)
Artifact-based informational review of SKILL.md, metadata, install specs, static scan signals, and capability signals. ClawScan does not execute the skill or run runtime probes.
Checks for instructions or behavior that redirect the agent, misuse tools, execute unexpected code, cascade across systems, exploit user trust, or continue outside the intended task.
"{{COMMON_NAME}}": args.species, ... "{{FUN_FACT}}": args.fun_fact, ... card_html = card_html.replace(key, value)User- and search-derived values are inserted into generated HTML by raw string replacement; the included screenshot flow renders these card files in Chromium, so malicious HTML or script content could become active during card generation.
use `exec` to find the most recently downloaded file in OpenClaw's temp/media folder ... Save the photo to `birdfolio/birds/{slug}-{timestamp}.jpg`The fallback photo-location instruction is purpose-aligned, but selecting the most recent media file is less precise than using the explicit attachment path.
Source: unknown; Homepage: none; No install spec — this is an instruction-only skill.
The artifacts provide limited provenance information even though the skill includes executable helper scripts and external-service integrations.
Checks whether tool use, credentials, dependencies, identity, account access, or inter-agent boundaries are broader than the stated purpose.
with open(secrets_path) as f: cfg = json.load(f) ... aws_access_key_id=cfg["access_key_id"], aws_secret_access_key=cfg["secret_access_key"] ... s3.put_object(
The optional upload helper reads Cloudflare R2 credentials from a local secrets file and can publish card PNGs, while registry metadata declares no credentials.
Checks for exposed credentials, poisoned memory or context, unclear communication boundaries, or sensitive data that could leave the user's control.
api_post(api_url, f"/users/{telegram_id}/sightings", { "common_name": args.species, ... "region": args.region, ... })Sightings are sent to an external API keyed by the locally stored Telegram ID, which is consistent with the stated tracking purpose but means birding data leaves the local workspace.
