diff --git a/src/openhuman/config/schema/autonomy.rs b/src/openhuman/config/schema/autonomy.rs index 732ec32d1..49c08093c 100644 --- a/src/openhuman/config/schema/autonomy.rs +++ b/src/openhuman/config/schema/autonomy.rs @@ -57,6 +57,11 @@ fn default_allowed_commands() -> Vec { "wc".into(), "head".into(), "tail".into(), + "dir".into(), + "type".into(), + "where".into(), + "findstr".into(), + "more".into(), ] } diff --git a/src/openhuman/security/policy.rs b/src/openhuman/security/policy.rs index 31b8c3895..3431a548e 100644 --- a/src/openhuman/security/policy.rs +++ b/src/openhuman/security/policy.rs @@ -120,6 +120,13 @@ impl Default for SecurityPolicy { "head".into(), "tail".into(), "date".into(), + // Windows read-only equivalents for the same basic + // inspection workflows as ls/cat/grep/which. + "dir".into(), + "type".into(), + "where".into(), + "findstr".into(), + "more".into(), ], forbidden_paths: vec![ // System directories (blocked even when workspace_only=false) diff --git a/src/openhuman/security/policy_tests.rs b/src/openhuman/security/policy_tests.rs index a8d890931..690338287 100644 --- a/src/openhuman/security/policy_tests.rs +++ b/src/openhuman/security/policy_tests.rs @@ -92,6 +92,42 @@ fn allowed_commands_basic() { assert!(p.is_command_allowed("date")); } +#[test] +fn allowed_commands_include_windows_read_equivalents() { + let p = default_policy(); + for command in [ + "dir", + "type README.md", + "where node", + "findstr pattern file.txt", + "more README.md", + ] { + assert!( + p.is_command_allowed(command), + "default policy should allow Windows read-only command: {command}" + ); + } +} + +#[test] +fn config_default_policy_includes_windows_read_equivalents() { + let cfg = crate::openhuman::config::AutonomyConfig::default(); + let p = SecurityPolicy::from_config(&cfg, std::path::Path::new(".")); + for command in [ + "dir", + "type README.md", + "where node", + "findstr pattern file.txt", + "more README.md", + ] { + assert!( + p.is_command_allowed(command), + "config-derived policy should allow Windows read-only command: {command}" + ); + } + assert!(!p.is_command_allowed("date 2026-05-21")); +} + #[test] fn blocked_commands_basic() { let p = default_policy();