Skip to content

Fix external threat detection to honor custom engine base URLs and allowlist propagation#46077

Merged
pelikhan merged 6 commits into
mainfrom
copilot/fix-threat-detection-issue
Jul 17, 2026
Merged

Fix external threat detection to honor custom engine base URLs and allowlist propagation#46077
pelikhan merged 6 commits into
mainfrom
copilot/fix-threat-detection-issue

Conversation

Copilot AI commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Threat detection in the external detector path could not use custom OpenAI-compatible endpoints configured via engine.env.OPENAI_BASE_URL/ANTHROPIC_BASE_URL, because detection rebuilt EngineConfig without inherited env and AWF api-proxy target derivation fell back to defaults. The same path also under-propagated network.allowed additions by only keying off COPILOT_PROVIDER_BASE_URL.

  • Engine config inheritance in external detection

    • External detector now clones threat-detection engine config (when present) and merges main engine env into detection env, with detection-specific keys taking precedence.
    • This ensures AWF config generation in detection sees the same base-URL env inputs as the main agent path.
  • Allowlist propagation trigger generalized

    • getThreatDetectionAdditionalAllowedDomains now enables additional-domain propagation when any custom provider base URL is configured:
      • OPENAI_BASE_URL
      • ANTHROPIC_BASE_URL
      • COPILOT_PROVIDER_BASE_URL
    • Behavior remains deduplicated and continues filtering expressions/ecosystem-managed domains.
  • Refactor for consistency

    • Added helper(s) to clone detection engine config and merge env deterministically, removing duplicated field-copy logic across external detector install/execute paths.
  • Regression coverage

    • Added focused tests for:
      • external detector inheriting OPENAI_BASE_URL into AWF api-proxy target config
      • additional allowed domains behavior across OpenAI/Anthropic/Copilot provider base URL scenarios
// Detection env now composes main engine env + detection overrides.
threatDetectionData.EngineConfig = cloneThreatDetectionEngineConfig(engineID, data.SafeOutputs.ThreatDetection.EngineConfig)
threatDetectionData.EngineConfig.Env = mergeThreatDetectionEngineEnv(data, threatDetectionData.EngineConfig.Env)

Copilot AI and others added 2 commits July 16, 2026 20:02
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix threat detection failures with custom OPENAI_BASE_URL Fix external threat detection to honor custom engine base URLs and allowlist propagation Jul 16, 2026
Copilot AI requested a review from pelikhan July 16, 2026 20:16
@pelikhan
pelikhan marked this pull request as ready for review July 16, 2026 21:12
Copilot AI review requested due to automatic review settings July 16, 2026 21:12

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes external threat detection to inherit custom provider endpoints and propagate related network domains.

Changes:

  • Merges main and detection-specific engine environments.
  • Generalizes custom provider URL detection.
  • Adds regression coverage for endpoint and allowlist propagation.
Show a summary per file
File Description
pkg/workflow/threat_detection_helpers.go Adds environment cloning/merging and generalized URL checks.
pkg/workflow/threat_detection_external.go Applies effective engine configuration to external detection.
pkg/workflow/threat_detection_test.go Tests custom endpoints and allowed domains.

Review details

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 3/3 changed files
  • Comments generated: 3
  • Review effort level: Medium

Comment on lines +78 to +80
hasCustomTarget := extractAPITargetHost(data, "OPENAI_BASE_URL") != "" ||
extractAPITargetHost(data, "ANTHROPIC_BASE_URL") != "" ||
extractAPITargetHost(data, constants.CopilotProviderBaseURL) != ""
}
threatDetectionData.EngineConfig = cloneThreatDetectionEngineConfig(engineID, data.SafeOutputs.ThreatDetection.EngineConfig)
}
threatDetectionData.EngineConfig.Env = mergeThreatDetectionEngineEnv(data, threatDetectionData.EngineConfig.Env)
Comment thread pkg/workflow/threat_detection_test.go Outdated
Comment on lines +2118 to +2123
if !strings.Contains(stepsContent, "apiProxy") {
t.Fatalf("expected external detector AWF config to include api-proxy target; got:\n%s", stepsContent)
}
if !strings.Contains(stepsContent, "llm-router.internal.example.com") {
t.Fatalf("expected external detector AWF config to include host from OPENAI_BASE_URL; got:\n%s", stepsContent)
}
@github-actions github-actions Bot mentioned this pull request Jul 16, 2026
@github-actions

This comment has been minimized.

@github-actions

Copy link
Copy Markdown
Contributor

Great work on tracking down this subtle config-inheritance bug in the external threat detection path! The PR is well-scoped, clearly described, and ships focused regression tests alongside the fix. The engine-env merge logic and the generalised allowlist-propagation trigger both look like the right approach. This looks ready for review.

Generated by ✅ Contribution Check · 155.6 AIC · ⌖ 8.97 AIC · ⊞ 6.2K ·

@pelikhan

Copy link
Copy Markdown
Collaborator

/matt

@github-actions

github-actions Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅

@github-actions

Copy link
Copy Markdown
Contributor

Skills-Based Review 🧠

Applied /diagnosing-bugs and /tdd — requesting changes on two aliasing correctness issues and one test coverage gap.

📋 Key Themes & Highlights

Key Themes

  • Shallow-copy aliasing risk in cloneThreatDetectionEngineConfig: map/slice fields (Config, Args) remain aliased to the source. Mutations via the clone would corrupt the original config.
  • Partial aliasing protection in mergeThreatDetectionEngineEnv: the empty-main-env branch returns detectionEnv by reference, undermining the aliasing-safety guarantee stated in the function doc.
  • Missing assertion in TestExternalDetectorInheritsOpenAIBaseURL: CUSTOM_FLAG is set up but never asserted, leaving the merge-precedence contract untested.

Positive Highlights

  • ✅ Root cause correctly identified and fixed: env now flows main → detection with detection keys winning on overlap.
  • ✅ Allowlist trigger generalised cleanly across all three provider URL constants.
  • ✅ The maps.Clone in the empty-detectionEnv branch shows the right instinct — just needs consistent application.
  • ✅ Detailed PR description with a code snippet that maps directly to the fix.

@copilot please address the review comments above.

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · 36.8 AIC · ⌖ 4.9 AIC · ⊞ 6.7K ·
Comment /matt to run again

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{"pull_request_number":46077,"event":"REQUEST_CHANGES","body":"### Skills-Based Review 🧠

Applied /diagnosing-bugs and /tdd — requesting changes on two aliasing correctness issues and one test coverage gap.

📋 Key Themes & Highlights

Key Themes

  • Shallow-copy aliasing risk in cloneThreatDetectionEngineConfig: map/slice fields (Config, Args) are not deep-copied, so mutations via the clone would corrupt the source engine config.
  • Partial aliasing protection in mergeThreatDetectionEngineEnv: the empty-main-env branch returns detectionEnv by reference, undermining the aliasing-safety guarantee stated in the function doc.
  • Missing assertion in TestExternalDetectorInheritsOpenAIBaseURL: the detection-specific CUSTOM_FLAG env var is set up but never asserted, leaving the merge-precedence contract unchecked.

Positive Highlights

  • ✅ Root cause correctly identified and fixed: env inheritance now flows main → detection with detection keys taking precedence.
  • ✅ Allowlist trigger generalised cleanly across all three provider URL constants.
  • ✅ The maps.Clone in the empty-detectionEnv branch shows the right intent — just needs to be applied consistently.
  • ✅ PR description is detailed and maps directly to the fix.
"}

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · 36.8 AIC · ⌖ 4.9 AIC · ⊞ 6.7K
Comment /matt to run again

@pelikhan

Copy link
Copy Markdown
Collaborator

@copilot run pr-finisher skill

Copilot AI and others added 2 commits July 16, 2026 22:13
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
…rengthen test assertions

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>

Copilot AI commented Jul 16, 2026

Copy link
Copy Markdown
Contributor Author

@copilot run pr-finisher skill

Addressed all three mandatory review items in commit d6b6ea1:

  1. getThreatDetectionAdditionalAllowedDomains uses merged env — now evaluates the effective merged detection environment (main + detection-specific overrides) when deciding whether to propagate additional allowed domains, so base URLs configured only in safe-outputs.threat-detection.engine.env also trigger propagation.

  2. Detection job dependency scan uses merged envthreat_detection_job.go now calls mergeThreatDetectionEngineEnv to build the effective env before scanning for needs.* expressions. This ensures that main engine env entries (e.g. OPENAI_BASE_URL: ${{ needs.router.outputs.url }}) that get merged into the detection step also produce the corresponding needs dependency — matching the behavior of the execution path.

  3. Strengthened test assertionTestExternalDetectorInheritsOpenAIBaseURL now asserts the specific serialized apiProxy.targets.openai.host field (\"targets\":{\"openai\":{\"host\":\"llm-router.internal.example.com\") rather than loose substring checks.

Two new regression tests added: TestGetThreatDetectionAdditionalAllowedDomains_DetectionOnlyBaseURL and TestBuildDetectionJobNeedsIncludesMainEngineEnvJobs. Pre-existing tests TestBuildDetectionJobEngineEnvNeedsExpression and TestBuildDetectionJobEngineEnvNeedsIntegration updated to reflect the merged-env behavior (they previously tested isolation semantics that are superseded by mergeThreatDetectionEngineEnv).

All pkg/workflow tests pass locally. Remaining pkg/cli failures (TestLogsJSONOutputWithNoRuns, TestCloseExistingOrgIssuesByMarkerSkipsPRsAndPaginates) are pre-existing and unrelated to these changes.

@github-actions

Copy link
Copy Markdown
Contributor

🤖 PR Triage

Field Value
Category bug
Risk 🔴 High
Score 67/100
Action 🚀 fast_track

Score breakdown: Impact 35 + Urgency 20 + Quality 12

Rationale: Threat detection silently fell back to default engine endpoints when custom OPENAI_BASE_URL/ANTHROPIC_BASE_URL were configured; allowlist propagation also broken. Behavior-correctness bug in security-adjacent code path. CI not yet run — needs CI before merge.

Run §29545908133

Generated by 🔧 PR Triage Agent · 181.7 AIC · ⌖ 5.04 AIC · ⊞ 5.6K ·

@pelikhan
pelikhan merged commit 479a220 into main Jul 17, 2026
29 checks passed
@pelikhan
pelikhan deleted the copilot/fix-threat-detection-issue branch July 17, 2026 02:55
@github-actions github-actions Bot mentioned this pull request Jul 17, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🎉 This pull request is included in a new release.

Release: v0.82.12

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Threat detection always fails with codex + custom OPENAI_BASE_URL: detection api-proxy never receives the custom target

3 participants