When no instance domain is set, invitation links were built from the
request host, which a client can spoof through a forwarded Host header.
Links now always use base_url(). The fallback test now forces a spoofed
root URL and checks that the link ignores it.
- Treat a commit value on the preview endpoint as a preview change
- Update the API docs, the MCP tool description, and the change file
- Add a test case
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Remove tests that only check markup, CSS, static text, wire:key strings,
framework behavior, copied app logic, or expect(true)
- Replace source-grep and Reflection checks of security fixes with tests
that run the real code (shell quoting, locked properties, 403 checks,
webhook fork trust, log redaction, Sentinel token cleanup)
- Assert response bodies and unchanged data on API error paths
- Run the Traefik version job through handle() instead of private methods
- Update stale tests for scheduled task props, the default Postgres image,
and the disabled transfer link of unvalidated servers
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The backup upload returned a hard-coded 500 when the database uuid was
unknown or belonged to another team. It now returns 404 with the same
JSON error shape that the import form reads.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Drop the RejectPublishedAppKey middleware and its registration in the
HTTP kernel, so requests are no longer refused with a 503 when APP_KEY
or APP_PREVIOUS_KEYS matches a key shipped in the repository.
Rename PublishedAppKeyTest to DecryptWithoutClassesTest and keep only
the checks that Sentinel tokens and team channel payloads are decrypted
without unserializing objects.
- Require the write permission and update policy to open a preview or
change its pull request URL, git type, or docker tag via the API;
deploy-only tokens can only redeploy an existing preview
- Reject rollbacks to commits that are neither a listed rollback image
nor a successful production deployment (GetRollbackImages::allows)
- Validate git_repository with ValidGitRepositoryUrl when it changes on
application update
- Add RejectPublishedAppKey global middleware
- Show a "still starting" message when the root setup window is pending
- Document the new 403 responses and constraints in the OpenAPI spec
- Add tests for the new checks
- Use the limits of the API token in more permission checks.
- Show a clearer message when a token limit blocks a change.
- Describe API tokens with limits in SECURITY.md.
Scanning is now controlled per server and per app. Each server downloads
the Grype database from its default source.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Show a clear message when team-wide write access is needed to use
team credentials.
- Reset the S3 selection on the backup page when a change is not allowed.
- Do not save database backups to S3 when the API request does not
send save_s3, as the API documentation says.
On self-hosted, a validation that connects now clears force_disabled. The unreachable cleanup skips the localhost server, and the server page explains why a server is disabled. Cloud and transferred servers stay disabled.
Closes#12475
An empty port routes to the required port, so it needs no confirmation.
The edit dialog shows the effective port, the warning buttons name the
ports, and domain conflicts ignore the container port.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Restores, downloads, and the import check refuse an SFTP storage without a saved host key.
- Only Validate, Save, Create, and the API validate endpoint save a new key; backup and
revalidation jobs do not.
- An endpoint change or a host key reset marks the storage unusable.
- Save the key only when the endpoint did not change during the connection test.
- Queue a status sync for deployments that Init, fail_undispatchable_deployment, and
superseded cancels change with a query update, so GitHub does not show them as
in progress forever.
- Run SyncGithubDeploymentJob on the default queue with 10 s GitHub request timeouts
and a 100 s job timeout, so a slow GitHub cannot delay deployments.
The gate treated a busy server scan lock as a scan error after 120 s, so a gated
deploy with Block failed while another scan ran. It now waits in steps, bounded by the
deployment job timeout, and still honors a cancel. The lock TTL now covers the sum
of the scan step timeouts.
- Restore the saved SMTP/Resend flags when a provider switch fails validation, so a
later event toggle cannot save a half-configured Resend (team and instance pages).
- Resend uses smtp_from_* when resend_from_* is blank, as before the Resend sender fields.
- Require the Resend sender only when Resend is enabled.
- Replace wire:confirm in the SMTP server picker with x-modal-confirmation.
Raise the Reverb max request size and store the remembered list view
cookies unencrypted, so the WebSocket handshake no longer fails with 413
and live updates (like proxy restart logs) reach the browser.
Anonymize the audit events of a deleted user, store only the ID and
name of other users, and drop the metadata copy of actor_email.
Store URLs without query strings, registries without user info, and
the exception class instead of raw SSH errors.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Return 429 after 30 failed (401/403/404) requests per minute for one
token or IP, also for unknown API routes (API_FAILED_REQUEST_RATE_LIMIT)
- Notify the team once a day when a token reaches the limit
- Deduplicate ability_denied and scope_denied audit events for 5 minutes
Add gitea_app_uuid to the allowed fields for application create and
update endpoints, with string validation on update, so Gitea App
sources can be set through the API.
Add a test checking that a closed GitLab merge request on the manual
webhook closes the matching preview and loads only applications of
that repository.
BuildKit keys every RUN step on the --add-host names, so a container
that joins or leaves the network between two builds rebuilt all layers.
Leave out database backup and S3 import helpers, Sentinel, and the
proxy error page container.
Closes#12452
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Updating the image of a service named like "api.test" wrote a nested
"test" key into the "api" service, because data_get/data_set split the
name on dots. Use array key paths instead. Also refuse service names that
Docker cannot use as a container name prefix, with a clear error on save.
Closes#12456
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The API and MCP saved names and descriptions that the UI rejects, so the
resource could not be saved in the UI after that. Applications, services,
databases, servers, and private keys now use the UI name and description
rules on create and update, with the UI error messages.
Closes#12466
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add GET /gitea-apps, POST /applications/private-gitea-app, and
gitea_app_uuid in PATCH /applications/{uuid}, with OpenAPI docs and MCP tool support.
Closes#12459
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>