From 4836e36f65c387ad3bf59f7946605942b1e7f2d0 Mon Sep 17 00:00:00 2001 From: Siddhant Medar Date: Wed, 15 Apr 2026 09:01:35 -0500 Subject: [PATCH] harden pipeline per PR review: locked lockfile, token permissions, image comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Replace 'uv sync --frozen' with 'uv sync --locked'. --frozen silently uses a stale lockfile if pyproject.toml is updated without regenerating uv.lock, masking missed dependencies. --locked fails loudly with a clear error when the lockfile is out of sync. Verified empirically with uv 0.9.14: --frozen exits 0 on mismatch, --locked exits 1. 2. Add 'chmod 600' on the OIDC token file after writing it. The container is already single-user root so this is defensive/cosmetic, but it silences security scanners and signals intent. 3. Add a comment explaining why gate steps use atlassian/default-image:4 instead of python:3.12.7 (gates run bash only, no Python toolchain needed — lighter image, faster pull). Explicitly rejected from the PR review: - Token-masking sed mitigation (delimiter collision with / in real Bitbucket clone tokens; cmd | sed || exit 1 swallows git failures without set -o pipefail). Bitbucket's built-in Secured variable masking is the correct mitigation and is already documented as a setup requirement. - SSH key alternative for git clone (architecturally worse — more secrets to manage; HTTPS+Secured is the Bitbucket-recommended pattern). - cd/python refactor ('fragile logic bug'). Verified empirically that 'cd X && python Y || echo Z' with set -e correctly catches both cd and python failures via the ||. The step exits 0 as intended by the 'advisory, not a gate' design. The suggested refactor would introduce a hard-fail regression. --- bitbucket-pipelines.yml | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/bitbucket-pipelines.yml b/bitbucket-pipelines.yml index b8ac02d..a8392dc 100644 --- a/bitbucket-pipelines.yml +++ b/bitbucket-pipelines.yml @@ -46,10 +46,12 @@ definitions: scripts: # Installs the uv package manager (pinned to avoid surprise breaks), - # then syncs both dev and test dependency groups from pyproject.toml + # then syncs both dev and test dependency groups from pyproject.toml. + # --locked (NOT --frozen) asserts uv.lock matches pyproject.toml and + # fails loudly on mismatch. --frozen would silently use a stale lockfile. - script: &install pip install uv==0.11.5; - uv sync --frozen --group dev --group test; + uv sync --locked --group dev --group test; # --------------------------------------------------------------------------- # Reusable step definitions @@ -116,8 +118,11 @@ definitions: - export AWS_REGION=us-east-1 - export AWS_ROLE_ARN="arn:aws:iam::975049960860:role/DoczyAI-Bitbucket-OIDC" - export AWS_WEB_IDENTITY_TOKEN_FILE="$(pwd)/web-identity-token" - # printf (not echo) avoids appending a trailing newline to the JWT + # printf (not echo) avoids appending a trailing newline to the JWT. + # chmod 600 restricts the token file to owner-only (defensive — + # the container is already single-user root, but silences scanners). - printf '%s' "$BITBUCKET_STEP_OIDC_TOKEN" > "$(pwd)/web-identity-token" + - chmod 600 "$(pwd)/web-identity-token" # Clone the review agent repo (private — needs BITBUCKET_CLONE_TOKEN) # SETUP REQUIRED: set BITBUCKET_CLONE_TOKEN (marked "Secured") in @@ -181,6 +186,9 @@ pipelines: # Feature branches represent new functionality. They must go through # dev first for integration testing before promotion to stg/main. "feature/*": + # Gate steps below use atlassian/default-image:4 (not python:3.12.7) + # because gates only run bash/shell — no Python needed. The default + # image is lighter and avoids pulling a full Python toolchain. - step: name: "Gate: feature → dev" image: atlassian/default-image:4