Skip to content

Commit 589ef8b

Browse files
Copilotpelikhan
andauthored
Fix integration tests: handle shell-escaped JSON keys and add sandbox feature flag
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
1 parent 2f7a099 commit 589ef8b

5 files changed

Lines changed: 75 additions & 22 deletions

pkg/workflow/allowed_domains_sanitization_test.go

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -605,8 +605,15 @@ Test workflow with non-api prefix api-target.
605605
// Check allowDomains in AWF JSON config contains expected domains.
606606
// Network settings are now expressed via --config JSON file instead of
607607
// --allow-domains CLI flag (see BuildAWFConfigJSON).
608+
// The JSON is shell-escaped in the lock file, so try both the unescaped
609+
// ("allowDomains":[) and escaped (\"allowDomains\":[) forms.
608610
allowDomainsPrefix := `"allowDomains":[`
611+
allowDomainsPrefixEscaped := `\"allowDomains\":[`
609612
allowDomainsIdx := strings.Index(lockStr, allowDomainsPrefix)
613+
if allowDomainsIdx < 0 {
614+
allowDomainsPrefix = allowDomainsPrefixEscaped
615+
allowDomainsIdx = strings.Index(lockStr, allowDomainsPrefixEscaped)
616+
}
610617
if allowDomainsIdx < 0 {
611618
t.Fatal("allowDomains key not found in compiled lock file")
612619
}
@@ -618,15 +625,22 @@ Test workflow with non-api prefix api-target.
618625
}
619626
allowDomainsSection := lockStr[arrayStart : arrayStart+allowDomainsEnd]
620627

628+
// containsJSONDomain checks for a domain as a JSON string value, handling both
629+
// escaped (\"domain\") and unescaped ("domain") forms in the lock file.
630+
containsJSONDomain := func(section, domain string) bool {
631+
return strings.Contains(section, `"`+domain+`"`) ||
632+
strings.Contains(section, `\"`+domain+`\"`)
633+
}
634+
621635
for _, domain := range tt.expectedDomains {
622-
if !strings.Contains(allowDomainsSection, `"`+domain+`"`) {
636+
if !containsJSONDomain(allowDomainsSection, domain) {
623637
t.Errorf("Expected domain %q not found in allowDomains.\nSection: %s", domain, allowDomainsSection)
624638
}
625639
}
626640
// Use exact JSON string matching for "not present" checks to avoid false positives
627641
// (e.g. "corp.example.com" would substring-match "copilot.corp.example.com").
628642
for _, domain := range tt.unexpectedDomains {
629-
if strings.Contains(allowDomainsSection, `"`+domain+`"`) {
643+
if containsJSONDomain(allowDomainsSection, domain) {
630644
t.Errorf("Unexpected domain %q found in allowDomains.\nSection: %s", domain, allowDomainsSection)
631645
}
632646
}
@@ -801,16 +815,28 @@ Test workflow with GHE data residency api-target and threat detection.
801815
// once for the main agent AWF run and once for the threat detection AWF run.
802816
// API proxy settings are now expressed via --config JSON file instead of
803817
// --copilot-api-target CLI flag (see BuildAWFConfigJSON).
804-
apiTargetCount := strings.Count(lockStr, `"copilot":{"host":"api.contoso-aw.ghe.com"}`)
818+
// The JSON is shell-escaped in the lock file, so try both unescaped and escaped forms.
819+
apiTargetUnescaped := `"copilot":{"host":"api.contoso-aw.ghe.com"}`
820+
apiTargetEscaped := `\"copilot\":{\"host\":\"api.contoso-aw.ghe.com\"}`
821+
apiTargetCount := strings.Count(lockStr, apiTargetUnescaped)
822+
if apiTargetCount == 0 {
823+
apiTargetCount = strings.Count(lockStr, apiTargetEscaped)
824+
}
805825
if apiTargetCount < 2 {
806826
t.Errorf("Expected copilot api-target to appear in both the main agent and threat detection AWF JSON configs (at least 2 times), but found %d occurrence(s).", apiTargetCount)
807827
}
808828

809829
// Find all allowDomains occurrences in AWF JSON config and verify each contains the GHE domains.
810830
// api.contoso-aw.ghe.com triggers base-domain derivation, so both the API domain
811831
// and the base domain (contoso-aw.ghe.com) must appear in each AWF invocation.
832+
// The JSON is shell-escaped in the lock file, so try both unescaped and escaped key forms.
812833
requiredDomains := []string{"api.contoso-aw.ghe.com", "contoso-aw.ghe.com"}
813834
allowDomainsPrefix := `"allowDomains":[`
835+
allowDomainsPrefixEscaped := `\"allowDomains\":[`
836+
// Use whichever prefix form is present in the lock file.
837+
if strings.Index(lockStr, allowDomainsPrefix) < 0 {
838+
allowDomainsPrefix = allowDomainsPrefixEscaped
839+
}
814840
remaining := lockStr
815841
occurrenceIdx := 0
816842
for {
@@ -826,7 +852,8 @@ Test workflow with GHE data residency api-target and threat detection.
826852
}
827853
section := remaining[arrayStart : arrayStart+arrayEnd]
828854
for _, domain := range requiredDomains {
829-
if !strings.Contains(section, `"`+domain+`"`) {
855+
// Handle both escaped (\"domain\") and unescaped ("domain") forms.
856+
if !strings.Contains(section, `"`+domain+`"`) && !strings.Contains(section, `\"`+domain+`\"`) {
830857
t.Errorf("allowDomains occurrence #%d is missing GHE domain %q.\nSection: %s", occurrenceIdx, domain, section)
831858
}
832859
}

pkg/workflow/aw_info_steps_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ permissions:
4747
issues: read
4848
pull-requests: read
4949
engine: copilot
50+
features:
51+
dangerously-disable-sandbox-agent: "controlled environment with no internet access"
5052
sandbox:
5153
agent: false
5254
strict: false

pkg/workflow/blocked_domains_integration_test.go

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,10 @@ Test workflow with blocked domains.
6565

6666
lockYAML := string(lockContent)
6767

68-
// Verify blockDomains key is present in the config JSON
69-
if !strings.Contains(lockYAML, `"blockDomains"`) {
68+
// Verify blockDomains key is present in the config JSON.
69+
// The key appears shell-escaped in the lock file (\"blockDomains\" or "blockDomains"),
70+
// so we search for the key name without surrounding quotes to match both forms.
71+
if !strings.Contains(lockYAML, "blockDomains") {
7072
t.Error("Compiled workflow should contain 'blockDomains' key in config JSON")
7173
}
7274

@@ -79,8 +81,10 @@ Test workflow with blocked domains.
7981
t.Error("Compiled workflow should contain blocked domain 'tracker.example.com'")
8082
}
8183

82-
// Verify allowDomains key is present in the config JSON
83-
if !strings.Contains(lockYAML, `"allowDomains"`) {
84+
// Verify allowDomains key is present in the config JSON.
85+
// The key appears shell-escaped in the lock file (\"allowDomains\" or "allowDomains"),
86+
// so we search for the key name without surrounding quotes to match both forms.
87+
if !strings.Contains(lockYAML, "allowDomains") {
8488
t.Error("Compiled workflow should still contain 'allowDomains' key in config JSON")
8589
}
8690

@@ -140,8 +144,10 @@ Test workflow with blocked ecosystem.
140144

141145
lockYAML := string(lockContent)
142146

143-
// Verify blockDomains key is present in the config JSON
144-
if !strings.Contains(lockYAML, `"blockDomains"`) {
147+
// Verify blockDomains key is present in the config JSON.
148+
// The key appears shell-escaped in the lock file (\"blockDomains\" or "blockDomains"),
149+
// so we search for the key name without surrounding quotes to match both forms.
150+
if !strings.Contains(lockYAML, "blockDomains") {
145151
t.Error("Compiled workflow should contain 'blockDomains' key in config JSON")
146152
}
147153

@@ -208,13 +214,17 @@ Test workflow without blocked domains.
208214

209215
lockYAML := string(lockContent)
210216

211-
// Verify blockDomains key is NOT present in the config JSON
212-
if strings.Contains(lockYAML, `"blockDomains"`) {
217+
// Verify blockDomains key is NOT present in the config JSON.
218+
// The key appears shell-escaped in the lock file (\"blockDomains\" or "blockDomains"),
219+
// so we search for the key name without surrounding quotes to match both forms.
220+
if strings.Contains(lockYAML, "blockDomains") {
213221
t.Error("Compiled workflow should NOT contain 'blockDomains' key in config JSON when no domains are blocked")
214222
}
215223

216-
// Verify allowDomains key is still present
217-
if !strings.Contains(lockYAML, `"allowDomains"`) {
224+
// Verify allowDomains key is still present.
225+
// The key appears shell-escaped in the lock file (\"allowDomains\" or "allowDomains"),
226+
// so we search for the key name without surrounding quotes to match both forms.
227+
if !strings.Contains(lockYAML, "allowDomains") {
218228
t.Error("Compiled workflow should still contain 'allowDomains' key in config JSON")
219229
}
220230
})
@@ -269,8 +279,10 @@ Test Claude workflow with blocked domains.
269279

270280
lockYAML := string(lockContent)
271281

272-
// Verify blockDomains key is present in the config JSON
273-
if !strings.Contains(lockYAML, `"blockDomains"`) {
282+
// Verify blockDomains key is present in the config JSON.
283+
// The key appears shell-escaped in the lock file (\"blockDomains\" or "blockDomains"),
284+
// so we search for the key name without surrounding quotes to match both forms.
285+
if !strings.Contains(lockYAML, "blockDomains") {
274286
t.Error("Compiled Claude workflow should contain 'blockDomains' key in config JSON")
275287
}
276288

@@ -330,8 +342,10 @@ Test Codex workflow with blocked domains.
330342

331343
lockYAML := string(lockContent)
332344

333-
// Verify blockDomains key is present in the config JSON
334-
if !strings.Contains(lockYAML, `"blockDomains"`) {
345+
// Verify blockDomains key is present in the config JSON.
346+
// The key appears shell-escaped in the lock file (\"blockDomains\" or "blockDomains"),
347+
// so we search for the key name without surrounding quotes to match both forms.
348+
if !strings.Contains(lockYAML, "blockDomains") {
335349
t.Error("Compiled Codex workflow should contain 'blockDomains' key in config JSON")
336350
}
337351

pkg/workflow/domains_protocol_integration_test.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,11 @@ Test protocol-specific domains in safe-outputs.
136136
}
137137
}
138138

139-
// If checking AWF args, verify allowDomains key is present in the config JSON
139+
// If checking AWF args, verify allowDomains key is present in the config JSON.
140+
// The key appears shell-escaped in the lock file (\"allowDomains\" or "allowDomains"),
141+
// so we search for the key name without surrounding quotes to match both forms.
140142
if tt.checkAWFArgs {
141-
if !strings.Contains(lockYAML, `"allowDomains"`) {
143+
if !strings.Contains(lockYAML, "allowDomains") {
142144
t.Error("Expected 'allowDomains' key in config JSON of compiled workflow")
143145
}
144146
}
@@ -301,8 +303,10 @@ Test backward compatibility with domains without protocols.
301303
}
302304
}
303305

304-
// Verify allowDomains key is present in the config JSON
305-
if !strings.Contains(lockYAML, `"allowDomains"`) {
306+
// Verify allowDomains key is present in the config JSON.
307+
// The key appears shell-escaped in the lock file (\"allowDomains\" or "allowDomains"),
308+
// so we search for the key name without surrounding quotes to match both forms.
309+
if !strings.Contains(lockYAML, "allowDomains") {
306310
t.Error("Expected 'allowDomains' key in config JSON of compiled workflow")
307311
}
308312
}

pkg/workflow/sandbox_agent_disabled_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ func TestSandboxAgentFalse(t *testing.T) {
7474

7575
markdown := `---
7676
engine: copilot
77+
features:
78+
dangerously-disable-sandbox-agent: "controlled environment with no internet access"
7779
sandbox:
7880
agent: false
7981
strict: false
@@ -157,6 +159,8 @@ Test workflow with agent sandbox disabled in strict mode.
157159

158160
markdown := `---
159161
engine: copilot
162+
features:
163+
dangerously-disable-sandbox-agent: "controlled environment with no internet access"
160164
sandbox:
161165
agent: false
162166
strict: false
@@ -192,6 +196,8 @@ func TestSandboxAgentFalseWithTools(t *testing.T) {
192196

193197
markdown := `---
194198
engine: copilot
199+
features:
200+
dangerously-disable-sandbox-agent: "controlled environment with no internet access"
195201
sandbox:
196202
agent: false
197203
strict: false

0 commit comments

Comments
 (0)