You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
#820's alias-ownership fix is merged but not deployed — GHSA-q9qq-223w-mqx6 is still live #859
PR #836 closed #820 and the advisory was published. The fix is not running in production.
spawn-dns-updater's LastModified is 2026-06-25T06:20:28. PR #836 merged in October. Confirmed against the deployed bytes rather than inferred from the date — downloaded via get-function's Code.Location and grepped the binary:
ABSENT : _spore-owner
ABSENT : aliasSubdomainOwner
ABSENT : authorizeCaller
ABSENT : DNS_AUTHZ_MODE
ABSENT : must be an IPv4 literal
PRESENT : aliasDNSName
aliasDNSName being present is the control: it proves the grep works on this binary and that the absences are real, not an invocation artefact. The deployed function therefore still builds the friendly alias from req.AccountName with no ownership check, which is GHSA-q9qq-223w-mqx6 exactly: any caller can UPSERT or DELETE {record}.{any-other-tenant-slug}.spore.host.
The ip_address validation from #835 is likewise not deployed.
Why it wasn't deployed
scripts/deploy-custom-dns.sh was unsafe to run until PR #858, which is the direct cause of the four-month gap. It granted IAM to SpawnDNSLambdaRole (a role that does not exist — the function runs under SpawnDNSLambdaExecutionRole), and its update path passed --environment Variables={...}, which would have deleted DOMAIN_ZONES, the only variable the live function has. Both fixed in #858.
Verify the deployed bytes, not the API's 200: re-run the grep above and expect _spore-owner and aliasSubdomainOwner PRESENT.
Confirm DOMAIN_ZONES survives the deploy (get-function-configuration --query 'Environment.Variables' before and after; expect zero drift plus whatever is deliberately added).
Check whether the live _spore-owner markers need seeding for the two existing alias tenants, or whether first-caller-claims is acceptable for them.
The general problem
This is the "merged != deployed" gap for the hand-deployed Lambdas, and nothing warns. The reaper stack sat untouched 2026-07-31 to 2026-10-04 while the CLI went v0.9x to v0.116.0. A published advisory whose fix is in main but not in production is the worst case of it, because the advisory asserts the fix shipped.
Worth considering: a check that compares each deploy script's target function's CodeSha256 against a locally-built zip (deploy-sweep-orchestrator.sh already does this for itself), run as a census rather than per-deploy.
Deploy spawn-dns-updater from main with the fixed script.LastModified 2026-06-25 → 2026-10-12T16:32:59Z; CodeSha256OmdRFNPs… → 4ms+TCaL….
Verify the deployed bytes, not the API's 200. Re-ran the grep from this issue against the newly downloaded artifact, this time with literals first confirmed to be real string literals in source (not comment text — that mistake produced a false "absent" earlier today), plus a negative control:
PRESENT : _spore-owner
PRESENT : must be an IPv4 literal
PRESENT : is not registered in
PRESENT : zone %s returned no records at all
ABSENT : <sentinel> (so the grep discriminates)
Confirm DOMAIN_ZONES survives. It does — this is the Authorize DNS-updater callers against the account registry (#835) #858 merge-not-replace fix working on its first real use. Before: {DOMAIN_ZONES: spore.host=Z0341053304H0DQXF6U4X}. After: that value unchanged, plus DEFAULT_DOMAIN, HOSTED_ZONE_ID, DNS_ALLOWED_ACCOUNTS, DNS_ACCOUNTS_TABLE. Under the old script this deploy would have deleted DOMAIN_ZONES.
Check whether _spore-owner markers need seeding. They don't. mycelium-development still has its two CNAMEs pointing at *.5k0zfnmq.spore.host, so aliasSubdomainOwner infers the owner as 435415984226 from the zone's own state, exactly as designed, and first-caller-claims will record the marker on the next write. No manual seeding.
Also: runtime provided.al2023 and arch x86_64 unchanged (the script builds GOARCH=amd64, checked against the live arch before deploying — an arm64 build would have been an exec-format failure), log retention set to 30 days, and spawn:version=0.127.0-34-g5610712 stamped.
One regression I introduced and reversed
Running the script executed its Step 5/6, which I had not audited when fixing the script in #858. It created a REST API spawn-dns-api (tcdwlpysn2) with POST /update-dns at authorizationType: NONE and added an apigateway-invoke statement to the function's resource policy — a public, unauthenticated endpoint into the DNS updater, created at 16:33Z.
It could not write DNS: a probe returned 502, because the handler takes a Function URL event (LambdaFunctionURLRequest) and API Gateway REST sends a different shape, so the integration is incompatible. The zone stayed at 17 records. But it was still an unauthenticated public invoke path on a billable function.
Both are gone — API deleted, statement removed, resource policy back to its pre-deploy shape and then narrowed per #835. Nothing depended on it: both /spawn/dns/* SSM parameters are absent, and spored uses the Function URL (…lambda-url.us-east-1.on.aws, AWS_IAM).
Filed as #870, because the script will recreate it for the next person.
Noted, not actioned
The function carries a managedby: opentofu tag alongside spawn:created-by: deploy-custom-dns.sh. If there is live OpenTofu state for this function, a script deploy puts it in drift. Worth confirming which tool is meant to own it.
Closing — the advisory's fix is now actually running.
Activity
scttfrdmn commentedon Oct 12, 2026
Deployed and verified. GHSA-q9qq-223w-mqx6 is remediated in production.
Deploy
spawn-dns-updaterfrommainwith the fixed script.LastModified2026-06-25 → 2026-10-12T16:32:59Z;CodeSha256OmdRFNPs…→4ms+TCaL….Verify the deployed bytes, not the API's 200. Re-ran the grep from this issue against the newly downloaded artifact, this time with literals first confirmed to be real string literals in source (not comment text — that mistake produced a false "absent" earlier today), plus a negative control:
_spore-owneris the alias-ownership marker, so Resolve the DNS alias owner server-side instead of from the request body #820's fix is live.Confirm
DOMAIN_ZONESsurvives. It does — this is the Authorize DNS-updater callers against the account registry (#835) #858 merge-not-replace fix working on its first real use. Before:{DOMAIN_ZONES: spore.host=Z0341053304H0DQXF6U4X}. After: that value unchanged, plusDEFAULT_DOMAIN,HOSTED_ZONE_ID,DNS_ALLOWED_ACCOUNTS,DNS_ACCOUNTS_TABLE. Under the old script this deploy would have deletedDOMAIN_ZONES.Check whether
_spore-ownermarkers need seeding. They don't.mycelium-developmentstill has its two CNAMEs pointing at*.5k0zfnmq.spore.host, soaliasSubdomainOwnerinfers the owner as 435415984226 from the zone's own state, exactly as designed, and first-caller-claims will record the marker on the next write. No manual seeding.Also: runtime
provided.al2023and archx86_64unchanged (the script buildsGOARCH=amd64, checked against the live arch before deploying — an arm64 build would have been an exec-format failure), log retention set to 30 days, andspawn:version=0.127.0-34-g5610712stamped.One regression I introduced and reversed
Running the script executed its Step 5/6, which I had not audited when fixing the script in #858. It created a REST API
spawn-dns-api(tcdwlpysn2) withPOST /update-dnsatauthorizationType: NONEand added anapigateway-invokestatement to the function's resource policy — a public, unauthenticated endpoint into the DNS updater, created at 16:33Z.It could not write DNS: a probe returned 502, because the handler takes a Function URL event (
LambdaFunctionURLRequest) and API Gateway REST sends a different shape, so the integration is incompatible. The zone stayed at 17 records. But it was still an unauthenticated public invoke path on a billable function.Both are gone — API deleted, statement removed, resource policy back to its pre-deploy shape and then narrowed per #835. Nothing depended on it: both
/spawn/dns/*SSM parameters are absent, and spored uses the Function URL (…lambda-url.us-east-1.on.aws,AWS_IAM).Filed as #870, because the script will recreate it for the next person.
Noted, not actioned
The function carries a
managedby: opentofutag alongsidespawn:created-by: deploy-custom-dns.sh. If there is live OpenTofu state for this function, a script deploy puts it in drift. Worth confirming which tool is meant to own it.Closing — the advisory's fix is now actually running.