Skip to content

ops: GHA inject box SSH pubkey + ufw prod - #228

Merged
echobt merged 1 commit into
mainfrom
ops/box-ssh-access-1788599056
Sep 5, 2026
Merged

ops: GHA inject box SSH pubkey + ufw prod#228
echobt merged 1 commit into
mainfrom
ops/box-ssh-access-1788599056

Conversation

@echobt

@echobt echobt commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Injects box@cursor pubkey via deploy SSH secrets; ufw allow 22 on prod master. workflow_dispatch only.

@echobt
echobt merged commit e7a600f into main Sep 5, 2026
3 checks passed
@greptile-apps

greptile-apps Bot commented Sep 5, 2026

Copy link
Copy Markdown

Greptile Summary

Summary

  • Enabling UFW with only SSH allowed can cut off the production master’s HTTP, HTTPS, and gateway traffic.
  • Firewall configuration failures and incomplete host updates can still produce a successful workflow run.
  • The workflow uses the production SSH identity for staging hosts when both environment keys are present.
  • A mutable checkout reference runs before a checked-out action receives the DigitalOcean credential.

These issues must be resolved before merging.

Confidence Score: 0/5

Not safe to merge: the workflow can cause a production connectivity outage, silently accept incomplete infrastructure changes, and exposes a privileged credential path to mutable action code.

Executed checks reproduced firewall error masking and partial host-rollout success, confirmed mixed-environment SSH key selection, verified required production ports, and verified the mutable checkout-to-token path.

Files Needing Attention: .github/workflows/ops-box-ssh-access.yml

Security Review

The workflow checks out repository content through mutable actions/checkout@v4 before invoking checked-out local action code with the DigitalOcean token. Pinning checkout to an immutable commit SHA prevents a moved or compromised tag from changing the privileged local action path.

T-Rex T-Rex Logs

What T-Rex did

  • T-Rex produced proofs for posted P1 findings and linked each to its corresponding reviewer comment.
  • T-Rex analyzed the UFW/SSH setup and concluded that a live production dispatch could not be attempted due to missing credentials.
  • T-Rex validated the UFW failure-masking workflow, demonstrating how simulated failures are masked and the final success path is reported.
  • T-Rex verified the key-target loop script, showing the selection of production and staging targets and a successful exit.
  • T-Rex validated partial rollout and local-action-token flows, including before/after harness runs and observed results.

View all artifacts

T-Rex Ran code and verified through T-Rex

Comments Outside Diff (5)

  1. General comment

    P1 SSH-access workflow can block required production-master ingress with UFW

    • Bug
      • On the production-master entry (mode=ufw), the workflow allows only OpenSSH/22 and then enables UFW. The repository's production master publishes HTTP on 80 and the gateway on 8080, and host Caddy terminates HTTPS on 443. If UFW has default-deny incoming behavior and no already-persistent equivalent rules, the workflow blocks those services immediately after line 64.
    • Cause
      • .github/workflows/ops-box-ssh-access.yml:63-64 creates an SSH-only UFW exception and enables UFW without adding allow rules for the production service ports. DigitalOcean firewall allowances are a separate network layer and do not configure host UFW.
    • Fix
      • Before enabling UFW, explicitly allow the production-master service ports with their intended scopes (80/tcp, 443/tcp, and 8080/tcp limited to the VPC CIDR if that remains the intended policy), then enable/reload UFW. Avoid suppressing failures for these required rules so an unsuccessful configuration fails the workflow.

    T-Rex Ran code and verified through T-Rex

  2. General comment

    P1 UFW failures are ignored and the host is reported successful

    • Bug
      • In .github/workflows/ops-box-ssh-access.yml:63-66, every UFW action is followed by || true (with the allow fallback ending in || true). This overrides set -e, so firewall configuration can fail while the remote script continues to hostname; ss and the enclosing if ssh_cmd ...; then prints SUCCESS and increments ok.
    • Cause
      • The unconditional true fallback converts nonzero UFW command statuses into success statuses.
    • Fix
      • Remove the unconditional || true fallbacks and allow UFW failures to terminate the remote shell. If a fallback from OpenSSH to 22/tcp is intended, retain only ufw allow OpenSSH || ufw allow 22/tcp and require the remaining UFW commands to succeed.

    T-Rex Ran code and verified through T-Rex

  3. General comment

    P1 Production-preferred identity is used for staging SSH targets

    • Bug
      • When both secrets are configured, the ops access workflow selects PROD_SSH_KEY at line 23 and uses that resulting identity for every host collected at lines 45-48, including STAGING_MASTER_HOST and STAGING_VALIDATOR_HOST. Existing staging deployment explicitly installs only STAGING_SSH_KEY at .github/workflows/deploy-staging.yml:66-74, evidencing separate environment credentials.
    • Cause
      • The workflow performs credential selection once before constructing a mixed production/staging target list, rather than associating each target environment with its corresponding SSH key.
    • Fix
      • Install/select the SSH identity per target environment (production hosts use PROD_SSH_KEY; staging hosts use STAGING_SSH_KEY) and pass the matching identity to ssh_cmd; alternatively split production and staging into separate jobs with only their scoped credential.

    T-Rex Ran code and verified through T-Rex

  4. General comment

    P1 SSH access rollout accepts partial host failures

    • Bug
      • The workflow reports successful completion when one target succeeds and another fails, allowing a partial SSH-key/firewall rollout to pass.
    • Cause
      • After processing hosts, .github/workflows/ops-box-ssh-access.yml:76 evaluates test "$ok" -gt 0, which only requires at least one successful target.
    • Fix
      • Track the total number of intended hosts and require all of them to succeed (for example, test "$ok" -eq "$total"), or fail immediately for each unsuccessful target.

    T-Rex Ran code and verified through T-Rex

  5. General comment

    P1 Mutable checkout tag precedes privileged checked-out local action

    • Bug
      • .github/workflows/ops-box-ssh-access.yml line 18 checks out repository content via mutable actions/checkout@v4; line 32 then executes ./.github/actions/do-firewall, passing ${{ secrets.DIGITALOCEAN_TOKEN }} at line 35. The composite action maps the input to DO_TOKEN at .github/actions/do-firewall/action.yml:41 and uses it in DigitalOcean Bearer authentication at line 65.
    • Cause
      • The workflow trusts an unpinned third-party action tag before executing a local action from the resulting working tree with a privileged secret.
    • Fix
      • Pin actions/checkout to a full immutable commit SHA (with an audit comment/version reference if desired) before invoking the local action.

    T-Rex Ran code and verified through T-Rex

Reviews (1): Last reviewed commit: "ops: GHA inject box SSH pubkey + ufw on ..." | Re-trigger Greptile

Comment on lines +63 to +64
ufw allow OpenSSH || ufw allow 22/tcp || true
ufw --force enable || true

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Preserve production service ports

If the production host uses UFW's default-deny incoming policy, this workflow enables UFW after allowing only SSH. The production master serves traffic on ports 80, 443, and 8080, so dispatching it can block the public gateway and validator connection, causing a production outage.

Artifacts

Evidence from the check

  • The authored Bash script checks the exact workflow UFW commands and the repository's production port requirements; it encodes the narrow supplied finding.

Command output from the check

  • The captured repository excerpts show the SSH-only UFW enablement, production port publishing, Caddy HTTPS contract, and DigitalOcean firewall rules; they establish the compared static state.

Command output from the check

  • The executed validation script exits 0 after confirming SSH-only host-UFW setup alongside required production ports 80, 443, and 8080; the supplied finding is supported.

Evidence from the check

  • A minimal authored Bash harness stubs UFW failures and executes the workflow-equivalent remote command, ending with the finding that masked failures produce host success.

Command output from the check

  • The executed harness output shows all mocked UFW operations exit 42 yet the current block reports SUCCESS, while the fail-closed comparison reports FAIL, ending with the finding that errors are masked.

Command output from the check

  • The captured changed-file inspection shows `|| true` at lines 63-66 and the subsequent SUCCESS branch at lines 68-69, ending with the finding that the workflow can report a host successful after UFW failure.

View artifacts

T-Rex Ran code and verified through T-Rex

Comment on lines +63 to +66
ufw allow OpenSSH || ufw allow 22/tcp || true
ufw --force enable || true
ufw reload || true
ufw status || true

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Fail on UFW errors

Every UFW operation suppresses failures with || true. A missing UFW installation or failed allow, enable, reload, or status command still lets the SSH block report the host as successful, so the workflow can finish green without creating the requested firewall access.

Artifacts

Evidence from the check

  • The authored Bash script checks the exact workflow UFW commands and the repository's production port requirements; it encodes the narrow supplied finding.

Command output from the check

  • The captured repository excerpts show the SSH-only UFW enablement, production port publishing, Caddy HTTPS contract, and DigitalOcean firewall rules; they establish the compared static state.

Command output from the check

  • The executed validation script exits 0 after confirming SSH-only host-UFW setup alongside required production ports 80, 443, and 8080; the supplied finding is supported.

Evidence from the check

  • A minimal authored Bash harness stubs UFW failures and executes the workflow-equivalent remote command, ending with the finding that masked failures produce host success.

Command output from the check

  • The executed harness output shows all mocked UFW operations exit 42 yet the current block reports SUCCESS, while the fail-closed comparison reports FAIL, ending with the finding that errors are masked.

Command output from the check

  • The captured changed-file inspection shows `|| true` at lines 63-66 and the subsequent SUCCESS branch at lines 68-69, ending with the finding that the workflow can report a host successful after UFW failure.

View artifacts

T-Rex Ran code and verified through T-Rex

- name: Install SSH key
run: |
set -euo pipefail
KEY="${{ secrets.PROD_SSH_KEY || secrets.STAGING_SSH_KEY }}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Use staging SSH identity

When both credentials are configured, this selects PROD_SSH_KEY once and uses it for every target, including the staging hosts. The staging deployment uses STAGING_SSH_KEY separately, so staging hosts that accept only their scoped key cannot receive the box key and firewall update.

Artifacts

Evidence from the check

  • The authored shell validator asserts the exact workflow definitions and runs fixture key selection plus host-loop expansion, showing the test method.

Command output from the check

  • The executed staging-only fixture selects STAGING_SSH_KEY and emits attempts solely for the two staging hosts, establishing the scoped baseline.

Command output from the check

  • The executed mixed fixture selects PROD_SSH_KEY and emits attempts for both production and staging hosts, proving the credential-target mismatch.

View artifacts

T-Rex Ran code and verified through T-Rex

echo "::endgroup::"
done
echo "ok_hosts=$ok"
test "$ok" -gt 0

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Require all target hosts

The final assertion requires only one successful target. If another host rejects the SSH key or its update fails, the workflow still succeeds after updating a different host, silently leaving the rollout incomplete.

Artifacts

Evidence from the check

  • Minimal Bash harness simulating one successful and one failed target while applying the workflow's exact final predicate; it tests that partial success is accepted.

Command output from the check

  • Captured execution of the harness from `/home/user/repo`, showing one success, one failure, and an overall exit code of 0; the workflow condition permits partial rollout.

Command output from the check

  • Captured numbered workflow excerpt showing the success counter, failure branch, and `test "$ok" -gt 0` at line 76; the condition only requires one successful host.

View artifacts

T-Rex Ran code and verified through T-Rex

runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v4

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 security Pin privileged checkout action

This workflow resolves actions/checkout@v4 through a mutable tag before it runs the checked-out do-firewall action with the DigitalOcean token. If the tag is repointed or compromised, altered checkout behavior can replace the local firewall action before it receives that privileged token.

How this was verified: The workflow checks out through actions/checkout@v4 before passing DIGITALOCEAN_TOKEN to the checked-out firewall action.

Artifacts

Evidence from the check

  • The authored Bash script checks the workflow ordering and composite-action token path; it is the executable proof used for this validation.

Command output from the check

  • Captured execution output records lines 18, 32, 35, 41, and 65 and exits successfully, confirming the supplied security proof.

View artifacts

T-Rex Ran code and verified through T-Rex

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant