Duansg commented on PR #4259:
URL: https://github.com/apache/hertzbeat/pull/4259#issuecomment-5232440193

   Thanks for tracking this down — I reproduced the issue and the direction is 
right. metric and table are interpolated into "%s" with no charset check, a " 
closes the identifier, and any payload without a . gets past the controller's 
three-segment split. replace("'", "\\'") is genuinely wrong for QuestDB (ANSI 
quote doubling, backslash is not an escape). The endpoint is reachable by the 
guest role (sureness.yml:31), so this is worth fixing.
   
   A few things I'd like to resolve before this lands.
   
   1. This fixes the least-exposed of four storages with the same pattern. 
TDengine (TdEngineDataStorage:367) and InfluxDB (InfluxdbDataStorage:255) 
interpolate history — a raw @RequestParam — straight into the SQL, with no 
equivalent of QuestDB's getDateAdd() parsing. InfluxDB doesn't even have the 
(broken) quote escaping for instanceValue. IoTDB has the same shape. Merging 
this as-is means an operator on TDengine or InfluxDB has a larger injection 
surface than the one we just closed.
   
   Two options: extend this PR to tdengine/influxdb/iotdb, or do the identifier 
and range validation once in MetricsDataServiceImpl — where all four storages 
converge — and keep only escapeStringLiteral() here, since quote escaping is 
the one genuinely dialect-specific piece that can't move up. Either way, could 
we open a tracking issue for the remaining storages? I'd rather not have this 
marked "fixed" while three of them stay open.
   
   2. The read-side allowlist is narrower than what the write side can produce. 
saveData() writes cell.getField().getName() verbatim as a column name, and 
verifyDefineAppContent() applies no charset validation to field names — we ship 
heap.memory.used (app-seatunnel.yml) and rocksdb.backup.read.bytes 
(app-nebula_graph.yml) today. The REST path won't regress because the 
three-segment split already rejects dotted names, but hertzbeat-ai's 
MetricsToolsImpl:172 calls the service directly and its fieldParameter is 
required = false, so it can be null or dotted. As a rule, a read-side validator 
shouldn't be stricter than the writer — otherwise some stored columns become 
unreadable by construction. Either constrain column names in saveData() too, or 
widen the pattern to at least . and /.
   
   3. Prefer normalizing table over validating it. The folding in 
generateTable() is conditional:
   
   if (instance.contains(".") || instance.contains(":") || 
instance.contains("["))
   
   An instance like a]b skips the branch entirely, keeps the ], and gets 
rejected by the new check. Dropping the if and folding unconditionally (or 
replacing anything outside the charset) makes the table slot non-injectable by 
construction and removes the need for validateIdentifier(table, ...). Note that 
a full-charset normalization would change existing table names, so that part 
needs a compatibility call. Keeping metric as reject-only is correct — it's a 
column name and must match exactly.
   
   4. Tests. The module already has TdEngineDataStorageTest, 
GreptimeDbDataStorageTest, VictoriaMetricsDataStorageTest. Making the two new 
methods package-private and adding four cases would lock this in: an identifier 
that closes the quoting is rejected; what generateTable actually produces still 
passes (127.0.0.1:8080, [::1]:8080, hyphenated hostnames); it's → it''s; null 
metric.
   
   Minor:
   - QUERY_HISTORY_SQL_WITH_INSTANCE (line 70) has no references anywhere and 
carries the same unescaped '%s' — worth deleting while we're here.
   - The IDENTIFIER constant sits between methods around line 370 while the 
other constants are at the top of the class. Checkstyle has no DeclarationOrder 
module so CI is fine, just a readability nit.
   - Unrelated, possibly worth its own issue: getDateAdd() only handles 
d/h/m/s, but the chart buttons send 1W/4W/12W, which throws on QuestDB.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to