Skip to content

Commit e2f3477

Browse files
lpcoxCopilot
andcommitted
cleanup: remove guard CLI flags, auto-detect DIFC from policies
Remove --enable-guards, --enable-config-extensions, --session-secrecy, and --session-integrity CLI flags. Guards are now auto-enabled when an allow-only policy is detected in the configuration. Changes: - Remove EnableDIFC field from config.Config - Remove SessionConfig struct and session label parsing - Remove enableDIFC, enableConfigExt, sessionSecrecy, sessionIntegrity flag variables and their env var defaults - Auto-detect DIFC in NewUnified() after guard registration: enabled when any non-noop guard or global policy override is present - Add HasNonNoopGuard() to guard.Registry for auto-detection - Move guards status logging into NewUnified() (before backend launch) - Always skip strict JSON schema validation for extension fields - Change requireGuardPolicyIfGuardEnabled to warn+noop fallback instead of fatal error - Fix flaky integration tests: replace hardcoded ports with dynamic allocation via getFreePort(t) - Update guard-policies docs to use canonical allow-only format - Update scripts to remove all references to removed flags - Update DIFC_RULES.md, config.example.toml, OVERVIEW.md Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 188786c commit e2f3477

24 files changed

Lines changed: 176 additions & 910 deletions

README.md

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ For the complete JSON configuration specification with all validation rules, see
132132
"EXPANDED_VAR": "${MY_HOME}/config"
133133
},
134134
"guard-policies": {
135-
"github": {
135+
"allow-only": {
136136
"repos": ["github/gh-aw-mcpg", "github/gh-aw"],
137137
"min-integrity": "unapproved"
138138
}
@@ -189,12 +189,21 @@ For the complete JSON configuration specification with all validation rules, see
189189
- **`url`** (required for http): HTTP endpoint URL for `type: "http"` servers
190190

191191
- **`guard-policies`** (optional): Guard policies for access control at the MCP gateway level
192-
- Structure is server-specific and depends on the MCP server implementation
192+
- Uses the `"allow-only"` policy format to restrict which repositories a guard allows
193193
- For **GitHub MCP server**, controls repository access with the following structure:
194+
```json
195+
"guard-policies": {
196+
"allow-only": {
197+
"repos": ["github/gh-aw-mcpg", "github/gh-aw"],
198+
"min-integrity": "unapproved"
199+
}
200+
}
201+
```
202+
TOML equivalent:
194203
```toml
195-
[servers.github.guard_policies.github]
196-
repos = ["github/gh-aw-mcpg", "github/gh-aw"] # Repository patterns
197-
min-integrity = "unapproved" # Minimum integrity level
204+
[servers.github.guard_policies.allow-only]
205+
repos = ["github/gh-aw-mcpg", "github/gh-aw"]
206+
min-integrity = "unapproved"
198207
```
199208
- **`repos`**: Repository access scope
200209
- `"all"` - All repositories accessible by the token

config.example.toml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ GITHUB_PERSONAL_ACCESS_TOKEN = "" # Pass through from host
7272
# Optional: Guard policies for access control at the MCP gateway level
7373
# The structure is server-specific. For GitHub MCP server, this controls repository access.
7474
# Example: Restrict access to specific GitHub organization and repositories
75-
# [servers.github.guard_policies.github]
75+
# [servers.github.guard_policies.allow-only]
7676
# repos = ["github/gh-aw-mcpg", "github/gh-aw"] # Exact repository patterns
7777
# min-integrity = "unapproved" # Minimum integrity level for GitHub changes:
7878
# # - none: allow any ref (branches, PRs, tags)
@@ -127,10 +127,10 @@ args = [
127127
# Advanced Options
128128
# ============================================================================
129129

130-
# Enable Data Information Flow Control (DIFC) security model (default: false)
131-
# When enabled, enforces information flow control policies on tool calls
132-
# This is an experimental feature - keep disabled for standard MCP compatibility
133-
# enable_guards = false
130+
# Guards enforcement mode: strict, filter, or propagate (default: strict)
131+
# Guards are automatically enabled when an allow-only policy is detected
132+
# in the server configuration (guard-policies field)
133+
# guards_mode = "strict"
134134

135135
# ============================================================================
136136
# Notes

guards/github-guard/docs/OVERVIEW.md

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,6 @@ make test-copilot-public-only
111111

112112
**Environment Variables**:
113113
```bash
114-
MCP_GATEWAY_ENABLE_GUARDS=1
115-
MCP_GATEWAY_CONFIG_EXTENSIONS=1
116114
MCP_GATEWAY_GUARD_POLICY_JSON='{"allow-only":{"repos":"public","min-integrity": "none"}}'
117115
```
118116

@@ -131,8 +129,6 @@ make test-copilot-owner-only
131129

132130
**Environment Variables**:
133131
```bash
134-
MCP_GATEWAY_ENABLE_GUARDS=1
135-
MCP_GATEWAY_CONFIG_EXTENSIONS=1
136132
ALLOW_OWNER=lpcox
137133
MCP_GATEWAY_GUARD_POLICY_JSON='{"allow-only":{"repos":["lpcox/*"],"min-integrity": "none"}}'
138134
```
@@ -152,8 +148,6 @@ make test-copilot-repo-only
152148

153149
**Environment Variables**:
154150
```bash
155-
MCP_GATEWAY_ENABLE_GUARDS=1
156-
MCP_GATEWAY_CONFIG_EXTENSIONS=1
157151
MCP_GATEWAY_GUARD_POLICY_JSON='{"allow-only":{"repos":["owner/repo"],"min-integrity": "none"}}'
158152
```
159153

guards/github-guard/scripts/run_copilot_test.sh

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -327,8 +327,6 @@ case "$MODE" in
327327
echo -e "${BLUE}Mode: all - Allow all repos with approved integrity floor${NC}"
328328
SERVER_GUARD_POLICIES_JSON="$ALLOW_ONLY_ALL_POLICY"
329329
DOCKER_ENV_ARGS+=(
330-
-e MCP_GATEWAY_ENABLE_GUARDS=1
331-
-e MCP_GATEWAY_CONFIG_EXTENSIONS=1
332330
-e DEBUG='server:unified,guard:wasm'
333331
)
334332
;;
@@ -337,8 +335,6 @@ case "$MODE" in
337335
echo -e "${BLUE}Mode: public-only - Filtering private data (public repos only)${NC}"
338336
SERVER_GUARD_POLICIES_JSON="$ALLOW_ONLY_PUBLIC_POLICY"
339337
DOCKER_ENV_ARGS+=(
340-
-e MCP_GATEWAY_ENABLE_GUARDS=1
341-
-e MCP_GATEWAY_CONFIG_EXTENSIONS=1
342338
-e DEBUG='server:unified,guard:wasm'
343339
)
344340
;;
@@ -347,8 +343,6 @@ case "$MODE" in
347343
echo -e "${BLUE}Mode: owner-only - Filtering data outside owner scope (${ALLOW_OWNER})${NC}"
348344
SERVER_GUARD_POLICIES_JSON="$ALLOW_ONLY_OWNER_POLICY"
349345
DOCKER_ENV_ARGS+=(
350-
-e MCP_GATEWAY_ENABLE_GUARDS=1
351-
-e MCP_GATEWAY_CONFIG_EXTENSIONS=1
352346
-e DEBUG='server:unified,guard:wasm'
353347
)
354348
;;
@@ -357,8 +351,6 @@ case "$MODE" in
357351
echo -e "${BLUE}Mode: repo-only - Filtering data outside repo scope (${DIFC_SCOPE})${NC}"
358352
SERVER_GUARD_POLICIES_JSON="$ALLOW_ONLY_REPO_POLICY"
359353
DOCKER_ENV_ARGS+=(
360-
-e MCP_GATEWAY_ENABLE_GUARDS=1
361-
-e MCP_GATEWAY_CONFIG_EXTENSIONS=1
362354
-e DEBUG='server:unified,guard:wasm'
363355
)
364356
;;
@@ -367,8 +359,6 @@ case "$MODE" in
367359
echo -e "${BLUE}Mode: prefix-only - Filtering data outside repo prefix scope (lpcox/git-*)${NC}"
368360
SERVER_GUARD_POLICIES_JSON="$ALLOW_ONLY_PREFIX_POLICY"
369361
DOCKER_ENV_ARGS+=(
370-
-e MCP_GATEWAY_ENABLE_GUARDS=1
371-
-e MCP_GATEWAY_CONFIG_EXTENSIONS=1
372362
-e DEBUG='server:unified,guard:wasm'
373363
)
374364
;;
@@ -377,8 +367,6 @@ case "$MODE" in
377367
echo -e "${BLUE}Mode: multi-only - Filtering using multiple repo scopes (lpcox/git-* + lpcox/github-guard)${NC}"
378368
SERVER_GUARD_POLICIES_JSON="$ALLOW_ONLY_MULTI_POLICY"
379369
DOCKER_ENV_ARGS+=(
380-
-e MCP_GATEWAY_ENABLE_GUARDS=1
381-
-e MCP_GATEWAY_CONFIG_EXTENSIONS=1
382370
-e DEBUG='server:unified,guard:wasm'
383371
)
384372
;;
@@ -472,8 +460,6 @@ ACTIVE_ALLOW_ONLY_POLICY=""
472460
# Add DIFC flags for non-yolo modes
473461
if [ "$MODE" != "yolo" ] && [ "$MODE" != "lockdown" ]; then
474462
GATEWAY_CLI_ARGS+=(
475-
--enable-config-extensions
476-
--enable-guards
477463
)
478464

479465
# DIFC mode is guard-managed at runtime (do not set via CLI)

guards/github-guard/scripts/run_integration_tests.sh

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -155,10 +155,7 @@ echo ""
155155

156156
GATEWAY_TEST_MODE="integration"
157157
GATEWAY_GUARDS_MODE="gateway-default"
158-
GATEWAY_CLI_ARGS=(
159-
--enable-config-extensions
160-
--enable-guards
161-
)
158+
GATEWAY_CLI_ARGS=()
162159

163160
echo "Gateway runtime settings:"
164161
echo " Test mode: $GATEWAY_TEST_MODE"
@@ -185,8 +182,6 @@ echo ""
185182
-e MCP_GATEWAY_DOMAIN=localhost \
186183
-e MCP_GATEWAY_API_KEY="$GATEWAY_API_KEY" \
187184
-e DOCKER_API_VERSION=1.44 \
188-
-e MCP_GATEWAY_ENABLE_GUARDS=1 \
189-
-e MCP_GATEWAY_CONFIG_EXTENSIONS=1 \
190185
-e MCP_GATEWAY_WASM_GUARDS_DIR="/guards" \
191186
-v /var/run/docker.sock:/var/run/docker.sock \
192187
-v "/tmp:/tmp:rw" \

internal/cmd/flags.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@
3232
// flags_logging.go getDefaultPayloadDir() → MCP_GATEWAY_PAYLOAD_DIR
3333
// flags_logging.go getDefaultPayloadPathPrefix() → MCP_GATEWAY_PAYLOAD_PATH_PREFIX
3434
// flags_logging.go getDefaultPayloadSizeThreshold() → MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD
35-
// flags_difc.go getDefaultEnableDIFC() → MCP_GATEWAY_ENABLE_GUARDS
35+
// flags_difc.go getDefaultDIFCMode() → MCP_GATEWAY_GUARDS_MODE
36+
// flags_difc.go getDefaultDIFCSinkServerIDs() → MCP_GATEWAY_GUARDS_SINK_SERVER_IDS
3637
//
3738
// This pattern is intentionally kept in individual feature files because:
3839
// - Each helper names the specific environment variable it reads, making the

internal/cmd/flags_difc.go

Lines changed: 0 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,9 @@ import (
1313
"github.com/spf13/cobra"
1414
)
1515

16-
// DIFC flag defaults
17-
const (
18-
defaultEnableDIFC = false
19-
defaultConfigExtensions = false
20-
)
21-
2216
// DIFC flag variables
2317
var (
24-
enableDIFC bool
2518
difcMode string
26-
enableConfigExt bool // Enable config extensions (guards, session labels)
27-
sessionSecrecy string // Comma-separated initial secrecy labels
28-
sessionIntegrity string // Comma-separated initial integrity labels
2919
difcSinkServerIDs string // Comma-separated server IDs that should include DIFC tag snapshots in RPC JSONL logs
3020
guardPolicyJSON string
3121
allowOnlyPublic bool
@@ -36,12 +26,7 @@ var (
3626

3727
func init() {
3828
RegisterFlag(func(cmd *cobra.Command) {
39-
cmd.Flags().BoolVar(&enableDIFC, "enable-guards", getDefaultEnableDIFC(), "Enable guards enforcement for information flow control")
40-
cmd.Flags().MarkHidden("enable-guards")
4129
cmd.Flags().StringVar(&difcMode, "guards-mode", getDefaultDIFCMode(), "Guards enforcement mode: strict (deny violations), filter (remove denied tools), or propagate (auto-adjust agent labels on reads)")
42-
cmd.Flags().BoolVar(&enableConfigExt, "enable-config-extensions", getDefaultConfigExtensions(), "Enable config extensions (guards, session labels) - required for guards session label features")
43-
cmd.Flags().StringVar(&sessionSecrecy, "session-secrecy", getDefaultSessionSecrecy(), "Comma-separated initial secrecy labels for agent sessions (requires --enable-config-extensions)")
44-
cmd.Flags().StringVar(&sessionIntegrity, "session-integrity", getDefaultSessionIntegrity(), "Comma-separated initial integrity labels for agent sessions (requires --enable-config-extensions)")
4530
cmd.Flags().StringVar(&difcSinkServerIDs, "guards-sink-server-ids", getDefaultDIFCSinkServerIDs(), "Comma-separated server IDs whose RPC JSONL logs should include agent secrecy/integrity tag snapshots")
4631
cmd.Flags().StringVar(&guardPolicyJSON, "guard-policy-json", getDefaultGuardPolicyJSON(), "Guard policy JSON (e.g. {\"allow-only\":{\"repos\":\"public\",\"min-integrity\":\"none\"}})")
4732
cmd.Flags().BoolVar(&allowOnlyPublic, "allowonly-scope-public", getDefaultAllowOnlyScopePublic(), "Use public AllowOnly scope")
@@ -51,12 +36,6 @@ func init() {
5136
})
5237
}
5338

54-
// getDefaultEnableDIFC returns the default guards setting, checking MCP_GATEWAY_ENABLE_GUARDS
55-
// environment variable first, then falling back to the hardcoded default (false)
56-
func getDefaultEnableDIFC() bool {
57-
return envutil.GetEnvBool("MCP_GATEWAY_ENABLE_GUARDS", defaultEnableDIFC)
58-
}
59-
6039
// getDefaultDIFCMode returns the default guards mode, checking MCP_GATEWAY_GUARDS_MODE
6140
// environment variable first, then falling back to the hardcoded default (strict)
6241
func getDefaultDIFCMode() string {
@@ -79,24 +58,6 @@ func isValidDIFCMode(mode string) bool {
7958
return false
8059
}
8160

82-
// getDefaultConfigExtensions returns the default config extensions setting,
83-
// checking MCP_GATEWAY_CONFIG_EXTENSIONS environment variable first
84-
func getDefaultConfigExtensions() bool {
85-
return envutil.GetEnvBool("MCP_GATEWAY_CONFIG_EXTENSIONS", defaultConfigExtensions)
86-
}
87-
88-
// getDefaultSessionSecrecy returns the default session secrecy labels from
89-
// MCP_GATEWAY_SESSION_SECRECY environment variable
90-
func getDefaultSessionSecrecy() string {
91-
return os.Getenv("MCP_GATEWAY_SESSION_SECRECY")
92-
}
93-
94-
// getDefaultSessionIntegrity returns the default session integrity labels from
95-
// MCP_GATEWAY_SESSION_INTEGRITY environment variable
96-
func getDefaultSessionIntegrity() string {
97-
return os.Getenv("MCP_GATEWAY_SESSION_INTEGRITY")
98-
}
99-
10061
func getDefaultDIFCSinkServerIDs() string {
10162
return os.Getenv("MCP_GATEWAY_GUARDS_SINK_SERVER_IDS")
10263
}
@@ -192,22 +153,6 @@ func ValidateDIFCMode(mode string) error {
192153
return nil
193154
}
194155

195-
// parseSessionLabels parses a comma-separated string of labels into a slice
196-
func parseSessionLabels(labels string) []string {
197-
if labels == "" {
198-
return nil
199-
}
200-
parts := strings.Split(labels, ",")
201-
result := make([]string, 0, len(parts))
202-
for _, part := range parts {
203-
trimmed := strings.TrimSpace(part)
204-
if trimmed != "" {
205-
result = append(result, trimmed)
206-
}
207-
}
208-
return result
209-
}
210-
211156
func parseDIFCSinkServerIDs(input string) ([]string, error) {
212157
if strings.TrimSpace(input) == "" {
213158
return nil, nil

0 commit comments

Comments
 (0)