T09 · Insecure Skill Coding Practices
- Location
SKILL.md:12- Finding
Hardcoded Writable TRMNL Webhook Credential
- Content
View full analysis
Vulnerability Details
File Location:
SKILL.md, lines 12–20
Vulnerability Type: Hardcoded secret / plaintext sensitive configuration
Risk Level: HighVulnerable Code
markdown - **Endpoint:** `https://trmnl.com/api/custom_plugins/0d9e7125-789d-46a6-9a51-070ac95364d8` - **Method:** POST - **Content-Type:** application/json ## How to Send a Message Use curl to POST a JSON payload with `merge_variables`: ```bash curl "https://trmnl.com/api/custom_plugins/0d9e7125-789d-46a6-9a51-070ac95364d8" \Technical Analysis
The skill embeds a device-specific, writable webhook URL directly in a tracked Markdown file. The UUID-like URL component functions as a bearer credential: possession of the complete endpoint is sufficient to submit content, with no separate authentication mechanism documented.
Anyone able to read the skill package, repository, archive, logs, or generated documentation can extract the endpoint and send arbitrary
merge_variablespayloads directly to the TRMNL service. Moving the same value into another tracked configuration file would not resolve the exposure; it must be revoked and replaced with a secret supplied at runtime.Attack Path
- An attacker obtains a copy of
SKILL.mdfrom the skill package or repository. - The attacker extracts the complete webhook endpoint from line 12 or line 20.
- The attacker submits an independent HTTP POST request containing attacker-controlled
title,text, and optionallyimagevalues:bash curl "https://trmnl.com/api/custom_plugins/REDACTED" \ -H "Content-Type: application/json" \ -X POST \ -d '{"merge_variables":{"title":"Urgent Notice","text":"Attacker-controlled content"}}' - The TRMNL service accepts the bearer webhook and updates the associated display content.
- The attacker can repeat requests to overwrite legitimate content or continuously disrupt display operation.
...[truncated 640 chars]
- An attacker obtains a copy of
- Remediation
View remediation
Remediation Suggestions
- Immediately revoke or rotate the exposed webhook because removing it from the current file does not invalidate copies in package or repository history.
- Remove the device-specific endpoint from
SKILL.md, examples, documentation, logs, and version-control history where feasible. - Require each operator to provide their own webhook through a protected runtime secret such as
TRMNL_WEBHOOK_URL. - Reference the secret without printing it:
bash test -n "$TRMNL_WEBHOOK_URL" || { echo "TRMNL_WEBHOOK_URL is not configured" >&2 exit 1 } curl --fail-with-body --silent --show-error \ "$TRMNL_WEBHOOK_URL" \ -H "Content-Type: application/json" \ -X POST \ --data-binary "$PAYLOAD" - Store the value in the deployment platform's secret manager rather than in source control or command examples. Restrict secret access to the minimum required runtime identity.
- If supported by the provider, apply endpoint rotation, rate limits, request signing, source restrictions, and least-privilege controls.
- Monitor the replacement webhook for unexpected request volume and unauthorized content changes.
- Add automated secret scanning and pre-commit checks to prevent credential-bearing webhook URLs from being committed again.
