Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
191 changes: 191 additions & 0 deletions cmd/handle_analyze_manifest_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -294,3 +294,194 @@ jobs:

t.Logf("Successfully analyzed manifest with %d findings", len(insights.Findings))
}

func TestHandleAnalyzeManifestWithAllowedRules(t *testing.T) {
ctx := context.Background()

analyzer, err := createTestAnalyzer(ctx)
require.NoError(t, err)

vulnerableManifest := `name: Test Workflow
on:
pull_request_target:
branches: [main]

jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Run test
run: echo "Testing ${{ github.event.pull_request.head.ref }}"`

t.Run("without allowed_rules filter", func(t *testing.T) {
request := NewCallToolRequest("analyze_manifest", map[string]interface{}{
"content": vulnerableManifest,
"manifest_type": "github-actions",
})

result, err := handleAnalyzeManifest(ctx, request, analyzer)
require.NoError(t, err)
require.NotNil(t, result)
assert.False(t, result.IsError)

contentText := extractTextFromContent(t, result.Content[0])
require.NotEmpty(t, contentText)

var insights struct {
Findings []results.Finding `json:"findings"`
Rules map[string]results.Rule `json:"rules"`
}
err = json.Unmarshal([]byte(contentText), &insights)
require.NoError(t, err)

// Should have multiple findings including injection
assert.Greater(t, len(insights.Findings), 1, "Should have multiple findings without filter")

// Verify injection rule is present
hasInjection := false
for _, finding := range insights.Findings {
if finding.RuleId == "injection" {
hasInjection = true
break
}
}
assert.True(t, hasInjection, "Should have injection finding")

t.Logf("Found %d findings without filter", len(insights.Findings))
})

t.Run("with allowed_rules filter for injection only", func(t *testing.T) {
request := NewCallToolRequest("analyze_manifest", map[string]interface{}{
"content": vulnerableManifest,
"manifest_type": "github-actions",
"allowed_rules": []string{"injection"},
})

result, err := handleAnalyzeManifest(ctx, request, analyzer)
require.NoError(t, err)
require.NotNil(t, result)
assert.False(t, result.IsError)

contentText := extractTextFromContent(t, result.Content[0])
require.NotEmpty(t, contentText)

var insights struct {
Findings []results.Finding `json:"findings"`
Rules map[string]results.Rule `json:"rules"`
}
err = json.Unmarshal([]byte(contentText), &insights)
require.NoError(t, err)

// Should have only injection finding
assert.Len(t, insights.Findings, 1, "Should have only one finding with filter")
assert.Equal(t, "injection", insights.Findings[0].RuleId, "Should only have injection finding")

// Should have only injection rule
assert.Len(t, insights.Rules, 1, "Should have only one rule with filter")
_, hasInjectionRule := insights.Rules["injection"]
assert.True(t, hasInjectionRule, "Should have injection rule in rules map")

t.Logf("Found %d findings with allowed_rules filter", len(insights.Findings))
})

t.Run("with allowed_rules filter for non-existent rule", func(t *testing.T) {
request := NewCallToolRequest("analyze_manifest", map[string]interface{}{
"content": vulnerableManifest,
"manifest_type": "github-actions",
"allowed_rules": []string{"non_existent_rule"},
})

result, err := handleAnalyzeManifest(ctx, request, analyzer)
require.NoError(t, err)
require.NotNil(t, result)
assert.False(t, result.IsError)

contentText := extractTextFromContent(t, result.Content[0])
require.NotEmpty(t, contentText)

var insights struct {
Findings []results.Finding `json:"findings"`
Rules map[string]results.Rule `json:"rules"`
}
err = json.Unmarshal([]byte(contentText), &insights)
require.NoError(t, err)

// Should have no findings
assert.Empty(t, insights.Findings, "Should have no findings with non-existent rule filter")
assert.Empty(t, insights.Rules, "Should have no rules with non-existent rule filter")

t.Logf("Found %d findings with non-existent rule filter", len(insights.Findings))
})
}

func TestMCPServerGlobalAllowedRules(t *testing.T) {
ctx := context.Background()

// Save original state
originalAllowedRules := allowedRules
defer func() {
allowedRules = originalAllowedRules
}()

// Simulate global --allowed-rules injection flag
allowedRules = []string{"injection"}

// Create analyzer with global allowed rules (simulating startMCPServer behavior)
testConfig := *config
if len(allowedRules) > 0 {
testConfig.AllowedRules = allowedRules
}

vulnerableManifest := `name: Test Workflow
on:
pull_request_target:
branches: [main]

jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Run test
run: echo "Testing ${{ github.event.pull_request.head.ref }}"`

t.Run("handleAnalyzeManifest respects global allowed rules", func(t *testing.T) {
opaClient, err := newOpaWithConfig(ctx, &testConfig)
require.NoError(t, err)
manifestAnalyzer := analyze.NewAnalyzer(nil, nil, &noop.Format{}, &testConfig, opaClient)

// Call without allowed_rules parameter (should inherit global)
request := NewCallToolRequest("analyze_manifest", map[string]interface{}{
"content": vulnerableManifest,
"manifest_type": "github-actions",
})

result, err := handleAnalyzeManifest(ctx, request, manifestAnalyzer)
require.NoError(t, err)
require.NotNil(t, result)
assert.False(t, result.IsError)

contentText := extractTextFromContent(t, result.Content[0])
require.NotEmpty(t, contentText)

var insights struct {
Findings []results.Finding `json:"findings"`
Rules map[string]results.Rule `json:"rules"`
}
err = json.Unmarshal([]byte(contentText), &insights)
require.NoError(t, err)

// Should have only injection finding due to global allowed rules
assert.Len(t, insights.Findings, 1, "Should have only injection finding with global allowed rules")
assert.Equal(t, "injection", insights.Findings[0].RuleId, "Should only have injection finding")

t.Logf("Global allowed rules test: Found %d findings", len(insights.Findings))
})
}
Loading
Loading