From 593392678f082052c66dde7c116ebff18a03e137 Mon Sep 17 00:00:00 2001 From: gmpassos Date: Thu, 4 Jun 2026 18:52:38 -0300 Subject: [PATCH 1/3] Add hash, compression, crypto, database and editor knowledge plugins Split single-stream compressors out of the archive plugin into a dedicated compression plugin, move hash/checksum tools out of the filesystem plugin into a hash plugin, and add new plugins for crypto, database and editor command classes. Adds the corresponding KnowledgeCategory values and registers/exports the new plugins. Co-Authored-By: Claude Opus 4.8 --- lib/command_shield.dart | 5 ++ .../knowledge/command_knowledge.dart | 17 ++++- .../knowledge/plugins/archive_knowledge.dart | 24 ++----- .../plugins/compression_knowledge.dart | 52 ++++++++++++++ .../knowledge/plugins/crypto_knowledge.dart | 69 +++++++++++++++++++ .../knowledge/plugins/database_knowledge.dart | 68 ++++++++++++++++++ .../knowledge/plugins/default_plugins.dart | 10 +++ .../knowledge/plugins/editor_knowledge.dart | 35 ++++++++++ .../plugins/filesystem_knowledge.dart | 4 -- .../knowledge/plugins/hash_knowledge.dart | 38 ++++++++++ .../capabilities/knowledge_base_test.dart | 37 ++++++++++ .../capabilities/knowledge_plugins_test.dart | 5 ++ 12 files changed, 340 insertions(+), 24 deletions(-) create mode 100644 lib/src/capabilities/knowledge/plugins/compression_knowledge.dart create mode 100644 lib/src/capabilities/knowledge/plugins/crypto_knowledge.dart create mode 100644 lib/src/capabilities/knowledge/plugins/database_knowledge.dart create mode 100644 lib/src/capabilities/knowledge/plugins/editor_knowledge.dart create mode 100644 lib/src/capabilities/knowledge/plugins/hash_knowledge.dart diff --git a/lib/command_shield.dart b/lib/command_shield.dart index 9c6249f..c87dad8 100644 --- a/lib/command_shield.dart +++ b/lib/command_shield.dart @@ -32,12 +32,17 @@ export 'src/capabilities/knowledge/command_knowledge.dart'; export 'src/capabilities/knowledge/command_knowledge_plugin.dart'; export 'src/capabilities/knowledge/command_knowledge_result.dart'; export 'src/capabilities/knowledge/plugins/archive_knowledge.dart'; +export 'src/capabilities/knowledge/plugins/compression_knowledge.dart'; export 'src/capabilities/knowledge/plugins/container_knowledge.dart'; +export 'src/capabilities/knowledge/plugins/crypto_knowledge.dart'; export 'src/capabilities/knowledge/plugins/dart_flutter_knowledge.dart'; +export 'src/capabilities/knowledge/plugins/database_knowledge.dart'; export 'src/capabilities/knowledge/plugins/default_plugins.dart'; +export 'src/capabilities/knowledge/plugins/editor_knowledge.dart'; export 'src/capabilities/knowledge/plugins/environment_knowledge.dart'; export 'src/capabilities/knowledge/plugins/filesystem_knowledge.dart'; export 'src/capabilities/knowledge/plugins/git_knowledge.dart'; +export 'src/capabilities/knowledge/plugins/hash_knowledge.dart'; export 'src/capabilities/knowledge/plugins/network_knowledge.dart'; export 'src/capabilities/knowledge/plugins/package_manager_knowledge.dart'; export 'src/capabilities/knowledge/plugins/process_knowledge.dart'; diff --git a/lib/src/capabilities/knowledge/command_knowledge.dart b/lib/src/capabilities/knowledge/command_knowledge.dart index 7283ffb..c62705f 100644 --- a/lib/src/capabilities/knowledge/command_knowledge.dart +++ b/lib/src/capabilities/knowledge/command_knowledge.dart @@ -15,9 +15,24 @@ enum KnowledgeCategory { /// Filesystem manipulation (`ls`, `cp`, `rm`, …). filesystem, - /// Archive and compression tools (`tar`, `zip`, `gzip`, …). + /// Archive and bundling tools (`tar`, `7z`, `cpio`, …). archive, + /// Single-stream compressors and zip tools (`gzip`, `zip`, `xz`, …). + compression, + + /// Checksum and digest tools (`md5sum`, `sha256sum`, `cksum`, …). + hash, + + /// Encryption, signing and encoding tools (`openssl`, `gpg`, `base64`, …). + crypto, + + /// Database clients and dump/restore tools (`psql`, `mysql`, `sqlite3`, …). + database, + + /// Interactive text editors (`vim`, `nano`, `emacs`, …). + editor, + /// Software package managers (`npm`, `pip`, `apt`, `brew`, …). packageManager, diff --git a/lib/src/capabilities/knowledge/plugins/archive_knowledge.dart b/lib/src/capabilities/knowledge/plugins/archive_knowledge.dart index 30426f2..d31458b 100644 --- a/lib/src/capabilities/knowledge/plugins/archive_knowledge.dart +++ b/lib/src/capabilities/knowledge/plugins/archive_knowledge.dart @@ -2,11 +2,12 @@ import '../../capability.dart'; import '../command_knowledge.dart'; import '../command_knowledge_plugin.dart'; -/// Knowledge about archive and compression tools. +/// Knowledge about archive and bundling tools. /// /// These both read inputs and write outputs, so they carry read + write /// filesystem capabilities; extraction-only or list-only modes are still -/// conservatively reported as read + write. +/// conservatively reported as read + write. Single-stream compressors live in +/// the compression plugin. final class ArchiveKnowledge implements CommandKnowledgePlugin { /// Creates the archive knowledge plugin. const ArchiveKnowledge(); @@ -16,26 +17,11 @@ final class ArchiveKnowledge implements CommandKnowledgePlugin { @override List get entries => [ - for (final tool in const [ - 'tar', - 'zip', - 'unzip', - 'gzip', - 'gunzip', - 'bzip2', - 'bunzip2', - 'xz', - 'unxz', - 'zstd', - '7z', - '7za', - 'compress', - 'uncompress', - ]) + for (final tool in const ['tar', '7z', '7za', 'cpio', 'ar', 'pax']) CommandKnowledge( executable: tool, category: KnowledgeCategory.archive, - description: 'Archive/compression tool (reads inputs, writes outputs).', + description: 'Archive/bundling tool (reads inputs, writes outputs).', baseCapabilities: const { CommandCapability.readFilesystem, CommandCapability.writeFilesystem, diff --git a/lib/src/capabilities/knowledge/plugins/compression_knowledge.dart b/lib/src/capabilities/knowledge/plugins/compression_knowledge.dart new file mode 100644 index 0000000..503fe72 --- /dev/null +++ b/lib/src/capabilities/knowledge/plugins/compression_knowledge.dart @@ -0,0 +1,52 @@ +import '../../capability.dart'; +import '../command_knowledge.dart'; +import '../command_knowledge_plugin.dart'; + +/// Knowledge about single-stream compressors and zip tools. +/// +/// These both read inputs and write outputs, so they carry read + write +/// filesystem capabilities; decompression-only or list-only modes are still +/// conservatively reported as read + write. +final class CompressionKnowledge implements CommandKnowledgePlugin { + /// Creates the compression knowledge plugin. + const CompressionKnowledge(); + + @override + String get name => 'compression'; + + @override + List get entries => [ + for (final tool in const [ + 'gzip', + 'gunzip', + 'zcat', + 'zip', + 'unzip', + 'bzip2', + 'bunzip2', + 'bzcat', + 'xz', + 'unxz', + 'xzcat', + 'zstd', + 'unzstd', + 'zstdcat', + 'lz4', + 'lzma', + 'unlzma', + 'compress', + 'uncompress', + 'brotli', + 'pigz', + ]) + CommandKnowledge( + executable: tool, + category: KnowledgeCategory.compression, + description: 'Compression tool (reads inputs, writes outputs).', + baseCapabilities: const { + CommandCapability.readFilesystem, + CommandCapability.writeFilesystem, + }, + ), + ]; +} diff --git a/lib/src/capabilities/knowledge/plugins/crypto_knowledge.dart b/lib/src/capabilities/knowledge/plugins/crypto_knowledge.dart new file mode 100644 index 0000000..54f89c4 --- /dev/null +++ b/lib/src/capabilities/knowledge/plugins/crypto_knowledge.dart @@ -0,0 +1,69 @@ +import '../../capability.dart'; +import '../command_knowledge.dart'; +import '../command_knowledge_plugin.dart'; +import 'knowledge_builders.dart'; + +/// Knowledge about encryption, signing and encoding tools. +final class CryptoKnowledge implements CommandKnowledgePlugin { + /// Creates the crypto knowledge plugin. + const CryptoKnowledge(); + + @override + String get name => 'crypto'; + + static const _crypto = KnowledgeCategory.crypto; + + @override + List get entries => [ + // openssl reads/writes files; the s_client/s_server/ocsp commands talk to + // the network. + const CommandKnowledge( + executable: 'openssl', + category: _crypto, + description: 'Cryptography toolkit (keys, certs, encryption, TLS).', + baseCapabilities: { + CommandCapability.readFilesystem, + CommandCapability.writeFilesystem, + }, + subcommands: [ + SubcommandRule( + {'s_client', 's_server', 'ocsp'}, + {CommandCapability.networkRead, CommandCapability.networkWrite}, + description: 'Opens a network connection to a TLS/OCSP endpoint.', + ), + ], + ), + + // gpg reads/writes files; keyserver operations talk to the network. + for (final g in const ['gpg', 'gpg2']) + CommandKnowledge( + executable: g, + category: _crypto, + description: 'OpenPGP encryption and signing tool.', + baseCapabilities: const { + CommandCapability.readFilesystem, + CommandCapability.writeFilesystem, + }, + argumentRules: const [ + ArgumentRule( + ExactFlag({ + '--recv-keys', + '--send-keys', + '--refresh-keys', + '--keyserver', + }), + {CommandCapability.networkRead, CommandCapability.networkWrite}, + description: 'Keyserver operations transfer keys over the network.', + ), + ], + ), + + // base64/base32 read an input file (or stdin) and write the result to + // stdout. + ...simpleEntries( + const ['base64', 'base32'], + _crypto, + const {CommandCapability.readFilesystem}, + ), + ]; +} diff --git a/lib/src/capabilities/knowledge/plugins/database_knowledge.dart b/lib/src/capabilities/knowledge/plugins/database_knowledge.dart new file mode 100644 index 0000000..507798c --- /dev/null +++ b/lib/src/capabilities/knowledge/plugins/database_knowledge.dart @@ -0,0 +1,68 @@ +import '../../capability.dart'; +import '../command_knowledge.dart'; +import '../command_knowledge_plugin.dart'; +import 'knowledge_builders.dart'; + +/// Knowledge about database clients and dump/restore tools. +final class DatabaseKnowledge implements CommandKnowledgePlugin { + /// Creates the database knowledge plugin. + const DatabaseKnowledge(); + + @override + String get name => 'database'; + + static const _db = KnowledgeCategory.database; + + @override + List get entries => [ + // --- network clients (connect to a database server) --- + ...simpleEntries( + const [ + 'psql', + 'mysql', + 'mariadb', + 'mongo', + 'mongosh', + 'redis-cli', + 'cqlsh', + 'influx', + ], + _db, + const {CommandCapability.networkRead, CommandCapability.networkWrite}, + ), + + // --- local file database --- + const CommandKnowledge( + executable: 'sqlite3', + category: _db, + description: 'Operates on a local SQLite database file.', + baseCapabilities: { + CommandCapability.readFilesystem, + CommandCapability.writeFilesystem, + }, + ), + + // --- dump tools: read from the server, write a dump file --- + for (final d in const ['pg_dump', 'mysqldump']) + CommandKnowledge( + executable: d, + category: _db, + description: 'Dumps a database to a file (reads server, writes file).', + baseCapabilities: const { + CommandCapability.networkRead, + CommandCapability.writeFilesystem, + }, + ), + + // --- restore tool: read a dump file, write to the server --- + const CommandKnowledge( + executable: 'pg_restore', + category: _db, + description: 'Restores a dump file into a database server.', + baseCapabilities: { + CommandCapability.readFilesystem, + CommandCapability.networkWrite, + }, + ), + ]; +} diff --git a/lib/src/capabilities/knowledge/plugins/default_plugins.dart b/lib/src/capabilities/knowledge/plugins/default_plugins.dart index 82f427d..a62c26d 100644 --- a/lib/src/capabilities/knowledge/plugins/default_plugins.dart +++ b/lib/src/capabilities/knowledge/plugins/default_plugins.dart @@ -1,10 +1,15 @@ import '../command_knowledge_plugin.dart'; import 'archive_knowledge.dart'; +import 'compression_knowledge.dart'; import 'container_knowledge.dart'; +import 'crypto_knowledge.dart'; import 'dart_flutter_knowledge.dart'; +import 'database_knowledge.dart'; +import 'editor_knowledge.dart'; import 'environment_knowledge.dart'; import 'filesystem_knowledge.dart'; import 'git_knowledge.dart'; +import 'hash_knowledge.dart'; import 'network_knowledge.dart'; import 'package_manager_knowledge.dart'; import 'process_knowledge.dart'; @@ -21,12 +26,17 @@ import 'windows_knowledge.dart'; const List defaultKnowledgePlugins = [ FilesystemKnowledge(), + HashKnowledge(), ArchiveKnowledge(), + CompressionKnowledge(), + CryptoKnowledge(), + EditorKnowledge(), ShellKnowledge(), EnvironmentKnowledge(), ProcessKnowledge(), SystemConfigKnowledge(), NetworkKnowledge(), + DatabaseKnowledge(), ContainerKnowledge(), PackageManagerKnowledge(), DartFlutterKnowledge(), diff --git a/lib/src/capabilities/knowledge/plugins/editor_knowledge.dart b/lib/src/capabilities/knowledge/plugins/editor_knowledge.dart new file mode 100644 index 0000000..730bcc1 --- /dev/null +++ b/lib/src/capabilities/knowledge/plugins/editor_knowledge.dart @@ -0,0 +1,35 @@ +import '../../capability.dart'; +import '../command_knowledge.dart'; +import '../command_knowledge_plugin.dart'; +import 'knowledge_builders.dart'; + +/// Knowledge about interactive text editors. +/// +/// Editors open files for reading and can write them back, so they carry +/// read + write filesystem capabilities. +final class EditorKnowledge implements CommandKnowledgePlugin { + /// Creates the editor knowledge plugin. + const EditorKnowledge(); + + @override + String get name => 'editor'; + + @override + List get entries => simpleEntries( + const [ + 'vim', + 'vi', + 'nvim', + 'vimdiff', + 'nano', + 'emacs', + 'ed', + 'ex', + 'pico', + 'joe', + 'micro', + ], + KnowledgeCategory.editor, + const {CommandCapability.readFilesystem, CommandCapability.writeFilesystem}, + ); +} diff --git a/lib/src/capabilities/knowledge/plugins/filesystem_knowledge.dart b/lib/src/capabilities/knowledge/plugins/filesystem_knowledge.dart index f711801..3b984b5 100644 --- a/lib/src/capabilities/knowledge/plugins/filesystem_knowledge.dart +++ b/lib/src/capabilities/knowledge/plugins/filesystem_knowledge.dart @@ -64,10 +64,6 @@ final class FilesystemKnowledge implements CommandKnowledgePlugin { 'nl', 'tac', 'strings', - 'md5sum', - 'sha256sum', - 'sha1sum', - 'cksum', ], _fs, const {CommandCapability.readFilesystem}, diff --git a/lib/src/capabilities/knowledge/plugins/hash_knowledge.dart b/lib/src/capabilities/knowledge/plugins/hash_knowledge.dart new file mode 100644 index 0000000..34a6866 --- /dev/null +++ b/lib/src/capabilities/knowledge/plugins/hash_knowledge.dart @@ -0,0 +1,38 @@ +import '../../capability.dart'; +import '../command_knowledge.dart'; +import '../command_knowledge_plugin.dart'; +import 'knowledge_builders.dart'; + +/// Knowledge about checksum and digest tools. +/// +/// These read file contents (or stdin) to compute a digest and print it; they +/// do not modify the files they hash, so they carry only the read capability. +final class HashKnowledge implements CommandKnowledgePlugin { + /// Creates the hash knowledge plugin. + const HashKnowledge(); + + @override + String get name => 'hash'; + + @override + List get entries => simpleEntries( + const [ + 'md5', + 'md5sum', + 'sha1', + 'sha1sum', + 'sha224sum', + 'sha256', + 'sha256sum', + 'sha384sum', + 'sha512sum', + 'shasum', + 'b2sum', + 'cksum', + 'sum', + 'get-filehash', + ], + KnowledgeCategory.hash, + const {CommandCapability.readFilesystem}, + ); +} diff --git a/test/unit/capabilities/knowledge_base_test.dart b/test/unit/capabilities/knowledge_base_test.dart index 5b9928c..da6e7aa 100644 --- a/test/unit/capabilities/knowledge_base_test.dart +++ b/test/unit/capabilities/knowledge_base_test.dart @@ -211,6 +211,43 @@ void main() { expect(c, contains(CommandCapability.writeFilesystem)); }); + test('md5sum reads the filesystem', () { + expect( + caps('md5sum', ['file']), + contains(CommandCapability.readFilesystem), + ); + }); + + test('gzip reads and writes the filesystem', () { + final c = caps('gzip', ['file']); + expect(c, contains(CommandCapability.readFilesystem)); + expect(c, contains(CommandCapability.writeFilesystem)); + }); + + test('openssl s_client uses the network', () { + final c = caps('openssl', ['s_client', '-connect', 'host:443']); + expect(c, contains(CommandCapability.networkRead)); + expect(c, contains(CommandCapability.networkWrite)); + }); + + test('psql uses the network', () { + final c = caps('psql', ['-h', 'db', '-c', 'select 1']); + expect(c, contains(CommandCapability.networkRead)); + expect(c, contains(CommandCapability.networkWrite)); + }); + + test('sqlite3 reads and writes a local database file', () { + final c = caps('sqlite3', ['db.sqlite']); + expect(c, contains(CommandCapability.readFilesystem)); + expect(c, contains(CommandCapability.writeFilesystem)); + }); + + test('vim reads and writes the filesystem', () { + final c = caps('vim', ['file']); + expect(c, contains(CommandCapability.readFilesystem)); + expect(c, contains(CommandCapability.writeFilesystem)); + }); + test('docker push writes to the network', () { expect( caps('docker', ['push', 'img']), diff --git a/test/unit/capabilities/knowledge_plugins_test.dart b/test/unit/capabilities/knowledge_plugins_test.dart index 3a2c52e..1f1d189 100644 --- a/test/unit/capabilities/knowledge_plugins_test.dart +++ b/test/unit/capabilities/knowledge_plugins_test.dart @@ -19,6 +19,11 @@ void main() { 'dart', 'git', 'icacls', + 'md5sum', + 'gzip', + 'openssl', + 'psql', + 'vim', ]) { expect(kb.knowledgeFor(exe), isNotNull, reason: '$exe should be known'); } From 295d44bc4d2ab28efd61ed2167690bd7ecb3744d Mon Sep 17 00:00:00 2001 From: gmpassos Date: Fri, 5 Jun 2026 01:30:54 -0300 Subject: [PATCH 2/3] v1.0.1 --- CHANGELOG.md | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a2ce09..9597fc8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## 2.0.0 +## 1.0.1 Plugin-based command knowledge base. diff --git a/pubspec.yaml b/pubspec.yaml index 482e3cf..9e4e983 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: >- Security-first command-line analysis: parse, normalize, classify, analyze and policy-validate shell commands into ALLOW / REVIEW / DENY decisions without ever executing them. Built for AI agents and sandboxed executors. -version: 2.0.0 +version: 1.0.1 homepage: https://github.com/OmnyGrid/command_shield repository: https://github.com/OmnyGrid/command_shield issue_tracker: https://github.com/OmnyGrid/command_shield/issues From 261d114f41c03d5340d85b4b4ebaba64c0d3e57e Mon Sep 17 00:00:00 2001 From: gmpassos Date: Fri, 5 Jun 2026 01:32:47 -0300 Subject: [PATCH 3/3] rm --- .claude/scheduled_tasks.lock | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .claude/scheduled_tasks.lock diff --git a/.claude/scheduled_tasks.lock b/.claude/scheduled_tasks.lock deleted file mode 100644 index 61d3bcb..0000000 --- a/.claude/scheduled_tasks.lock +++ /dev/null @@ -1 +0,0 @@ -{"sessionId":"f07e1029-6636-4e31-9cbe-f4a6bdf202fd","pid":28092,"procStart":"Thu Jun 4 18:49:13 2026","acquiredAt":1780600969029} \ No newline at end of file