terminal: move sanitization check to this package, unit test

This commit is contained in:
Mitchell Hashimoto
2023-11-04 11:19:25 -07:00
parent 65c9ba0a86
commit a38220eade
4 changed files with 30 additions and 21 deletions

View File

@ -2455,15 +2455,19 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool
/// Call this to complete a clipboard request sent to apprt. This should /// Call this to complete a clipboard request sent to apprt. This should
/// only be called once for each request. The data is immediately copied so /// only be called once for each request. The data is immediately copied so
/// it is safe to free the data after this call. /// it is safe to free the data after this call.
///
/// If "allow_unsafe" is false, then the data is checked for "safety" prior.
/// If unsafe data is detected, this will return error.UnsafePaste. Unsafe
/// data is defined as data that contains newlines, though this definition
/// may change later to detect other scenarios.
pub fn completeClipboardRequest( pub fn completeClipboardRequest(
self: *Surface, self: *Surface,
req: apprt.ClipboardRequest, req: apprt.ClipboardRequest,
data: []const u8, data: []const u8,
force: bool, // Dialog has been shown, and ignoring unsafe pastes. allow_unsafe: bool,
) !void { ) !void {
switch (req) { switch (req) {
.paste => try self.completeClipboardPaste(data, force), .paste => try self.completeClipboardPaste(data, allow_unsafe),
// TODO: Support sanaization for OSC 52
.osc_52 => |kind| try self.completeClipboardReadOSC52(data, kind), .osc_52 => |kind| try self.completeClipboardReadOSC52(data, kind),
} }
} }
@ -2489,22 +2493,22 @@ fn startClipboardRequest(
try self.rt_surface.clipboardRequest(loc, req); try self.rt_surface.clipboardRequest(loc, req);
} }
fn sanatizeClipboardPaste(data: []const u8) !void { fn completeClipboardPaste(
// Split into lines. self: *Surface,
var lines = std.mem.splitSequence(u8, data, "\n"); data: []const u8,
allow_unsafe: bool,
// If there's only one line no need to proceed. ) !void {
if (std.mem.eql(u8, lines.next().?, data)) return;
// Warning popup.
return error.UnsafePaste;
}
fn completeClipboardPaste(self: *Surface, data: []const u8, force: bool) !void {
if (data.len == 0) return; if (data.len == 0) return;
if (!force and self.config.clipboard_paste_protection) { // If we have paste protection enabled, we detect unsafe pastes and return
try sanatizeClipboardPaste(data); // an error. The error approach allows apprt to attempt to complete the paste
// before falling back to requesting confirmation.
if (self.config.clipboard_paste_protection and
!allow_unsafe and
!terminal.isSafePaste(data))
{
log.info("potentially unsafe paste detected, rejecting until confirmation", .{});
return error.UnsafePaste;
} }
const bracketed = bracketed: { const bracketed = bracketed: {

View File

@ -588,8 +588,8 @@ pub const Surface = struct {
}, },
}; };
// Complete our request // Complete our request. We always allow unsafe because we don't
// TODO: Support sanaization for GLFW (force: false) // want to deal with user confirmation in this runtime.
try self.core_surface.completeClipboardRequest(state, str, true); try self.core_surface.completeClipboardRequest(state, str, true);
} }

View File

@ -423,8 +423,11 @@ keybind: Keybinds = .{},
/// This does not affect data sent to the clipboard via "clipboard-write". /// This does not affect data sent to the clipboard via "clipboard-write".
@"clipboard-trim-trailing-spaces": bool = true, @"clipboard-trim-trailing-spaces": bool = true,
/// Creates a pop-up window when active, warning the user that they are pasting /// Require confirmation before pasting text that appears unsafe. This helps
/// contents that contains more than one line. This could be a "copy paste attack" /// prevent a "copy/paste attack" where a user may accidentally execute unsafe
/// commands by pasting text with newlines.
///
/// This currently only works on Linux (GTK).
@"clipboard-paste-protection": bool = true, @"clipboard-paste-protection": bool = true,
/// The total amount of bytes that can be used for image data (i.e. /// The total amount of bytes that can be used for image data (i.e.

View File

@ -1,5 +1,7 @@
const builtin = @import("builtin"); const builtin = @import("builtin");
pub usingnamespace @import("sanitize.zig");
const charsets = @import("charsets.zig"); const charsets = @import("charsets.zig");
const stream = @import("stream.zig"); const stream = @import("stream.zig");
const ansi = @import("ansi.zig"); const ansi = @import("ansi.zig");