Skip to content

MM-69978: strengthen validation of card property data - #243

Merged
nang2049 merged 3 commits into
mainfrom
MM-69978
Aug 4, 2026
Merged

MM-69978: strengthen validation of card property data#243
nang2049 merged 3 commits into
mainfrom
MM-69978

Conversation

@nang2049

@nang2049 nang2049 commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Summary

Card property templates and values were accepted and persisted without checking that they matched the shape the clients expect. This adds a shared validator, used across the board, card and block create and patch paths, so data that does not match the expected type is rejected with a 400 rather than stored. The webapp side coerces card property names and values before rendering them, so any existing record that does not match the expected shape degrades gracefully instead of breaking the view it appears in.

Ticket Link

https://mattermost.atlassian.net/browse/MM-69978

Change Impact: 🟡 Medium

Regression Risk: Shared validation and rendering utilities affect server persistence and webapp display paths. Automated tests cover malformed data, but valid edge cases may regress.

QA Recommendation: Manual QA can be skipped due to comprehensive automated coverage. Targeted smoke testing remains optional.

Generated by CodeRabbitAI

@nang2049 nang2049 added 2: Dev Review Requires review by a core committer 3: QA Review Requires review by a QA tester labels Jul 30, 2026
@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 4bbe0579-ed84-4a75-bd6f-945715d5cbc7

📥 Commits

Reviewing files that changed from the base of the PR and between a24c3b6 and c10954f.

📒 Files selected for processing (2)
  • server/app/boards_and_blocks.go
  • server/integrationtests/boards_and_blocks_test.go

📝 Walkthrough

Walkthrough

Card, board, and block property payloads now receive server-side validation before patching or persistence. API and integration tests cover malformed requests. Frontend helpers normalize invalid property names and values before rendering and editing.

Changes

Card property integrity

Layer / File(s) Summary
Card property validation contract
server/model/card_property.go, server/model/card_property_test.go
Adds validation for card property values, templates, options, and invalid shapes.
Model patch validation and application
server/model/card.go, server/model/board.go, server/model/block.go, server/model/card_property_test.go
Validates card, board, and block property updates. Invalid patch values do not change existing state.
API patch enforcement
server/api/..., server/app/..., server/integrationtests/...
Rejects missing or malformed card, board, and block patches with 400 Bad Request before persistence.
Frontend property sanitization
webapp/src/blocks/..., webapp/src/components/..., webapp/src/properties/...
Adds shared sanitizers and applies them to property names, values, editors, URL handling, and table headers.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant API
  participant Model
  participant Storage
  Client->>API: Submit card, board, or block patch
  API->>Model: Validate patch and properties
  alt Invalid payload
    Model-->>API: Validation error
    API-->>Client: 400 Bad Request
  else Valid payload
    Model-->>API: Valid patch
    API->>Storage: Apply patch
    Storage-->>API: Updated state
    API-->>Client: Success response
  end
Loading

Possibly related PRs

Suggested reviewers: ogi-m, avasconcelos114, edgarbellot

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.11% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: stronger validation of card property data.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch MM-69978

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
server/model/block.go (1)

203-207: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Validate property values on full block validation.

This path only verifies the outer map type. Unlike BlockPatch, it can still persist {"properties":{"prop":{}}} through full block creation/update validation. Call ValidateCardPropertyValues after the type assertion.

Proposed fix
 	if propsIface, present := b.Fields[BlockFieldProperties]; present {
-		if _, ok := propsIface.(map[string]interface{}); !ok {
+		props, ok := propsIface.(map[string]interface{})
+		if !ok {
 			return ErrBlockPropertiesInvalidType
 		}
+		if err := ValidateCardPropertyValues(props); err != nil {
+			return err
+		}
 	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@server/model/block.go` around lines 203 - 207, Update full block validation
in the block validation method containing the BlockFieldProperties type check to
call ValidateCardPropertyValues after the properties map type assertion
succeeds. Preserve ErrBlockPropertiesInvalidType for invalid outer values, and
reject invalid nested property values before full block creation or update
proceeds.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@server/api/cards.go`:
- Around line 300-303: In the handler flow before calling patch.CheckValid,
detect when the unmarshaled patch is nil, including a JSON null body, and return
a 400 Bad Request through a.errorResponse. Keep the existing validation and
error handling unchanged for non-nil patches.

In `@webapp/src/properties/url/url.tsx`:
- Around line 29-30: Initialize the URL editor’s value from the sanitized
propertyValue rather than the raw card property, ensuring Editable always
receives a string. Update the relevant URL editor state initialization near
safePropertyString, and add a regression test covering edit mode with a
malformed persisted URL object or array.

---

Outside diff comments:
In `@server/model/block.go`:
- Around line 203-207: Update full block validation in the block validation
method containing the BlockFieldProperties type check to call
ValidateCardPropertyValues after the properties map type assertion succeeds.
Preserve ErrBlockPropertiesInvalidType for invalid outer values, and reject
invalid nested property values before full block creation or update proceeds.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 3c3949e1-5f7d-4140-9cf5-072e5c700a49

📥 Commits

Reviewing files that changed from the base of the PR and between 9c099ba and 8247e67.

📒 Files selected for processing (14)
  • server/api/cards.go
  • server/integrationtests/board_test.go
  • server/integrationtests/cards_test.go
  • server/model/block.go
  • server/model/board.go
  • server/model/card.go
  • server/model/card_property.go
  • server/model/card_property_test.go
  • webapp/src/blocks/board.test.ts
  • webapp/src/blocks/board.ts
  • webapp/src/components/cardDetail/cardDetailProperties.tsx
  • webapp/src/components/propertyValueElement.tsx
  • webapp/src/components/table/tableHeaders.tsx
  • webapp/src/properties/url/url.tsx

Comment thread server/api/cards.go
Comment thread webapp/src/properties/url/url.tsx

@edgarbellot edgarbellot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thank you Nevy!

@nang2049 nang2049 changed the title MM-69978: validate card property types before persisting them MM-69978: strengthen validation of card property data Aug 3, 2026
@dryrunsecurity

dryrunsecurity Bot commented Aug 3, 2026

Copy link
Copy Markdown

DryRun Security

This pull request introduces a low-severity vulnerability where the validateUpdatedFields function lacks recursion depth limits, potentially allowing malicious users to trigger a stack overflow and denial of service via deeply nested JSON input.

Code Policy: Safe Recursive Functions Handling User Input (drs_8132b6a4)
Policy Safe Recursive Functions Handling User Input
Result The recursive function validateUpdatedFields in server/model/block.go (lines 258-300) lacks any controlled recursion depth mechanism. It recursively traverses nested map[string]interface{} structures without a depth counter, maximum depth limit, or any safeguard against unbounded recursion. This function is directly reachable from user-controlled HTTP PATCH requests via the call chain: API handler handlePatchBlock -> PatchBlockAndNotify -> ValidateBlockPatch -> validateUpdatedFields. A malicious user could craft deeply nested JSON input to cause stack overflow and denial of service. Guidance: To remediate violations: - Add explicit recursion depth parameters with guarded maximum limits. For example: go func recursiveFunc(input InputType, depth int) error { const maxDepth = 100 if depth > maxDepth { return fmt.Errorf("recursion limit exceeded") } if !isValid(input) { return fmt.Errorf("invalid input") } // Recursive call with incremented depth return recursiveFunc(modifiedInput, depth+1) } - Validate all user-controlled inputs rigorously before initiating recursion. - Consider replacing recursion with iterative implementations if feasible. - Use any existing internal utilities or conventions for safe recursion control. Ensure all relevant new or modified Go recursive functions comply with these safeguards.

}
}
if key == BlockFieldProperties {
props, ok := value.(map[string]interface{})
if !ok {
return NewErrBadRequest(ErrBlockPropertiesInvalidType.Error())
}
if err := ValidateCardPropertyValues(props); err != nil {
return NewErrBadRequest(err.Error())
}
}
if nestedMap, ok := value.(map[string]interface{}); ok {
if err := validateUpdatedFields(nestedMap); err != nil {
return err


Comment to provide feedback on these findings.

Report false positive: @dryrunsecurity fp [FINDING ID] [FEEDBACK]
Report low-impact: @dryrunsecurity nit [FINDING ID] [FEEDBACK]

Example: @dryrunsecurity fp drs_90eda195 This code is not user-facing

All finding details can be found in the DryRun Security Dashboard.

@avasconcelos114 avasconcelos114 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Nicely done with the last commit moving the validation checks onto PatchBlocksAndNotify :D

@nang2049
nang2049 merged commit 1b13eca into main Aug 4, 2026
22 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

2: Dev Review Requires review by a core committer 3: QA Review Requires review by a QA tester

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants