Skip to content

[security-audit-agent] Security Audit Findings — 2026-06-15#102

Closed
rosa-regional-platform-ci wants to merge 1 commit into
openshift-online:mainfrom
rosa-regional-platform-ci:security-audit-2026-06-15
Closed

[security-audit-agent] Security Audit Findings — 2026-06-15#102
rosa-regional-platform-ci wants to merge 1 commit into
openshift-online:mainfrom
rosa-regional-platform-ci:security-audit-2026-06-15

Conversation

@rosa-regional-platform-ci

Copy link
Copy Markdown

Security Audit — rosa-regional-platform-api

Date: 2026-06-15
Auditor: Automated security-audit-agent
Method: Full static analysis of Go source files, Kubernetes manifests, Envoy configuration, CI scripts, Dockerfiles
Action required: Triage each finding below. This PR does not contain fixes — it exists to track and communicate security issues for owner review.

Supersedes: PR #97 (open, now closed). Incorporates all findings from #97 and the merged #85. No user comments in any previous PR dismissed any finding as a non-issue.


CRITICAL Findings

CRIT-1 — Authentication via Forgeable HTTP Headers (carry-over from #85/#97, unresolved)

File: pkg/middleware/identity.go

Risk: The entire authentication model trusts X-Amz-Account-Id, X-Amz-Caller-Arn, and related HTTP headers with no cryptographic verification. Any caller that bypasses Envoy and reaches the API pod directly can forge any identity, including privileged accounts.

Attack vectors:

  1. Direct pod IP call from any cluster pod sets X-Amz-Account-Id: <target> and X-Amz-Caller-Arn: arn:aws:iam::<target>:role/OrganizationAccountAccessRole — impersonates any account.
  2. The Kubernetes Service exposes port 8000 (see CRIT-2) — Envoy bypass is trivially accessible.
  3. Missing NetworkPolicy makes all cluster pods eligible callers.

Mitigation: Validate requests using an HMAC or shared secret injected only by Envoy/API Gateway. Remove port 8000 from the Kubernetes Service. Enforce NetworkPolicy restricting ingress to port 8000 to localhost only.


CRIT-2 — Kubernetes Service Exposes Raw API Port 8000, Bypassing Envoy Sidecar (NEW)

File: deployment/manifests/api.yaml

spec:
  ports:
    - name: http
      port: 8080    # Envoy — correct
    - name: api
      port: 8000    # Raw app — bypasses Envoy and identity header injection
    - name: health
      port: 8081
    - name: metrics
      port: 9090

Risk: Port 8000 is the raw application port, bypassing the Envoy sidecar that sets identity headers. Any pod in the cluster can call http://rosa-regional-platform:8000 and reach the application with no identity context. The identity middleware receives requests with empty X-Amz-* headers, and behavior with missing headers may allow unauthenticated operations.

Attack vector: Compromised pod calls port 8000 directly — no identity headers, no Envoy middleware, direct application access.

Mitigation: Remove ports 8000, 8081, and 9090 from the Kubernetes Service. Add NetworkPolicy denying all ingress except port 8080 from ALB/monitoring sources.


HIGH Findings

HIGH-1 — Authorization Silently Disabled When Config Is Missing (carry-over from #85/#97, unresolved)

File: pkg/server/server.go

Risk: When cfg.Authz is nil or disabled, the server falls back to account-allowlist-only mode with no per-resource authorization. Any misconfiguration (missing env var, DynamoDB connection failure) silently degrades security. Any allowlisted account gets full access to all operations.

Mitigation: Fail-closed: if authz is expected but config is missing/invalid, exit with a fatal error rather than starting in degraded mode.


HIGH-2 — No Request Body Size Limits Enable Memory Exhaustion DoS (carry-over from #97, unresolved)

Files: pkg/handlers/cluster.go:85, pkg/handlers/nodepool.go:81, and 40+ handler locations

Risk: All handlers use json.NewDecoder(r.Body).Decode() without http.MaxBytesReader. A client sends a large Content-Length, causing the pod to OOM. Any authorized account can trigger this — no auth bypass needed.

Mitigation: Add middleware: r.Body = http.MaxBytesReader(w, r.Body, 10*1024*1024)


HIGH-3 — Hardcoded Privileged Test Account in e2e Script (carry-over from #97, unresolved)

File: scripts/e2e-init-dynamodb.sh

aws dynamodb put-item --endpoint-url "$ENDPOINT" ... "accountId": {"S": "000000000000"}, "privileged": {"BOOL": true}

Risk: If $ENDPOINT is empty or misconfigured, account 000000000000 is written as privileged in production DynamoDB. This account ID is public in source code.

Mitigation: Abort if $ENDPOINT is not localhost/127.0.0.1. Use a randomly generated test account ID.


HIGH-4 — Authorization Middleware Fails Open on DynamoDB Errors (carry-over from #97, unresolved)

Files: pkg/middleware/account_check.go, pkg/middleware/privileged.go

Risk: When DynamoDB is unavailable, both middleware functions log an error and allow the request to proceed with unverified authorization state. This is fail-open.

Mitigation: Return 503 Service Unavailable when the authorization backend is unreachable.


HIGH-5 — Unpinned Container Images in Deployment Manifest (NEW)

File: deployment/manifests/api.yaml

image: quay.io/cdoan0/rosa-regional-platform-api:latest   # personal account, mutable tag
image: envoyproxy/envoy:v1.31-latest                       # moving branch tag

Risk:

  1. A personal quay.io account image with a mutable tag. A compromised push to cdoan0's account updates the production API (with imagePullPolicy: Always).
  2. The Envoy sidecar that performs identity extraction is on a moving tag — any v1.31.x patch update is silently deployed.

Mitigation: Move the API image to quay.io/rrp-dev-ci/ or the openshift-online org. Pin both images to SHA256 digests.


HIGH-6 — Prometheus Metrics Exposed Cluster-Wide Without Authentication (carry-over from #85, partially mitigated)

File: deployment/manifests/api.yaml, pkg/server/server.go

Risk: Metrics endpoint on 0.0.0.0:9090 is exposed via the Kubernetes Service on port 9090 with no authentication. Any cluster pod can scrape operational intelligence about the API service.

Mitigation: Bind to 127.0.0.1 or add bearer token auth. Remove port 9090 from the Kubernetes Service. Add NetworkPolicy restricting scraping to the Prometheus namespace.


MEDIUM Findings

MED-1 — Wildcard CORS Policy (carry-over from #85, unresolved)

File: pkg/server/server.gohandlers.AllowedOrigins([]string{"*"})

Mitigation: Restrict to specific frontend domains.


MED-2 — Identity Headers Not Validated for Format (carry-over from #85, unresolved)

File: pkg/middleware/identity.go

Risk: X-Amz-Account-Id accepts arbitrary strings. AWS account IDs are always 12-digit numbers. Malformed values enable log injection and downstream key injection.

Mitigation: Validate against /^\d{12}$/. Return 400 Bad Request for malformed values.


MED-3 — Build Stage Dockerfile Uses Unpinned golang:1.25-alpine (NEW)

File: Dockerfile line 2 — FROM golang:1.25-alpine AS builder

Mitigation: Pin to SHA256 digest.


MED-4 — Runtime Dockerfile Uses Unpinned distroless/static-debian12:nonroot (NEW)

File: DockerfileFROM gcr.io/distroless/static-debian12:nonroot

Mitigation: Pin to SHA256 digest.


Full findings detail is in SECURITY-AUDIT.md added in this PR.

@openshift-ci

openshift-ci Bot commented Jun 15, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: rosa-regional-platform-ci
Once this PR has been reviewed and has the lgtm label, please assign cdoan1 for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@rosa-regional-platform-ci, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 58 minutes and 8 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: openshift-online/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: efdcbc17-e076-403b-af74-17045dd9c3ce

📥 Commits

Reviewing files that changed from the base of the PR and between 5d817c7 and 0b45622.

📒 Files selected for processing (1)
  • SECURITY-AUDIT.md
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@openshift-ci

openshift-ci Bot commented Jun 15, 2026

Copy link
Copy Markdown

Hi @rosa-regional-platform-ci. Thanks for your PR.

I'm waiting for a openshift-online member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work.

Tip

We noticed you've done this a few times! Consider joining the org to skip this step and gain /lgtm and other bot rights. We recommend asking approvers on your previous PRs to sponsor you.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@openshift-ci openshift-ci Bot added the needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. label Jun 15, 2026
@typeid typeid closed this Jul 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants