Email the maintainer or open a private GitHub security advisory. Please do not open public issues for vulnerabilities.
Copilot Omni is a development-time orchestration layer for GitHub Copilot CLI sessions. It runs with the same privileges as the Copilot CLI process itself — which is the same as the user. It does not run services, network listeners, privileged daemons, or background agents.
- Protecting plugin-managed files (
.omni/config.json,plugin.json,AGENTS.md, …) from accidental modification by the LLM. - Defense-in-depth against obviously-dangerous shell commands (
sudo,rm -rf /,mkfs, fork bombs,dd if=/dev/zero). - Keeping the runtime footprint EDR-compatible: pure Python stdlib, no compiled artifacts, no third-party imports.
- Path-traversal protection for MCP tools that write to disk (
wiki_write). The shared_safe_identifier/_safe_child_pathhelpers inmcp/server.pyreject absolute paths,..segments, and non-alphanumeric run IDs. (The legacyartifact_writeandworkspacetools were removed in Phase-C C23; their traversal guards remain covered bytests/test_security.py::TestPathTraversalHelpers.) - Stdlib-only discipline enforced at CI-time by
scripts/verify_plugin_contract.py --check-stdlib-only-imports.
- Policy engine is advisory, not authoritative. Policy enforcement is via the MCP
policy_checktool, which does best-effort pattern matching on tool arguments. Skilled adversaries who control the LLM's input can craft commands that bypass substring and token matching (base64-piped payloads, unusual binary paths, command substitution). The engine raises the cost of accidental damage; it is not a sandbox. - No authentication. The MCP server listens on stdio, started by Copilot CLI under the invoking user. Anyone who can start
python3 mcp/server.pyon your machine can already read your files. - No crypto. The SQLite store at
$OMNI_HOME/omni.dbis plaintext. Don't put secrets inmemory_capture/wiki_writeunless you encrypt them upstream. - Supply chain of Copilot CLI itself is not validated by this plugin.
Three shipped profiles, selected via $OMNI_POLICY_PROFILE:
| Profile | Use case |
|---|---|
permissive |
Trusted solo dev, minimal guardrails |
standard (default) |
Corporate dev laptop with EDR |
strict |
Shared build host / heightened review |
Custom profiles live at <cwd>/.omni/policy-<name>.json. Project-level policy files are trusted on read. If you cd into a hostile repo that ships .omni/policy-standard.json with an empty deny_commands, you have disabled the project-scoped policy. The plugin-default policy still applies. We intentionally do not sign policy files; treat them the way you treat .envrc or package.json scripts.
- Base64 / eval / background subshell bypass deny-patterns:
printf '%s' c29 | base64 -d | shis not matched. The pre-tool hook does not evaluate shell-equivalent meanings; pattern-matching shell commands for intent is undecidable. - Unicode normalization on case-insensitive filesystems: path comparison is case-folded but not NFC/NFD normalized. A filename differing only in combining-character form may evade protected-path checks. On Linux this is not exploitable.
- Non-canonical tool names (tools the LLM invokes under a name we don't know about) are not gated. The hook matches against a known set:
shell,bash,write,edit,edit_file,multi_edit,multiedit,patch,apply_patch,str_replace_editor. New tool names added by future Copilot CLI versions will fail open until the plugin is updated.
- Use profile=
stricton CI and shared build hosts. - Run Copilot CLI without
--allow-allfor untrusted sessions; the plugin's subagent helper now defaults to interactive approval (opt in viaOMNI_SUBAGENT_ALLOW_ALL=1). - Consider writing a custom
.omni/policy-<you>.jsonthat extendsprotected_pathswith your repo's secret files and deploy configs. - Review
.omni/audit/tool-audit.logperiodically. Rotate and archive.
- 2026-04-16: initial v1.0.0 release.
policies/*.json— shipped profiles.mcp/server.pypolicy_checktool — runtime policy enforcement (MCP endpoint).tests/test_security.py— regression suite.