The get-page RPC command did not validate that the requested page-id was within the share-link's authorized :pages set, allowing share-link holders to read out-of-scope pages. The get-file-fragment command had the same issue.
This fix adds page scope validation to get-page, rejecting requests for pages not in the share-link's :pages set with a :not-found error. For get-file-fragment, share-link access is denied entirely as fragments lack direct page-id mapping.
The fix aligns these commands with the existing correct behavior in get-view-only-bundle, which already filters pages based on share-link scope.
Closes#11281
AI-assisted-by: qwen3.7-plus
Persist binfile manifest metadata in file_data on import so file
statistics are available at open-workspace time. Emit a new
open-workspace-file audit event enriched with file statistics:
page count, shape count, component count, linked libraries,
design tokens, and whether the file is a shared library.
Closes#11106
AI-assisted-by: mimo-v2.5-pro
Pan/zoom via render_from_cache while the tile atlas is still empty
left a blank workspace under the page-transition blur. Ignore
set-view-box / view-interaction-start until tiles-complete, block
pointer events on the viewport SVG, and flush any deferred local
viewport sync when the overlay ends.
Rename skill directory and update all references to follow the
same naming pattern as plan-review.
Simplify review.md command from 138 to 25 lines — remove redundant
content that duplicated what the skills already define. The command
now acts as a thin router; the skills own the methodology.
AI-assisted-by: mimo-v2.5-pro
Logout only cleared the auth-token cookie but never deleted the
server-side row because delete-fn read ::id which wrap-authz no longer
sets since 363b4e3778. Make delete-fn delete via ::session/:id attached
by wrap-authz so replayed tokens are rejected (CWE-613, GHSA-mj9f-5cwq-7p3q).
Add regression tests covering invalidation, idempotency and isolation
of other sessions. Fix verified with Red→Green TDD and full backend
suite (677 tests).
Closes#11316
AI-assisted-by: muse-spark-1.2-contributor
* 🚑 Remove internal error details from HTTP error responses
PostgreSQL exceptions, I/O exceptions, and unhandled errors were
leaking raw database messages (table names, constraint names,
SQLSTATE codes), filesystem paths, and internal exception details
to API clients via :hint, :state, and :path response fields.
Remove these fields from server-error responses while keeping
full error context in server-side logs for operators.
Closes#11287
AI-assisted-by: mimo-v2.5-pro
* 🚑 Strip internal fields and map PG errors to safe messages
Complete the security fix for GHSA-r8wx-23q6-w3gf by addressing
the incomplete redaction found in code review.
Add strip-internal-fields helper to dissoc :hint, :state, :path,
and :context from error response data in three handlers that
previously passed raw ex-data through to clients:
- handle-error :internal
- handle-exception :default (else branch)
- handle-error :assertion (else branch)
Add pgsql-state->message to map PostgreSQL SQLSTATE codes to safe,
client-facing messages (e.g. 23505 → "A conflicting entry already
exists") instead of returning raw PG error text. Include :message
in all PSQLException response branches.
Add regression tests asserting :hint, :state, :path, :context are
absent from responses for :internal and unhandled ex-info errors.
Closes#11287
AI-assisted-by: mimo-v2.5-pro
* 🚑 Keep :hint in error protocol, fix unsafe sources
Refine the security fix based on code review feedback.
Keep :hint as part of the error protocol — it is essential for
controlled error communication. Remove it from strip-internal-fields
(which now only strips :state, :path, :context).
Fix the actual sources of unsafe :hint values:
- http/middleware.clj: replace (ex-message cause) with safe static
strings for IllegalArgumentException, RequestTooBigException, and
EOFException. These :validation errors return ex-data verbatim
to clients, so raw exception messages were leaking internals.
- PSQLException handler: use :hint instead of :message for the
SQLSTATE-mapped messages, staying consistent with the error
protocol.
Update tests to assert :hint is present (with safe static values)
in :internal and unhandled ex-info responses, and absent only from
bare RuntimeException and IOException responses.
Closes#11287
AI-assisted-by: mimo-v2.5-pro
During view gestures, fast mode renders tiles without shadows or
blur. Writing those tiles into the doc/tile atlas left shadowless
patches when render_from_cache overlayed them on the scaled
preview. Keep the last HQ atlas tiles until the post-gesture
full-quality render completes.
HQ tiles are 512px and the atlas stays at 4096² (64 full-size
slots). Browser zoom plus a forced ?dpr= can need more visible
tiles than that, and a framebuffer larger than the GPU allows.
Pack interest tiles into smaller atlas cells, blit at 512 then
scale, and inset Linear samples so seams do not bleed. Clamp the
canvas backing store and DPR together, wrap Skia at the real
drawingBuffer size, and wait one frame after DPR changes so CSS
client size and overlays stay aligned.
Add a direct container-geometry path for eligible frames: inline blur
when the kernel fits the tile margin, otherwise a cached filter-surface
pass reused across tiles via DropShadowFilterCache on both the direct
and slow render_shape paths.
Move frame shadow logic into shadows.rs. Fix nested/clipped frame
shadows by deferring parent clip to composite time, apply negative
spread via inset, and allow rotated/transformed frames on the direct
path. Skip descendant extrect walks for clipped frames when only
nested drop shadows matter, and skip child silhouettes when the
container fill already covers shadow descendants.
* 🐛 Add ownership check to share-link deletion
The delete-share-link RPC command only verified file-level edit
permission but did not check if the caller owned the share-link.
This allowed any file editor to delete share-links created by
other users, disrupting collaborative workflows.
The fix adds an ownership check that allows deletion only by:
- The share-link creator (owner-id matches profile-id)
- File admins (is-admin permission)
- File owners (is-owner permission)
Implemented using TDD:
- RED: Test demonstrates IDOR vulnerability (editor can delete)
- GREEN: Ownership check prevents unauthorized deletion
- All existing tests continue to pass
Closes#11289
AI-assisted-by: qwen3.7-plus
* 🐛 Add test coverage for share-link deletion escape hatches
Address code review feedback for PR #11290:
- Add test for editor deleting their own share-link
- Add test for admin deleting editor's share-link
- Add test for owner deleting editor's share-link
- Remove redundant :is-owner check (already included in :is-admin)
- Add clarifying comment about :is-admin including :is-owner
Closes#11289
AI-assisted-by: qwen3.7-plus
The notification pill component now properly respects the `is-html`
flag when rendering the detail section, matching the behavior of the
children section. Token import error messages now escape HTML
characters in user-provided values like token names and type names
before displaying them in notifications.
AI-assisted-by: qwen3.7-plus
* 🐛 Use gradient type instead of export type in SVG renderer
data->gradient-def was comparing the render `type` parameter (:svg,
:png, :pdf) against "linear" to decide between linearGradient and
radialGradient elements. Since the export type is never "linear",
the comparison always fell through to radialGradient, causing all
linear gradients to be exported as radial in SVG output.
Read the gradient type from the data map instead:
(get-in data ["gradient" "type"])
Closes#5972
* 🐛 Add SVG gradient export regression test
Extract SVG gradient definition generation from the renderer so it can
be tested directly. Add exporter test build wiring and cover both
linear and radial gradient output.
AI-assisted-by: gpt-5.6-luna
* ✨ Standardize exporter testing workflow
Align exporter scripts with the frontend testing pattern. Add a
dedicated GitHub Actions workflow and document the canonical exporter
commands in Serena memories.
AI-assisted-by: gpt-5.6-luna
* ✨ Add focused exporter test execution
Mirror frontend test-runner behavior for focused namespaces and test
vars. Support --focus, --log-level, and --help, and document the
commands.
AI-assisted-by: gpt-5.6-luna
* 🐛 Replace shell exec with execFile in exporter
Replace child_process.exec with execFile to eliminate shell
interpretation. Add hex color validation in exporter and frontend
to reject malformed input before command construction.
This fixes GHSA-4f36-m4hj-cv86 (CVSS 9.9 Critical), an authenticated
OS command injection vulnerability where malicious fill-color values
could execute arbitrary commands in the exporter container.
Defense in depth:
- Layer 1: execFile passes arguments directly without shell parsing
- Layer 2: Exporter validates colors with strict hex regex
- Layer 3: Frontend filters invalid colors before DOM emission
All three independent reporters' attack vectors are addressed:
- Quote breakout (lyhtheori)
- Command substitution (B1gN0Se)
- Path traversal (KimiSecurityTeam)
AI-assisted-by: qwen3.7-plus
* 🐛 Use existing hex-color-string? and fix test path mismatch
Address code review feedback:
- Replace duplicated hex-color-rx and valid-hex-color? with existing
hex-color-string? from app.common.types.color
- Fix RCE test to use marker path in payload instead of hardcoded /tmp/pwned
AI-assisted-by: qwen3.7-plus
---------
Co-authored-by: Sumit Ridhal <sridhal@redhat.com>
* 🐛 Use gradient type instead of export type in SVG renderer
data->gradient-def was comparing the render `type` parameter (:svg,
:png, :pdf) against "linear" to decide between linearGradient and
radialGradient elements. Since the export type is never "linear",
the comparison always fell through to radialGradient, causing all
linear gradients to be exported as radial in SVG output.
Read the gradient type from the data map instead:
(get-in data ["gradient" "type"])
Closes#5972
* 🐛 Add SVG gradient export regression test
Extract SVG gradient definition generation from the renderer so it can
be tested directly. Add exporter test build wiring and cover both
linear and radial gradient output.
AI-assisted-by: gpt-5.6-luna
* ✨ Standardize exporter testing workflow
Align exporter scripts with the frontend testing pattern. Add a
dedicated GitHub Actions workflow and document the canonical exporter
commands in Serena memories.
AI-assisted-by: gpt-5.6-luna
* ✨ Add focused exporter test execution
Mirror frontend test-runner behavior for focused namespaces and test
vars. Support --focus, --log-level, and --help, and document the
commands.
AI-assisted-by: gpt-5.6-luna
* 🐛 Replace shell exec with execFile in exporter
Replace child_process.exec with execFile to eliminate shell
interpretation. Add hex color validation in exporter and frontend
to reject malformed input before command construction.
This fixes GHSA-4f36-m4hj-cv86 (CVSS 9.9 Critical), an authenticated
OS command injection vulnerability where malicious fill-color values
could execute arbitrary commands in the exporter container.
Defense in depth:
- Layer 1: execFile passes arguments directly without shell parsing
- Layer 2: Exporter validates colors with strict hex regex
- Layer 3: Frontend filters invalid colors before DOM emission
All three independent reporters' attack vectors are addressed:
- Quote breakout (lyhtheori)
- Command substitution (B1gN0Se)
- Path traversal (KimiSecurityTeam)
AI-assisted-by: qwen3.7-plus
* 🐛 Use existing hex-color-string? and fix test path mismatch
Address code review feedback:
- Replace duplicated hex-color-rx and valid-hex-color? with existing
hex-color-string? from app.common.types.color
- Fix RCE test to use marker path in payload instead of hardcoded /tmp/pwned
AI-assisted-by: qwen3.7-plus
---------
Co-authored-by: Sumit Ridhal <sridhal@redhat.com>
* 🐛 Use gradient type instead of export type in SVG renderer
data->gradient-def was comparing the render `type` parameter (:svg,
:png, :pdf) against "linear" to decide between linearGradient and
radialGradient elements. Since the export type is never "linear",
the comparison always fell through to radialGradient, causing all
linear gradients to be exported as radial in SVG output.
Read the gradient type from the data map instead:
(get-in data ["gradient" "type"])
Closes#5972
* 🐛 Add SVG gradient export regression test
Extract SVG gradient definition generation from the renderer so it can
be tested directly. Add exporter test build wiring and cover both
linear and radial gradient output.
AI-assisted-by: gpt-5.6-luna
* ✨ Standardize exporter testing workflow
Align exporter scripts with the frontend testing pattern. Add a
dedicated GitHub Actions workflow and document the canonical exporter
commands in Serena memories.
AI-assisted-by: gpt-5.6-luna
* ✨ Add focused exporter test execution
Mirror frontend test-runner behavior for focused namespaces and test
vars. Support --focus, --log-level, and --help, and document the
commands.
AI-assisted-by: gpt-5.6-luna
* 🐛 Replace shell exec with execFile in exporter
Replace child_process.exec with execFile to eliminate shell
interpretation. Add hex color validation in exporter and frontend
to reject malformed input before command construction.
This fixes GHSA-4f36-m4hj-cv86 (CVSS 9.9 Critical), an authenticated
OS command injection vulnerability where malicious fill-color values
could execute arbitrary commands in the exporter container.
Defense in depth:
- Layer 1: execFile passes arguments directly without shell parsing
- Layer 2: Exporter validates colors with strict hex regex
- Layer 3: Frontend filters invalid colors before DOM emission
All three independent reporters' attack vectors are addressed:
- Quote breakout (lyhtheori)
- Command substitution (B1gN0Se)
- Path traversal (KimiSecurityTeam)
AI-assisted-by: qwen3.7-plus
* 🐛 Use existing hex-color-string? and fix test path mismatch
Address code review feedback:
- Replace duplicated hex-color-rx and valid-hex-color? with existing
hex-color-string? from app.common.types.color
- Fix RCE test to use marker path in payload instead of hardcoded /tmp/pwned
AI-assisted-by: qwen3.7-plus
---------
Co-authored-by: Sumit Ridhal <sridhal@redhat.com>
* ⚡ Memoize shape-attr->token-attrs and hoist per-type attrs in get-attrs*
* ⚡ Skip redundant token merges for token-less shapes in get-attrs*
* ⚡ Freeze group descendant attrs in design panel during transforms
Add escape-markdown to common/data.cljc that escapes Markdown
special characters (*, _, ~, `, [, ], >, #, @, etc.) by prefixing
them with backslash. Apply it to user-controlled fields (:hint,
:href) in the Mattermost error reporter before constructing the
notification message.
This is an internal-only feature not accessible to end users.
AI-assisted-by: mimo-v2.5-pro
Restrict version parameter to supported values (1 or 3) via schema
validation instead of accepting any integer. Add content-based format
detection when version is not provided, using bfc/parse-file-format
to inspect file magic bytes.
Closes#11105
AI-assisted-by: qwen3.7-plus
The create-upload-session RPC method accepted total-chunks values of 0
or negative numbers without validation, creating inconsistent session
state. Add {:min 1} constraint to the schema to reject invalid values
at input validation.
Closes#11103
AI-assisted-by: qwen3.7-plus
The clone-file-media-object RPC command only checked edit permissions
on the destination file. The source media object was fetched directly
by UUID without verifying the caller had access to the file that owns
it.
This fix adds a read permission check on the source file before
cloning. If the caller lacks read access to the source file, the
operation fails with :not-found to avoid leaking information about
the existence of files/media the caller cannot access.
Closes#11087
AI-assisted-by: qwen3.7-plus