Where does the bug appear (feature/product)?
Somewhere else…
Describe the Bug
We’re running cloud agents and hitting a 401 when Composer tries to download a package from a private registry (advancedtables.privato.pub) during the start step.
Steps to Reproduce
What we do:
In install.sh we run:
composer config --auth http-basic.advancedtables.privato.pub
“$FILAMENT_ADVANCED_TABLES_PLUGIN_EMAIL”
“$FILAMENT_ADVANCED_TABLES_PLUGIN_KEY”
composer install
Both FILAMENT_ADVANCED_TABLES_PLUGIN_EMAIL and FILAMENT_ADVANCED_TABLES_PLUGIN_KEY are set as Cursor Team Secrets and validated
The error (from the start step):
Downloading archilex/filament-filter-sets (v3.8.12)
The ‘https://advancedtables.privato.pub/composer/11/153/download’ URL required authentication (HTTP 401).
You must be using the interactive console to authenticate
Our question: Does the Cursor cloud VM strip or intercept outbound HTTP Basic Auth headers to external hosts? Or is there a reason the auth.json written during the install step would not be available during the start step (e.g. workspace snapshot does not preserve gitignored files)?
Any guidance on how to correctly pass Composer HTTP Basic credentials to a private registry in the cloud agent environment would be much appreciated.
Operating System
MacOS
Version Information
Cloud agents
For AI issues: which model did you use?
Sonnet 4.6
Does this stop you from using Cursor
Yes - Cursor is unusable
It’s unlikely that auth headers are being stripped, but we can quickly rule it out. The more likely cause is that PHP Composer’s file-based auth (auth.json) isn’t available when the download actually happens.
The cleanest fix is to bypass file-based auth entirely and use PHP Composer’s built-in COMPOSER_AUTH environment variable. Since Cursor Team Secrets are injected as env vars, Composer will read them automatically.
Option A (single secret, recommended): Create a new Cursor Team Secret:
Then remove the composer config --auth line from your script. Composer will use the env var for all auth automatically.
Option B (keep your two existing secrets): Add this to the top of your script before composer install:
export COMPOSER_AUTH="{\"http-basic\": {\"advancedtables.privato.pub\": {\"username\": \"$FILAMENT_ADVANCED_TABLES_PLUGIN_EMAIL\", \"password\": \"$FILAMENT_ADVANCED_TABLES_PLUGIN_KEY\"}}}"
If the COMPOSER_AUTH approach still results in a 401, that would tell us the issue is at the network/proxy layer rather than file persistence, and we’d investigate further on our end.
One clarifying question: is install.sh configured as the install command or the start command in your environment setup?
install.sh is our install command, start.sh is our start command (see environment.json). So install → snapshot → start is exactly the flow where the auth.json was being lost.
We’ve implemented Option B — exporting COMPOSER_AUTH from our two existing secrets in both scripts. However, we’re still getting the same 401. Here are the relevant sections:
install.sh (install command):
export COMPOSER_AUTH="{\"http-basic\":{\"advancedtables.privato.pub\":{\"username\":\"$FILAMENT_ADVANCED_TABLES_PLUGIN_EMAIL\",\"password\":\"$FILAMENT_ADVANCED_TABLES_PLUGIN_KEY\"}}}"
cd /workspace/backend
composer install --no-interaction --prefer-dist --optimize-autoloader
start.sh (start command):
export COMPOSER_AUTH="{\"http-basic\":{\"advancedtables.privato.pub\":{\"username\":\"$FILAMENT_ADVANCED_TABLES_PLUGIN_EMAIL\",\"password\":\"$FILAMENT_ADVANCED_TABLES_PLUGIN_KEY\"}}}"
cd /workspace/backend
composer install --no-interaction --prefer-dist --optimize-autoloader
Both FILAMENT_ADVANCED_TABLES_PLUGIN_EMAIL and FILAMENT_ADVANCED_TABLES_PLUGIN_KEY are confirmed present — our secrets-guard.sh (sourced just before these lines) would have exited with an error if they were missing, and the run continues past that point. The 401 still appears when Composer tries to download the package. This would suggest the issue may be at the network/proxy layer after all — could you investigate on your end?
Thanks for the detailed follow-up and for confirming the install/start setup.
We’ve been investigating on our end. To narrow this down, could you add these diagnostic lines to your install.sh right before composer install and share the output?
echo "=== auth debug ==="
# 1) Verify COMPOSER_AUTH is valid JSON after shell expansion
echo "$COMPOSER_AUTH" | python3 -c "
import json, sys
try:
d = json.load(sys.stdin)
keys = list(d.get('http-basic', {}).keys())
print(f'COMPOSER_AUTH: valid JSON, domains: {keys}')
except Exception as e:
print(f'COMPOSER_AUTH: INVALID JSON — {e}')
"
# 2) Test the credentials directly via curl (bypasses Composer)
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" \
-u "$FILAMENT_ADVANCED_TABLES_PLUGIN_EMAIL:$FILAMENT_ADVANCED_TABLES_PLUGIN_KEY" \
https://advancedtables.privato.pub/composer/packages.json)
echo "Direct curl test: HTTP $HTTP_CODE"
echo "=== end debug ==="
How to read the results:
-
COMPOSER_AUTH says “INVALID JSON” - the nested shell escaping is breaking the JSON. The fix is Option A: create a single COMPOSER_AUTH team secret with the full JSON pre-baked ({"http-basic":{"advancedtables.privato.pub":{"username":"your-email","password":"your-key"}}}). This bypasses shell escaping entirely since the JSON is stored as-is and injected directly as an env var.
-
Curl returns 200 but Composer still 401s - the network path and credentials are fine; the issue is purely in how Composer reads the env var. Option A would fix this too.
-
Curl returns 401 - the issue is upstream of Composer. Share the output and we’ll dig deeper into the network path on our end.
If you’d rather skip the diagnostics, trying Option A directly is the fastest path - it eliminates both shell escaping and any env var delivery issues in one step.
Added the diagnostics to install.sh. Output from the install step:
=== auth debug ===
COMPOSER_AUTH: valid JSON, domains: ['advancedtables.privato.pub']
Direct curl test: HTTP 401
=== end debug ===
Composer still returns 401 during package download. [Add which case applies based on the output above.]