Skip to content

Refactor proxying for all adapters - #5

Merged
aram356 merged 1 commit into
mainfrom
feature/refactor-proxy
Oct 7, 2025
Merged

Refactor proxying for all adapters#5
aram356 merged 1 commit into
mainfrom
feature/refactor-proxy

Conversation

@aram356

Copy link
Copy Markdown
Contributor

No description provided.

@aram356
aram356 merged commit df88e0d into mainOct 7, 2025
2 checks passed
@aram356
aram356 deleted the feature/refactor-proxy branch October 7, 2025 22:16
aram356 added a commit that referenced this pull request Aug 2, 2026
Blocking #1 -- symlink escapes in gitignored local state.
`.edgezero/` and the env files are gitignored, so a symlink planted in
either never surfaces in review, and both write paths followed it:
- `env_file::append_lines_dedup_with_header` used `path.exists()` +
`fs::write`, which follow a symlinked final component. A planted
`.env -> ~/.ssh/authorized_keys` had provision write attacker-chosen
`KEY=value` lines into the target, and `set_restrictive_mode` then
chmod 0600'd the victim's file. A DANGLING link is worse: `fs::write`
creates the target. Now rejected via `symlink_metadata`, which does
not follow links.
- `ProvisionLock::acquire` ran `create_dir_all` + `OpenOptions::create`
on `.edgezero/provision.lock`, taking an flock on -- and holding a
writable descriptor to -- a file outside the tree.
- The dry-run staging copy vetted symlinked entries *inside* the tree it
walked but not the root it was handed, so a symlinked `.edgezero`
would have it copy e.g. `~/.aws` into the operator-visible staging dir.
`path_safety::reject_symlink_components` already implemented the bounded
component walk for manifest-declared paths; it is now pub(crate) with a
field-agnostic message and reused by the two CLI sites. `env_file` lives
in `edgezero-adapter` and has no project root to bound a walk against,
so it guards its final component only -- the parent chain remains the
resolving caller's job.
Blocking #5 -- lossy derivations collapsing two values onto one target.
Two independent axes, both silent and both serving the wrong value:
- Fastly derives each secret's Viceroy env var as
`key.to_ascii_uppercase()`, and `upsert_secret_store_entry` dedups on
the exact key -- so `api_token` and `API_TOKEN` produced two separate
`fastly.toml` rows that BOTH read `$API_TOKEN`. Now caught by
`validate_typed_secrets`, which was a no-op stub. Cloudflare's stub is
correct and stays: it never derives anything from the secret key.
- Cloudflare AND Fastly both upper-case `store.logical` into
`EDGEZERO__STORES__<KIND>__<LOGICAL>__NAME`. TOML keys are
case-sensitive, so `[stores.kv.myStore]` and `[stores.kv.MYSTORE]` are
two real stores emitting one variable, and env_file's dedup silently
dropped the loser -- leaving that store pointed at the other's
platform name. Guarded once in `ProvisionStores`, called by both.
Kind is part of the variable name, so cross-kind id reuse still works.
Tests cover each escape and each collision, asserting the victim file is
byte-identical / the link target was never created, plus the negative
cases (exact duplicate ids, same id across kinds, one key in two stores)
so the guards don't over-reject.
aram356 added a commit that referenced this pull request Aug 19, 2026
…ects
Two P0 blockers (both live-verified):
- Spin build no longer TRUNCATES its own artifact. `refresh_declared_source`
compared lexical paths, so the default `source` (`../../target/.../x.wasm`,
a relative path with `..`) never matched the normalised artifact and
`fs::copy` copied the file onto itself -> 0 bytes. Now guarded by a
canonicalize-based same-file check (also for the conventional refresh), plus
containment (refuse a `source` resolving outside the workspace or through a
symlink) and single-component matching (#1, #5).
- Fresh Cloudflare scaffolds can build/serve/deploy. The synthesised
`wrangler.toml` now declares `[build] command = "worker-build --release"`
(main points at the worker-build-generated shim), and the adapter drops its
`[commands]` shell block so build/serve/deploy route through the registry
dispatch, which passes `--config <manifest>` (also fixes custom manifest
paths being ignored) (#2, #7).
Spin:
- `[adapters.spin.adapter].cloud = true` is the SOLE Fermyon Cloud selector;
the legacy deploy-command heuristic and its `manifest_adapter_deploy_cmd`
field are removed, and `config diff` threads the flag like `config push` (#3).
- `edgezero serve` forwards parent-shell `EDGEZERO__*` overrides to the guest
via `spin up --env` (highest precedence) so a shell override reaches the
sandboxed component (#4).
- deploy uses `spin cloud deploy` (bare `spin deploy` needs a plugin on
Spin 3+/4) (#6).
Cloudflare / Axum (via subagents):
- typed secret keys are validated for `.dev.vars` round-trip (empty/=/#/
newline/whitespace) (#16); local push refuses a `.wrangler` symlink escape
(#11); axum runtime honours `EDGEZERO_MANIFEST` when locating `.edgezero`
(#8).
Fastly:
- cloud provision now writes the per-store `__NAME` runtime mappings into
`edgezero_runtime_env` so a renamed cloud store is reachable (#10); the
dry-run preflight redacts malformed-manifest parse errors and models the
real writer's inline-toml rejection (#13).
Convergence (via subagent): reprovisioning converges managed `__NAME`
overlays across env_file + all four adapters via a new
`upsert_lines_with_header` (#9).
CLI:
- dry-run staging refuses a TMPDIR inside the project (self-recursive copy)
and no longer follows a symlinked live path into the diff output (#12);
- cloud provision preflights manifest writability before mutating the account,
so an unwritable manifest can't orphan a created resource (#15).
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@aram356