Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions packages/flux-editor/src/flux-editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -300,10 +300,16 @@ export default class MyElement extends LitElement {
}

async getMentionSuggestions(query: string) {
const matches = this.members
// Protocol-level group mentions
const groupMentions: Suggestion[] = [
{ id: 'ad4m://everyone', label: 'everyone' },
].filter((m) => m.label.toLowerCase().startsWith(query.toLowerCase()));

Comment on lines +303 to +307

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, verify the file exists and read the context around the mentioned lines
find . -type f -name "flux-editor.ts" | head -20

Repository: coasys/flux

Length of output: 96


🏁 Script executed:

# Read the relevant section of the file
cat -n packages/flux-editor/src/flux-editor.ts | sed -n '295,320p'

Repository: coasys/flux

Length of output: 1106


🏁 Script executed:

# Search for getMentionSuggestions method to understand the full context
rg -n "getMentionSuggestions" packages/flux-editor/src/flux-editor.ts -A 20 -B 5

Repository: coasys/flux

Length of output: 2920


🏁 Script executed:

# Search for any permission checks related to mentions or ad4m://everyone
rg -n "permission|capability|role|authorize" packages/flux-editor/src/flux-editor.ts -i

Repository: coasys/flux

Length of output: 37


🏁 Script executed:

# Check if there are backend implementations that enforce permissions for ad4m://everyone
find . -type f \( -name "*.ts" -o -name "*.js" \) | xargs rg "ad4m://everyone" -l

Repository: coasys/flux

Length of output: 98


🏁 Script executed:

# Search for mention processing or validation in the codebase
rg -n "mention" packages/flux-editor/src/ -i --type ts -A 3 | head -50

Repository: coasys/flux

Length of output: 3396


🏁 Script executed:

# Check the full flux-editor.ts class definition to see what properties exist
cat -n packages/flux-editor/src/flux-editor.ts | head -150 | tail -100

Repository: coasys/flux

Length of output: 2573


🏁 Script executed:

# Search for message sending or dispatch logic
rg -n "send|dispatch|message" packages/flux-editor/src/flux-editor.ts -i -A 2

Repository: coasys/flux

Length of output: 665


🏁 Script executed:

# Look for where mentions are actually processed when sending
find . -type f \( -name "*.ts" -o -name "*.js" \) -path "*/packages/*" | xargs rg "ad4m://everyone" -B 5 -A 5

Repository: coasys/flux

Length of output: 984


🏁 Script executed:

# Check if there's any reference to permissions or roles in the codebase
find . -type f \( -name "*.ts" -o -name "*.js" \) -path "*/packages/*" | xargs rg "everyone|permission|role" -i -l | head -20

Repository: coasys/flux

Length of output: 464


🏁 Script executed:

# Look at the full mention.ts to understand the complete flow
cat -n packages/flux-editor/src/mention.ts

Repository: coasys/flux

Length of output: 5138


🏁 Script executed:

# Find Message class and create method
find . -type f \( -name "*.ts" -o -name "*.js" \) -path "*/packages/*" | xargs rg "class Message|export.*Message" -A 5 | head -50

Repository: coasys/flux

Length of output: 3684


🏁 Script executed:

# Search for Message.create specifically
find . -type f \( -name "*.ts" -o -name "*.js" \) -path "*/packages/*" | xargs rg "create\(" -B 3 -A 10 | grep -A 10 "Message.create"

Repository: coasys/flux

Length of output: 912


🏁 Script executed:

# Check the api package for Message handling
find packages/api -type f -name "*.ts" | head -20

Repository: coasys/flux

Length of output: 783


🏁 Script executed:

# Look for any validation of mention content
rg -n "ad4m://" packages/ -r -A 5 -B 5

Repository: coasys/flux

Length of output: 18215


🏁 Script executed:

# Check if there's any role/permission based logic for messages
find . -type f \( -name "*.ts" -o -name "*.js" \) -path "*/packages/api*" | xargs rg -l "permission|role|authorize" 2>/dev/null

Repository: coasys/flux

Length of output: 105


🏁 Script executed:

# Get the exact content around line 305 to confirm
cat -n packages/flux-editor/src/flux-editor.ts | sed -n '303,307p'

Repository: coasys/flux

Length of output: 297


🏁 Script executed:

# Also check the mention.ts file to see what IDs it recognizes
cat -n packages/flux-editor/src/mention.ts | sed -n '20,23p'

Repository: coasys/flux

Length of output: 299


🏁 Script executed:

# Check the Message class implementation for any validation
cat -n packages/api/src/message/index.ts | head -80

Repository: coasys/flux

Length of output: 1443


🏁 Script executed:

# Search for where mentions are parsed or processed from body
rg -n "body|mention" packages/api/src/ -i -B 2 -A 2 | grep -A 3 -B 3 "everyone\|ad4m://"

Repository: coasys/flux

Length of output: 37


🏁 Script executed:

# Check if there's any mention processing or notification logic
find packages/api -type f -name "*.ts" | xargs rg -l "notification\|broadcast\|mention" -i

Repository: coasys/flux

Length of output: 39


🏁 Script executed:

# Look for any permission enforcement on message creation or sending
rg -n "permission\|capability\|authorize\|admin\|role" packages/api/src/message -i

Repository: coasys/flux

Length of output: 37


🏁 Script executed:

# Check what properties the flux-editor component has
cat -n packages/flux-editor/src/flux-editor.ts | sed -n '110,150p'

Repository: coasys/flux

Length of output: 986


🏁 Script executed:

# Check how messages flow from the editor to the perspective
rg -n "perspective.add\|Message.create" packages/flux-editor/src/flux-editor.ts -B 3 -A 3

Repository: coasys/flux

Length of output: 37


Gate @everyone suggestion behind an explicit permission/capability check in the editor.

Lines 303–307 expose ad4m://everyone to all users unconditionally in the suggestion list. The mention plugin accepts any mention with the ad4m:// prefix without validation. Ensure this capability is restricted based on user permissions—at minimum in the backend when processing messages, and preferably also in the UI suggestion layer to prevent users from attempting unsupported mentions.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/flux-editor/src/flux-editor.ts` around lines 303 - 307, The
unconditional inclusion of the ad4m://everyone suggestion in the groupMentions
array must be gated by a permission/capability check: modify the logic that
builds groupMentions in flux-editor.ts (the groupMentions variable) to only
include { id: 'ad4m://everyone', label: 'everyone' } when the current user
passes an explicit check (e.g., hasCapability('mention:everyone') or
canMentionEveryone()) and fall back to an empty set otherwise; additionally
ensure the backend mention-processing path (where the mention plugin validates
ad4m:// prefixes) enforces the same capability check when handling
outgoing/received messages so unsupported mentions are rejected server-side.

const memberMatches = this.members
.filter((m) => this.getSafeString(m.username).toLowerCase().startsWith(query.toLowerCase()))
.map((m) => ({ id: m.did, label: m.username || 'anonymous' }))
.slice(0, 10) as Suggestion[];
.map((m) => ({ id: m.did, label: m.username || 'anonymous' }));

const matches = [...groupMentions, ...memberMatches].slice(0, 10) as Suggestion[];

this.suggestions = matches;
return matches;
Expand Down
2 changes: 1 addition & 1 deletion packages/flux-editor/src/mention.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export default Node.create<MentionOptions>({
return {
HTMLAttributes: {},
renderLabel({ node }) {
const isMention = node.attrs.id.startsWith('did:');
const isMention = node.attrs.id.startsWith('did:') || node.attrs.id.startsWith('ad4m://');
return `${isMention ? '@' : '#'}${node.attrs.label ?? node.attrs.id}`;
Comment on lines +21 to 22

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Guard node.attrs.id before calling startsWith to avoid render-time crashes.

Line 21 assumes node.attrs.id is always a string, but id defaults to null (Line 72). A malformed/pasted mention node can throw here and break rendering.

Proposed fix
       renderLabel({ node }) {
-        const isMention = node.attrs.id.startsWith('did:') || node.attrs.id.startsWith('ad4m://');
-        return `${isMention ? '@' : '#'}${node.attrs.label ?? node.attrs.id}`;
+        const id = typeof node.attrs.id === 'string' ? node.attrs.id : '';
+        const isMention = id.startsWith('did:') || id.startsWith('ad4m://');
+        return `${isMention ? '@' : '#'}${node.attrs.label ?? id}`;
       },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const isMention = node.attrs.id.startsWith('did:') || node.attrs.id.startsWith('ad4m://');
return `${isMention ? '@' : '#'}${node.attrs.label ?? node.attrs.id}`;
const id = typeof node.attrs.id === 'string' ? node.attrs.id : '';
const isMention = id.startsWith('did:') || id.startsWith('ad4m://');
return `${isMention ? '@' : '#'}${node.attrs.label ?? id}`;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/flux-editor/src/mention.ts` around lines 21 - 22, Guard the access
to node.attrs.id before calling startsWith in the mention rendering logic: in
the expression using isMention and the return that builds the label (the snippet
around node.attrs.id.startsWith(...) and `${isMention ? '@' :
'#'}${node.attrs.label ?? node.attrs.id}` in
packages/flux-editor/src/mention.ts), check that node.attrs.id is a non-empty
string (e.g. typeof node.attrs.id === 'string' && node.attrs.id.startsWith(...))
and fall back to treating it as not-a-mention when it is
null/undefined/non-string so rendering uses node.attrs.label or a safe fallback
instead of calling startsWith on null.

},
suggestion: {
Expand Down
Loading