Skip to content

Commit 36ec05f

Browse files
committed
fix(logging): avoid raw parser input in diagnostics
Previously, malformed GraphQL chunk-size errors included untrusted request data, and no regression test ensured that unclassified Network Activity failures did not push raw parser messages to the gateway. Now, GraphQL chunk-size errors omit the untrusted token, and the log-push regression test verifies that raw parser messages remain suppressed. Signed-off-by: Kris Hicks <khicks@nvidia.com>
1 parent cb6e88a commit 36ec05f

2 files changed

Lines changed: 43 additions & 1 deletion

File tree

crates/openshell-supervisor-network/src/l7/graphql.rs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,7 @@ async fn read_chunked_body_for_inspection<C: AsyncRead + Unpin>(
498498
.unwrap_or_default();
499499
let chunk_size = usize::from_str_radix(size_token, 16)
500500
.into_diagnostic()
501-
.map_err(|_| miette!("Invalid GraphQL chunk size token: {size_token:?}"))?;
501+
.map_err(|_| miette!("Invalid GraphQL chunk size token"))?;
502502
pos = size_line_end + 2;
503503

504504
if decoded.len().saturating_add(chunk_size) > max_body_bytes {
@@ -734,6 +734,31 @@ mod tests {
734734
assert!(req.raw_header.ends_with(body));
735735
}
736736

737+
#[tokio::test]
738+
async fn invalid_chunk_size_does_not_echo_request_data() {
739+
let sentinel = "graphql-chunk-secret";
740+
let mut req = L7Request {
741+
action: "POST".to_string(),
742+
target: "/graphql".to_string(),
743+
query_params: HashMap::new(),
744+
raw_header: format!(
745+
"POST /graphql HTTP/1.1\r\nHost: example.com\r\nTransfer-Encoding: chunked\r\n\r\n{sentinel}\r\n"
746+
)
747+
.into_bytes(),
748+
body_length: BodyLength::Chunked,
749+
};
750+
let error =
751+
inspect_graphql_request(&mut tokio::io::empty(), &mut req, DEFAULT_MAX_BODY_BYTES)
752+
.await
753+
.expect_err("invalid chunk size must be rejected");
754+
assert!(
755+
error
756+
.to_string()
757+
.contains("Invalid GraphQL chunk size token")
758+
);
759+
assert!(!error.to_string().contains(sentinel));
760+
}
761+
737762
#[tokio::test]
738763
async fn absolute_form_chunked_graphql_post_classifies_after_inspection() {
739764
let body = br#"{"query":"query Viewer { viewer { login } }"}"#;

crates/openshell-supervisor-process/src/log_push.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,23 @@ mod tests {
378378
assert!(line.event_time.is_some());
379379
}
380380

381+
#[test]
382+
fn unclassified_network_failures_do_not_push_raw_messages() {
383+
let sentinel = "raw-parser-secret";
384+
let event = NetworkActivityBuilder::new(&ocsf_ctx())
385+
.activity(ActivityId::Fail)
386+
.severity(SeverityId::Medium)
387+
.status(StatusId::Failure)
388+
.dst_endpoint(Endpoint::from_domain("example.com", 443))
389+
.message(format!("parser failed: {sentinel}"))
390+
.build();
391+
392+
let lines = capture(16, || ocsf_emit!(event));
393+
394+
assert_eq!(lines.len(), 1);
395+
assert!(!lines[0].message.contains(sentinel), "{:?}", lines[0]);
396+
}
397+
381398
#[test]
382399
fn non_ocsf_events_use_visitor_extraction() {
383400
let lines = capture(16, || {

0 commit comments

Comments
 (0)