Skip to content

[security-scan] Weekly OWASP Security Scan - 2026-05-14 #386

Description

@willvelida

Scan Summary

Domain CRITICAL HIGH MEDIUM LOW Notes
Agentic Security (ASI01-ASI10) 0 0 4 2 6 pass, 4 partial
CI/CD Security (CICD-SEC 1-10) 0 1 3 2 SHA-pinned actions (1 exception), OIDC auth
Container Security (Docker Top 6) 0 0 2 2 Multi-stage builds, non-root user
Totals 0 1 9 6

Comparison with Previous Scan (#341 — 2026-05-07)

Metric Previous Current Delta
CRITICAL 1 0 ✅ -1
HIGH 4 1 ✅ -3
MEDIUM 10 9 ✅ -1
LOW 2 6 ⬆️ +4 (more granular reporting)

Key improvements since last scan:

  • CRITICAL unpinned base image finding downgraded to MEDIUM (images use :10.0 not :latest)
  • ACR adminUserEnabled HIGH finding not detected this scan (may be resolved)
  • Docker resource limits and Cosmos emulator pinning not flagged (out of scope this run)
  • Container security posture improved overall

1. Agentic Security (ASI01-ASI10)

Scope: src/Biotrackr.Chat.Api/, src/Biotrackr.Mcp.Server/, src/Biotrackr.Reporting.Api/

Controls Passing ✅

  • ASI06 (Memory/Context Poisoning): 50 hydrated msgs, 10K char limit, 100 msg cap, 90-day TTL
  • ASI07 (Inter-Agent Communication): JWT + azp claim validation, API key with constant-time comparison
  • ASI08 (Cascading Failures): Circuit breakers, rate limiting (100 req/min), concurrency semaphore (3 jobs), timeouts
  • ASI09 (Human-Agent Trust): Independent reviewer agent, mandatory disclaimers, fail-safe disclosures
  • ASI10 (Rogue Agents): Kill switch, 50MB artifact limit, full OpenTelemetry tracing
  • ASI04 (Supply Chain): Explicit version pins (no floating ranges)

MEDIUM — ASI01: Chat.Api user messages not injection-scanned

File: src/Biotrackr.Chat.Api/Biotrackr.Chat.Api/Middleware/ConversationPersistenceMiddleware.cs
Issue: User messages pass to Claude without injection pattern detection. Reporting.Api has a blocklist but Chat.Api relies solely on system prompt boundaries.
Remediation: Add PromptInjectionMiddleware to Chat.Api scanning user messages before LLM invocation.

MEDIUM — ASI01: Shallow injection blocklist in Reporting.Api

File: src/Biotrackr.Reporting.Api/Biotrackr.Reporting.Api/Validation/ReportRequestValidator.cs, lines 15-21
Issue: Blocklist is trivially bypassed with Unicode homoglyphs, Base64 encoding, or indirect injection via sourceDataSnapshot (not scanned).
Remediation: Add input normalization before matching. Scan sourceDataSnapshot string fields. Consider LLM-based classifier.

MEDIUM — ASI03: Chat.Api conversation endpoints unauthenticated

File: src/Biotrackr.Chat.Api/Biotrackr.Chat.Api/Extensions/EndpointRouteBuilderExtensions.cs, lines 13-29
Issue: /conversations GET, GET/{sessionId}, DELETE/{sessionId} have no .RequireAuthorization(). Any caller can list/read/delete conversation history.
Remediation: Add .RequireAuthorization() to all conversation endpoints.

MEDIUM — ASI05: Post-hoc code validation only warns, doesn't abort

File: src/Biotrackr.Reporting.Api/Biotrackr.Reporting.Api/Services/ReportGenerationService.cs, lines 326-330
Issue: ValidateGeneratedCode logs a warning when dangerous patterns are found but does not abort the job or skip artifact upload.
Remediation: Fail the job when dangerous patterns are detected in the secondary scan.

LOW — ASI02: Tool whitelist logs but doesn't block

File: src/Biotrackr.Chat.Api/Biotrackr.Chat.Api/Middleware/ToolPolicyMiddleware.cs, lines 48-54
Issue: Unrecognized tool calls are logged as warnings but execution continues. Only budget exhaustion triggers blocking.
Remediation: Set blocked = true when tool name is not in AllowedToolNames.

LOW — ASI04: Preview package dependencies

File: src/Biotrackr.Chat.Api/Biotrackr.Chat.Api/Biotrackr.Chat.Api.csproj
Issue: Several packages use -preview and -rc versions with no LTS support.
Remediation: Track for GA releases. Consider packages.lock.json for reproducible builds.


2. CI/CD Security

Scope: .github/workflows/, infra/

Strong Practices ✅

SHA-pinned actions (one exception), OIDC auth, CodeQL scanning, scoped per-job permissions, no pull_request_target abuse, no script injection vectors, secrets via Key Vault.

HIGH — Overly Permissive RBAC: Contributor Role on ACS

File: infra/modules/communication/acs-email.bicep, lines 29, 70-75
Issue: Assigns Contributor role (b24988ac-6180-42a0-ab88-20f7382dd24c) to the managed identity over ACS. Contributor grants full management rights except RBAC assignment.
Remediation: Use a scoped built-in role or custom role with only email-sending permissions.

MEDIUM — Unpinned Action

File: .github/workflows/copilot-setup-steps.yml, line 22
Issue: actions/checkout@v6 uses a mutable tag. All other workflows correctly pin to SHA.
Remediation: Pin to full SHA: actions/checkout@<sha> # v6

MEDIUM — Container Apps Default to Public Ingress

File: infra/modules/host/container-app-http.bicep, line 61
Issue: external: true is hardcoded with no parameter override. APIs behind APIM should use internal ingress.
Remediation: Parameterize external so internal services can disable public exposure.

MEDIUM — AI Foundry Public Network Access

File: infra/modules/ai/foundry.bicep, line 59
Issue: publicNetworkAccess: 'Enabled' exposes AI Foundry endpoint publicly.
Remediation: Set to 'Disabled' with private endpoints, or parameterize per environment.

LOW — Unnecessary Permissions on Build Workflow

File: .github/workflows/build-copilot-python-image.yml, lines 6-11
Issue: pull-requests: write and checks: write granted for a workflow_dispatch-only workflow that doesn't use them.
Remediation: Remove unused permissions.

LOW — Log Analytics Public Network Access

File: infra/modules/monitoring/log-analytics.bicep, lines 29-30
Issue: Both ingestion and query public access enabled. Acceptable for dev but should be restricted in production.
Remediation: Parameterize for environment-specific control.


3. Container Security

Scope: All 14 Dockerfiles in src/

Strong Practices ✅

Multi-stage builds (3 stages), non-root user (USER $APP_UID), COPY-only (no ADD), no secrets in layers, no package installation, exec-form ENTRYPOINT.

MEDIUM — Unpinned Base Image Tags

Files: All 14 Dockerfiles, lines 4 and 10/12
Example: FROM mcr.microsoft.com/dotnet/aspnet:10.0
Issue: Images use :10.0 without SHA256 digest. Builds are non-reproducible.
Remediation: Pin to digest: FROM mcr.microsoft.com/dotnet/aspnet:10.0@sha256:<hash> or full patch version.

MEDIUM — No HEALTHCHECK Directive

Files: All 14 Dockerfiles
Issue: No HEALTHCHECK instruction. Container orchestrators cannot detect unhealthy apps without external probes.
Remediation: Add HEALTHCHECK --interval=30s --timeout=5s CMD curl -f (localhost/redacted) || exit 1

LOW — Unnecessary Port Exposure (8081)

Files: 7 of 14 Dockerfiles (Activity.Api, Chat.Api, Food.Api, Mcp.Server, UI, Vitals.Api, Sleep.Api)
Issue: EXPOSE 8081 alongside 8080. If TLS is terminated at ingress, port 8081 is unnecessary.
Remediation: Remove EXPOSE 8081 unless the app explicitly binds HTTPS at container level.

LOW — Missing .dockerignore

Files: 5 services — Chat.Api, Mcp.Server, Reporting.Api, Reporting.Svc, UI
Issue: Without .dockerignore, COPY . . sends unnecessary files to the Docker daemon build context.
Remediation: Copy .dockerignore from sibling services (e.g., Activity.Api/.dockerignore).


Priority Remediation Roadmap

Priority Finding Effort Recurring?
P1 ASI03: Add auth to conversation endpoints Low New
P1 HIGH: Scope ACS RBAC to least privilege Low Recurring
P2 ASI05: Fail job on dangerous code detection Low New
P2 ASI02: Block unrecognized tool calls Low New
P2 Pin copilot-setup-steps.yml checkout action Low New
P3 ASI01: Add injection middleware to Chat.Api Medium Recurring
P3 Parameterize container app ingress Medium Recurring
P3 Pin Dockerfile base images by digest Medium Recurring
P4 Add HEALTHCHECK to Dockerfiles Low Recurring
P4 Add .dockerignore to 5 services Low Recurring
P4 Disable AI Foundry public access Low Recurring

Generated by Weekly OWASP Security Scan — Multi-Persona · ● 5.8M ·

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions