Blog Logo

25-Jul-2025 ~ 3 min read

Incognito Shell - Isolating Credentials with Subshells in Bash


In Bash scripting, subshells are created using parentheses () and are often used for parallel execution or simple scoping. But there’s another use case that can greatly enhance script hygiene and security: creating isolated execution environments for sensitive operations. Think of it as running your logic in an incognito tab: temporary, scoped, and self-cleaning.

Let’s explore this concept with a real-world use case: provisioning a Google Cloud VM instance using temporary authentication in a throwaway environment.

💡 What is an Incognito Shell?

An Incognito Shell is a term (coined for clarity here) describing the use of a Bash subshell to temporarily:

  • Export environment variables
  • Authenticate using credentials
  • Perform a sequence of commands
  • Automatically clean up afterwards

Unlike the main shell, the subshell doesn’t persist variables or config beyond its scope, making it ideal for handling credentials and other sensitive state.

📄 Example Use Case: GCE Instance Creation Script

Consider the following shell script that provisions a Google Compute Engine (GCE) instance using a service account key. Credentials are scoped inside a subshell, preventing them from leaking into the outer environment.

#!/bin/bash
set -euxo pipefail

# Constants
INSTANCE_NAME="instance-1"
PROJECT_ID="my-project-id"
ZONE="asia-south1-a"
MACHINE_TYPE="e2-micro"
HARDDISK_SIZE_GB=10
KEY_FILE="$(realpath ../docker_k/dockerbuild.json)"

# Begin Incognito Shell
(
  TEMP_DIR=$(mktemp -d)
  export CLOUDSDK_CONFIG="$TEMP_DIR"

  # Authenticate using temporary config dir
  gcloud auth activate-service-account --key-file="${KEY_FILE}" || {
      echo "❌ Failed to authenticate with the provided key file."
      exit 1
  }

  gcloud config set project "${PROJECT_ID}"

  # Check for existing instance
  if gcloud compute instances describe "${INSTANCE_NAME}" \
      --project="${PROJECT_ID}" \
      --zone="${ZONE}" >/dev/null 2>&1; then
          echo "❌ Instance '${INSTANCE_NAME}' already exists."
          exit 1
  else
          echo "✅ Instance '${INSTANCE_NAME}' does not exist. Proceeding."
  fi

  # Create instance
  gcloud compute instances create "${INSTANCE_NAME}" \
      --project="${PROJECT_ID}" \
      --zone="${ZONE}" \
      --machine-type="${MACHINE_TYPE}" \
      --network-interface=network-tier=PREMIUM,stack-type=IPV4_ONLY,subnet=default \
      --can-ip-forward \
      --maintenance-policy=MIGRATE \
      --provisioning-model=STANDARD \
      --service-account=1070710XXXXXX-compute@developer.gserviceaccount.com \
      --scopes=https://www.googleapis.com/auth/devstorage.read_only,\
https://www.googleapis.com/auth/logging.write,\
https://www.googleapis.com/auth/monitoring.write,\
https://www.googleapis.com/auth/service.management.readonly,\
https://www.googleapis.com/auth/servicecontrol,\
https://www.googleapis.com/auth/trace.append \
      --tags=http-server,https-server \
      --create-disk=auto-delete=yes,boot=yes,device-name=${INSTANCE_NAME},\
image=projects/debian-cloud/global/images/debian-12-bookworm-v20250709,\
mode=rw,size=${HARDDISK_SIZE_GB},type=pd-balanced \
      --no-shielded-secure-boot \
      --shielded-vtpm \
      --shielded-integrity-monitoring \
      --labels=goog-ec-src=vm_add-gcloud \
      --reservation-affinity=any

  # Subshell exits here, temp config and auth are discarded
)

🧼 Why Use a Subshell?

  1. Credential Isolation: Sensitive variables (e.g., CLOUDSDK_CONFIG) and temp auth tokens don’t leak into your shell history or environment.

  2. Automatic Cleanup: The temporary directory (mktemp -d) vanishes with the subshell. No trap needed.

  3. Safe Failures: If something fails inside, it doesn’t pollute your outer environment. This makes debugging and rerunning safer.

  4. Reusability: You can easily copy/paste or reuse the subshell logic in other scripts without worrying about side effects.

🔄 Alternative Without Subshell

You could manually clean up, but it’s messier:

export CLOUDSDK_CONFIG=$(mktemp -d)
# ...
# Then remember to clean it up
rm -rf "$CLOUDSDK_CONFIG"
unset CLOUDSDK_CONFIG

This approach is error-prone and easy to forget, especially in larger scripts.

🧠 Pro Tip: Nesting Incognito Shells

You can nest subshells for nested scopes. For instance, authenticating with one service inside a broader scoped environment (e.g., Terraform, Docker, etc.).

(
  export AWS_CONFIG_FILE="$(mktemp)"
  (
    export CLOUDSDK_CONFIG="$(mktemp -d)"
    # Do GCP stuff here
  )
  # Do AWS stuff here
)

✅ Conclusion

The humble Bash subshell offers a lightweight, elegant way to sandbox parts of your script, especially when dealing with temporary credentials or environment state. By thinking of it as an “Incognito Shell”, you can write cleaner, safer, and more maintainable scripts.