T09 · Insecure Skill Coding Practices
- Location
SKILL.md:74- Finding
Timeplus Credentials and Data Transmitted over Plaintext HTTP
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill is a coherent Timeplus SQL guide, but it needs Review because it normalizes privileged database actions, plaintext credential use, external data sinks, and server-side package installs without enough safeguards.
Install only if you intend the agent to operate a real Timeplus environment. Use HTTPS/TLS, least-privilege accounts, avoid credentials in URLs or SQL definitions, require explicit approval before DROP/ALTER/DELETE/CREATE VIEW/CREATE ALERT/CREATE TASK/package-install actions, and review any webhook, Slack, S3, Kafka, or database sink so sensitive data is not sent to unapproved destinations.
SKILL.md:74Timeplus Credentials and Data Transmitted over Plaintext HTTP
references/Python_TABLE_FUNCTION.md:17Unpinned Server-Side Python Package Installation
references/SINKS.md:145Connector Secrets Embedded in Persistent SQL Definitions
The combined presence of inline cloud credentials, database passwords, and Slack/webhook endpoints strongly resembles an exfiltration-enabling pattern, even if presented as documentation. In an agent skill that can generate and execute data-moving SQL, these examples materially lower the barrier to sending sensitive records or using embedded secrets against external services.
ess = 'postgres:5432', user = 'postgres', password = 'secret', database = 'analytics', table = 'hourly_summaries';
---
## 4. Write to S3 / Object Storage (via External Table)
```sql
CREATE EXTERNAL TABLE IF NOT EXISTS s3_archive
SETTINGS
type = 's3',
url = 's3://my-bucket/timeplus/events/',
aws_access_key_id = 'AKIAIOSFODNN7EXAMPLE',
aws_secret_access_key = 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY',
format = 'Parquet';
For HTTP webhooks, use a remote UDF as the push mechanism:
-- Create a remote function that POSTs to your webhook
CREATE REMOTE FUNCTION send_alert(payload string)
RETURNS string
URL 'https://hooks.slack.com/services/xxx/yyy/zzz'
AUTH_METHOD 'none';
-- Call in a streaming query or view
SELECT send_alert(
concat('{"text":"Alert: device ', device_id, ' temp=', to_string(temperature), '"}')
)
FROM sensor_data
WHERE
The skill explicitly supports full DDL/DML execution, including CREATE, DROP, and INSERT, yet it provides no warning or guardrails around destructive operations. In an agent context, this increases the chance that a user prompt or model mistake could modify or destroy streams, views, or data without informed confirmation.
The skill instructs transmitting credentials and SQL payloads over plain HTTP using basic authentication, without warning that credentials and data may be exposed in transit. If used on untrusted networks, an attacker could intercept database credentials, queries, and returned data.
This example sends arbitrary SQL and database credentials to the Timeplus server over plain HTTP via curl basic auth. That exposes both credentials and potentially sensitive query contents to interception or modification if the network path is not trusted.
# Standard pattern — pipe SQL into curl
echo "YOUR SQL HERE" | curl "http://${TIMEPLUS_HOST}:8123/" \
-u "${TIMEPLUS_USER}:${TIMEPLUS_PASSWORD}" \
--data-binary @-
The create-stream example transmits authenticated administrative SQL over plain HTTP. Because DDL changes affect database structure, interception or tampering could lead to unauthorized schema changes or credential disclosure.
temperature float32,
ts datetime64(3, 'UTC') DEFAULT now64(3, 'UTC')
) SETTINGS logstore_retention_ms=86400000" |
curl "http://${TIMEPLUS_HOST}:8123/"
-u "${TIMEPLUS_USER}:${TIMEPLUS_PASSWORD}"
--data-binary @-
This historical query example sends credentials and may retrieve sensitive data over an unencrypted HTTP connection. Query results and authentication data could be exposed to passive monitoring or man-in-the-middle attacks.
Historical query with JSON output:
echo "SELECT * FROM table(sensor_data) LIMIT 10" | \
curl "http://${TIMEPLUS_HOST}:8123/?default_format=JSONEachRow" \
-u "${TIMEPLUS_USER}:${TIMEPLUS_PASSWORD}" \
--data-binary @-
The insert example performs authenticated data modification over plain HTTP, exposing credentials and inserted records in transit. An attacker on the network could capture or alter the request, causing unauthorized data injection or corruption.
Insert data:
echo "INSERT INTO sensor_data (device_id, temperature) VALUES ('dev-1', 23.5), ('dev-2', 18.2)" | \
curl "http://${TIMEPLUS_HOST}:8123/" \
-u "${TIMEPLUS_USER}:${TIMEPLUS_PASSWORD}" \
--data-binary @-
This pattern demonstrates authenticated stream creation over plain HTTP, which exposes both credentials and DDL statements. In an agent-driven workflow, repeated insecure examples normalize unsafe transport for privileged operations.
product string,
amount float32,
region string
)" | curl "http://${TIMEPLUS_HOST}:8123/" \
-u "${TIMEPLUS_USER}:${TIMEPLUS_PASSWORD}" \
--data-binary @-
This example inserts data over plain HTTP using basic authentication, creating risk of credential leakage and in-transit tampering. Because it modifies state, exploitation could directly affect data integrity.
# 2. Insert data
echo "INSERT INTO orders VALUES ('o-1','Widget',19.99,'US'), ('o-2','Gadget',49.99,'EU')" | \
curl "http://${TIMEPLUS_HOST}:8123/" \
-u "${TIMEPLUS_USER}:${TIMEPLUS_PASSWORD}" \
--data-binary @-
This query example may return sensitive business data and sends credentials over unencrypted HTTP. Anyone able to observe the traffic could capture both the authentication token and the returned analytics output.
echo "SELECT region, sum(amount) FROM table(orders) GROUP BY region" |
curl "http://${TIMEPLUS_HOST}:8123/?default_format=JSONEachRow"
-u "${TIMEPLUS_USER}:${TIMEPLUS_PASSWORD}"
--data-binary @-
The streaming aggregation example authenticates over plain HTTP and may run long-lived queries, increasing exposure time for interception. Long-running insecure sessions can leak credentials and operational data over an extended period.
FROM tumble(orders, 1m)
GROUP BY window_start, region
EMIT AFTER WATERMARK AND DELAY 5s" |
curl "http://${TIMEPLUS_HOST}:8123/"
-u "${TIMEPLUS_USER}:${TIMEPLUS_PASSWORD}"
--data-binary @-
This materialized view creation example performs privileged DDL over plain HTTP, making schema and pipeline changes vulnerable to interception or manipulation. Compromise here could alter downstream analytics behavior or persist malicious transformations.
SELECT window_start, region, sum(amount) AS total
FROM tumble(orders, 5m)
GROUP BY window_start, region" |
curl "http://${TIMEPLUS_HOST}:8123/"
-u "${TIMEPLUS_USER}:${TIMEPLUS_PASSWORD}"
--data-binary @-
Even though this example creates a random test stream, it still sends authenticated DDL over plain HTTP. The insecure transport issue remains regardless of whether the target object is production or test data.
temperature float32 DEFAULT 20 + (rand() % 30),
status string DEFAULT ['ok','warn','error'][rand() % 3 + 1]
) SETTINGS eps=5" |
curl "http://${TIMEPLUS_HOST}:8123/"
-u "${TIMEPLUS_USER}:${TIMEPLUS_PASSWORD}"
--data-binary @-
The describe-stream example transmits credentials and metadata requests over plain HTTP. Schema metadata can still be sensitive, and exposure of credentials enables broader unauthorized access.
Inspect a stream:
echo "DESCRIBE sensor_data" | curl "http://${TIMEPLUS_HOST}:8123/" \
-u "${TIMEPLUS_USER}:${TIMEPLUS_PASSWORD}" \
--data-binary @-
Listing all streams over unencrypted HTTP reveals environment structure and uses basic auth in transit. This aids reconnaissance and can expose credentials to an attacker monitoring network traffic.
List all streams:
echo "SHOW STREAMS" | curl "http://${TIMEPLUS_HOST}:8123/" \
-u "${TIMEPLUS_USER}:${TIMEPLUS_PASSWORD}" \
--data-binary @-
The explain-query example still authenticates over plain HTTP, exposing credentials and internal query plan details. Query plans can reveal schema, functions, and processing logic useful to an attacker.
Explain a query:
echo "EXPLAIN SELECT * FROM tumble(sensor_data, 1m) GROUP BY window_start" | \
curl "http://${TIMEPLUS_HOST}:8123/" \
-u "${TIMEPLUS_USER}:${TIMEPLUS_PASSWORD}" \
--data-binary @-
This markdown file describes sending alert actions to Slack, Webhook, and Email, and later includes a concrete Slack webhook example. The document does not provide a user-facing warning that alert contents may leave the system and be sent to third-party services, which is relevant to privacy and system-integrity awareness.
The Python UDF performs an outbound HTTP POST to a Slack webhook, transmitting event-derived content to an external endpoint. In a skill that helps users build executable alerts and UDFs, this is more dangerous than passive documentation because it provides ready-to-run exfiltration behavior and includes a hardcoded webhook pattern that may encourage poor secret management.
def send_star_events_to_slack(value):
for github_id in value:
requests.post(
"https://hooks.slack.com/services/T123/B456/other_id",
data=json.dumps({
"text": f"New 🌟 for Timeplus Proton from https://github.com/{github_id}"
The example contains a concrete requests.post to a Slack webhook, which demonstrates sending alert-derived data to an external service without an explicit warning about data egress, secret handling, or payload sensitivity. In this skill's context, users are encouraged to execute SQL/UDF patterns directly, so a copy-pasted example could unintentionally exfiltrate production event data or normalize embedding webhook secrets in code.
The documentation shows authenticated requests over plain HTTP and includes examples that place credentials directly in URLs or command lines. This is dangerous because credentials can be exposed via shell history, process lists, logs, proxies, and network interception, especially since this skill is specifically designed to execute live ingestion against a real service.
This example transmits authenticated data to a remote service using plain HTTP on port 8123. Because the skill context explicitly supports executing these commands against configured hosts, the risk is more concrete: credentials and ingested data may be intercepted in transit or captured from command invocation metadata.
Via curl:
echo "INSERT INTO sensor_data (device_id, temperature) VALUES ('dev-1', 22.0)" | \
curl "http://${TIMEPLUS_HOST}:8123/" \
-u "${TIMEPLUS_USER}:${TIMEPLUS_PASSWORD}" \
--data-binary @-
The examples for Kafka, Timeplus, ClickHouse, MySQL, and PostgreSQL show inline usernames and passwords in SQL definitions. Even as placeholders, this normalizes insecure secret handling and increases the chance users will copy real credentials into files, prompts, version control, or query logs in an execution-oriented skill.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
from datetime import datetime
def fetch_prices():
resp = requests.get('https://api.example.com/prices').json()
rows = []
for item in resp:
rows.append((item['symbol'], item['price'], datetime.utcnow()))
The guide demonstrates Python table functions that send or receive data from external HTTP/WebSocket endpoints but does not warn users that stream contents may leave the Timeplus environment. In a skill that helps users generate executable SQL and embedded Python, omission of disclosure, destination validation, and data-handling cautions can lead to unintentional exfiltration of sensitive or regulated data.
This duplicate finding points to the same requests.post(..., json=...) sink behavior: exporting streamed data to an external service. Even though the code is illustrative, the skill's purpose is operational SQL execution with embedded Python, which makes example-based exfiltration patterns materially more risky than passive documentation.
def send_to_webhook(event_type, payload):
for etype, body in zip(event_type, payload):
requests.post(
'https://hooks.example.com/ingest',
json={'type': etype, 'data': body}
)
Detected: suspicious.exposed_secret_literal