Removing backup.zip from S3 does not prove every public variant is gone. CloudFront cache keys, percent encoding, case differences, repeated slashes, alternate hostnames, query handling, and origin normalization can expose an old archive through a route that was not invalidated or scanned.
Use this after discovering a WordPress ZIP, tar, SQL, environment, or migration archive in a web root or S3 frontend bucket, especially when CloudFront or another CDN sits in front of the origin.
Quick answer
List the origin objects first, preserve access evidence, delete unauthorized archives, and test a controlled set of encoded and normalized URL variants without brute forcing unrelated paths. Invalidate the exact exposed keys plus any confirmed aliases, verify from multiple edges and hosts, then rotate secrets based on archive contents and observed access.
Test scenarios to run
Run the same controlled fixture across these branches. Write down the expected result before testing so a surprising response is easy to identify.
| Scenario | Fixture | Expected result |
| Exact key | Confirmed archive path | Origin is absent and edge returns the intended not-found behavior |
| Encoded key | Percent-encoded dot or space variant | No cache or function normalization reveals the archive |
| Alternate hostname | CloudFront domain and every public alias | All hosts apply the same deny and not-found policy |
| Query variation | Confirmed path with changed query values | Cache-key configuration cannot retrieve a stale archive object |
Diagnostic table
Use this table to connect the observed behavior to evidence and a verification step.
| Action | Evidence to collect | How to verify |
| Freeze object metadata, relevant logs, cache behavior, and archive inventory. | List S3 keys that match backup, archive, dump, migration, old, copy, zip, tar, gz, sql, env, and common case variants. | S3 recursive listings contain no unauthorized backup, SQL, environment, or migration archives. |
| Remove the unauthorized origin objects and block archive extensions in deployment policy. | Record CloudFront behavior, cache-key policy, origin path, URL normalization, alternate domain names, and viewer-request functions. | Exact, encoded, query, case, and alternate-host variants do not return archive bytes from CloudFront. |
| Invalidate confirmed public variants and review viewer-request normalization. | Test percent-encoded dots, spaces, slashes, case, duplicate separators, query strings, and expected redirect behavior for confirmed filenames. | CloudFront invalidations are complete and viewer-request normalization is documented. |
| Verify every hostname and edge path returns the intended safe response. | Check CloudFront and S3 access logs for each exact and normalized key before deleting evidence. | Secrets and data affected by the archive have named response owners and closure evidence. |
What to check first
- List S3 keys that match backup, archive, dump, migration, old, copy, zip, tar, gz, sql, env, and common case variants.
- Record CloudFront behavior, cache-key policy, origin path, URL normalization, alternate domain names, and viewer-request functions.
- Test percent-encoded dots, spaces, slashes, case, duplicate separators, query strings, and expected redirect behavior for confirmed filenames.
- Check CloudFront and S3 access logs for each exact and normalized key before deleting evidence.
- Inventory credentials, salts, customer data, database contents, and private files contained in any exposed archive.
Field notes
- Keep the variant list bounded to confirmed sensitive filenames and documented normalization behavior.
- A 403 from a private S3 origin is not proof that CloudFront no longer has a cached copy.
- Secret rotation depends on archive contents and access evidence, not just successful deletion.
Useful command or data shape
Adapt paths, IDs, and privacy handling to the site before running commands or storing data on production.
aws s3 ls s3://frontend-bucket/ --recursive --profile handl | grep -Ei '\.(zip|tar|tgz|gz|sql)$|backup|archive|dump|migration|\.env'
curl -sS -I --max-time 20 'https://example.com/backup.zip'
curl -sS -I --max-time 20 'https://example.com/backup%2Ezip'
curl -sS -I --max-time 20 'https://d111111abcdef8.cloudfront.net/backup.zip'
Why this usually happens
- An edge can retain an object after the S3 key is deleted until invalidation or expiration completes.
- Viewer-request functions and origin normalization can map several public strings to one internal object key.
- Teams often scan the website hostname but forget the CloudFront distribution hostname or alternate aliases.
Decision rule
Close exposure only when the origin contains no unauthorized archive, every confirmed public variant fails safely, edge logs show invalidation completion, and archive contents have a completed credential and data response.
Production verification checklist
- S3 recursive listings contain no unauthorized backup, SQL, environment, or migration archives.
- Exact, encoded, query, case, and alternate-host variants do not return archive bytes from CloudFront.
- CloudFront invalidations are complete and viewer-request normalization is documented.
- Secrets and data affected by the archive have named response owners and closure evidence.
Safe fix order
Use a sequence that makes each result easy to prove. Stop when new evidence changes the scope or owner of the problem.
- Freeze object metadata, relevant logs, cache behavior, and archive inventory.
- Remove the unauthorized origin objects and block archive extensions in deployment policy.
- Invalidate confirmed public variants and review viewer-request normalization.
- Verify every hostname and edge path returns the intended safe response.
- Rotate exposed secrets, notify data owners, and monitor repeated requests.
Mistakes to avoid
- Do not test only the pretty website URL.
- Do not assume origin deletion evicts every edge object immediately.
- Do not publish the sensitive filename and variant list in a public issue.
- Do not close the incident before reviewing the archive contents and access logs.
Questions teams ask during testing
Should I invalidate /*?
Use the narrowest confirmed paths that reliably remove the exposure unless evidence shows the cache behavior is broader. A full invalidation can create unnecessary origin load.
Why test the CloudFront hostname?
It may bypass application redirects or host controls applied only to the branded domain.
Does 404 prove the file was never accessed?
No. Historical access logs and secret rotation address past exposure; the current response only proves present reachability.
What to tell the client or owner
Share sensitive key inventory, affected hosts, tested variants, origin deletion time, invalidation IDs, completion time, historical access evidence, archive contents, rotated secrets, and monitoring owner.
When HandL WP should help
Bring in help when this affects leads, checkout, search visibility, security, paid media reporting, or a client production site. HandL WP can trace the issue through WordPress, hosting, cache, tracking, and Search Console, then verify the workflow after the technical fix.
If this is active on a production site, remove a cached WordPress backup exposure.
Related HandL WP guides
Use these related guides when the same issue touches tracking, security, checkout, or crawler visibility.
Helpful references