Strip CR/LF/NUL from every outbound s2s line
Free-form trailing text (message bodies, kick reasons, topics, metadata) now passes through a single sanitizing choke-point in the serializer, so no such text can carry an embedded line break that would smuggle a second command onto the link. Line-based input closes the obvious path today, but sanitizing at the point of serialization removes the whole class regardless of where the text originated (federation, config, future non-line sources).
This commit is contained in:
parent
2fd5676ff2
commit
5d67133295
1 changed files with 20 additions and 2 deletions
|
|
@ -227,7 +227,7 @@ impl Protocol for InspIrcd {
|
|||
}
|
||||
|
||||
fn serialize(&mut self, action: &NetAction) -> Vec<String> {
|
||||
match action {
|
||||
let lines = match action {
|
||||
NetAction::Burst => vec![self.sourced(format!("BURST {}", self.ts))],
|
||||
NetAction::EndBurst => vec![self.sourced("ENDBURST".to_string())],
|
||||
NetAction::Pong { token, from } => {
|
||||
|
|
@ -321,7 +321,12 @@ impl Protocol for InspIrcd {
|
|||
NetAction::Raw(s) => vec![s.clone()],
|
||||
// Internal: the link layer handles these before serialization.
|
||||
NetAction::DeferRegister { .. } | NetAction::DeferPassword { .. } | NetAction::SendEmail { .. } => vec![],
|
||||
}
|
||||
};
|
||||
// A trailing parameter can carry free-form text (message bodies, kick
|
||||
// reasons, topics, metadata). Strip CR/LF/NUL at this single choke-point
|
||||
// so no such text — whatever its origin — can smuggle a second command
|
||||
// onto the s2s link.
|
||||
lines.into_iter().map(|l| l.replace(['\r', '\n', '\0'], "")).collect()
|
||||
}
|
||||
|
||||
fn sid(&self) -> &str {
|
||||
|
|
@ -467,6 +472,19 @@ mod tests {
|
|||
assert_eq!(lines, vec![":42S ENCAP 0IR CHGIDENT 0IRAAAAAB cool".to_string()]);
|
||||
}
|
||||
|
||||
// Free-form text with embedded line breaks must not smuggle a second line
|
||||
// onto the link: the serializer strips CR/LF/NUL from every outbound line.
|
||||
#[test]
|
||||
fn strips_crlf_from_trailing_text() {
|
||||
let lines = proto().serialize(&NetAction::Notice {
|
||||
from: "42SAAAAAA".into(),
|
||||
to: "0IRAAAAAB".into(),
|
||||
text: "hi\r\nKILL 0IRAAAAAB :pwned".into(),
|
||||
});
|
||||
assert_eq!(lines, vec![":42SAAAAAA NOTICE 0IRAAAAAB :hiKILL 0IRAAAAAB :pwned".to_string()]);
|
||||
assert!(!lines[0].contains('\n') && !lines[0].contains('\r'));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parses_ftopic_and_filters_own() {
|
||||
let ev = proto().parse(":0IRAAAAAB FTOPIC #chan 1783845132 1783845140 :Welcome all");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue