D4: setup-deploy reports Render API key presence only

/setup-deploy ran 'echo $RENDER_API_KEY | head -c 4', printing the
key's first bytes into the transcript. It now prints only
'RENDER_API_KEY: set' or 'RENDER_API_KEY: not set'. Wording follows the
#2971 port of #1096; a test also guards against any setup-deploy command
echoing a credential variable.

Co-authored-by: jacob-wang <jiayuw794@gmail.com>
This commit is contained in:
garrytanandjacob-wang committed 2026-10-03 21:10:54 +00:00
1 parent 64638f3978
commit 0d9ebd27ec
2 files changed
+43 -1

No files matched your search

+8 -1
View File
@@ -99,7 +99,14 @@ Ask the user to confirm the production URL. Some Fly apps use custom domains.
If `render.yaml` detected:
1. Extract service name and type from render.yaml
2. Check for Render API key: `echo $RENDER_API_KEY | head -c 4` (don't expose the full key)
2. Check only whether the Render API key is set. Never print any key bytes, including a prefix:
```bash
if [ -n "${RENDER_API_KEY:-}" ]; then
echo "RENDER_API_KEY: set"
else
echo "RENDER_API_KEY: not set"
fi
```
3. Infer URL: `https://{service-name}.onrender.com`
4. Render deploys automatically on push to the connected branch — no deploy workflow needed
5. Set health check: the inferred URL
+35
View File
@@ -0,0 +1,35 @@
/**
* D4 (#1078): /setup-deploy ran `echo $RENDER_API_KEY | head -c 4`, printing
* the key's first bytes into the transcript. It now reports presence only.
*/
import { describe, test, expect } from 'bun:test';
import { spawnSync } from 'child_process';
import * as fs from 'fs';
import * as path from 'path';
const SKILL = fs.readFileSync(path.resolve(import.meta.dir, '..', 'setup-deploy', 'SKILL.md'), 'utf-8');
const KEY = 'rnd_D4testKeyValue1234567890';
describe('D4: setup-deploy reports Render key presence, never key bytes', () => {
const at = SKILL.indexOf('Check only whether the Render API key is set');
const block = SKILL.slice(at).match(/```bash\n([\s\S]*?)\n```/)?.[1] ?? '';
test('the check runs and prints only set / not set', () => {
expect(at).toBeGreaterThanOrEqual(0);
const run = (env: Record<string, string>) => spawnSync('bash', ['-c', block], {
env: { PATH: process.env.PATH!, ...env }, encoding: 'utf-8', timeout: 10_000,
});
const set = run({ RENDER_API_KEY: KEY });
expect(set.stdout).toBe('RENDER_API_KEY: set\n');
expect(set.stdout).not.toContain(KEY.slice(0, 4));
expect(run({}).stdout).toBe('RENDER_API_KEY: not set\n');
});
test('no setup-deploy command prints a credential variable value', () => {
const fences = [...SKILL.matchAll(/```bash\n([\s\S]*?)\n```/g)].map(m => m[1]).join('\n');
const inline = [...SKILL.matchAll(/`([^`\n]*)`/g)].map(m => m[1]).join('\n');
for (const text of [fences, inline]) {
expect(text).not.toMatch(/(echo|printf)[^\n|;]*\$\{?[A-Z0-9_]*(API_KEY|TOKEN|SECRET)\b/);
}
});
});