Mostly safe — a couple of notes worth reading.
Scanned 5/1/2026, 12:46:45 PM·Cached result·Fast Scan·45 rules·View source ↗·How we decide ↗
AIVSS Score
Low
Severity Breakdown
0
critical
0
high
35
medium
31
low
MCP Server Information
Findings
This package scores 62/100 on safety with a B security grade, driven primarily by 35 medium-severity findings across readiness, ANSI escape injection, and server configuration issues. The 31 readiness concerns suggest incomplete implementation or documentation that could affect deployment reliability, while 16 ANSI escape injection vulnerabilities and 19 server configuration gaps present moderate risks if the package processes untrusted input or runs in exposed environments. You should address these medium-severity issues before production use, particularly the injection and configuration problems.
No known CVEs found for this package or its dependencies.
Scan Details
Want deeper analysis?
Fast scan found 66 findings using rule-based analysis. Upgrade for LLM consensus across 5 judges, AI-generated remediation, and cross-file taint analysis.
Building your own MCP server?
Same rules, same LLM judges, same grade. Private scans stay isolated to your account and never appear in the public registry. Required for code your team hasn’t shipped yet.
Showing 1–30 of 66 findings
66 findings
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 175 | if (f.checkin) { |
| 176 | if (!f.code || !f.id) return console.error("Usage: antenna event --checkin --code abc123 --id <platform>:<user_id> [--lat 34.05 --lng -118.24]"); |
| 177 | const result = await eventCheckin({ code: f.code, device_id: f.id, lat: f.lat ? +f.lat : undefined, lng: f.lng ? +f.lng : undefined }); |
| 178 | console.log(`\n✅ Checked in to event.\n`); |
| 179 | return; |
| 180 | } |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 167 | if (result.ended) { |
| 168 | console.log(`\n✅ Event ended.\n`); |
| 169 | } else { |
| 170 | console.log(`\n❌ ${result.error || 'Failed to end event'}\n`); |
| 171 | } |
| 172 | return; |
| 173 | } |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 58 | result.nearby_events.forEach((e) => { |
| 59 | console.log(` ${e.name} — ${e.participants} people`); |
| 60 | if (e.description) console.log(` ${e.description}`); |
| 61 | console.log(` Join: antenna event --join --code ${e.code}\n`); |
| 62 | }); |
| 63 | } |
| 64 | } |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 173 | } |
| 174 | |
| 175 | if (f.checkin) { |
| 176 | if (!f.code || !f.id) return console.error("Usage: antenna event --checkin --code abc123 --id <platform>:<user_id> [--lat 34.05 --lng -118.24]"); |
| 177 | const result = await eventCheckin({ code: f.code, device_id: f.id, lat: f.lat ? +f.lat : undefined, lng: f.lng ? +f.lng : undefined }); |
| 178 | console.log(`\n✅ Checked in to event.\n`); |
| 179 | return; |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 274 | } |
| 275 | |
| 276 | if (f.message || f.msg) { |
| 277 | if (!f.code || !f.id || !(f.message || f.msg)) return console.error("Usage: antenna event --message 'Hello everyone' --code abc123 --id <platform>:<user_id> [--ref 1]"); |
| 278 | const result = await sendEventMessage({ code: f.code, device_id: f.id, message: f.message || f.msg, target_ref: f.ref || undefined }); |
| 279 | if (result.sent) { |
| 280 | console.log(`\n✅ Message sent${result.broadcast ? ' (broadcast to all)' : ''}\n`); |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 213 | } |
| 214 | |
| 215 | if (f.scan) { |
| 216 | if (!f.code) return console.error("Usage: antenna event --scan --code abc123 [--id <platform>:<user_id>]"); |
| 217 | const result = await eventScan({ code: f.code, device_id: f.id || null }); |
| 218 | if (result.count === 0) return console.log("\n🏟️ No participants yet.\n"); |
| 219 | console.log(`\n🏟️ ${result.count} joined, ${result.checked_in_count || 0} checked in:\n`); |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 263 | } |
| 264 | |
| 265 | if (f['add-host']) { |
| 266 | if (!f.code || !f.id || !f.ref) return console.error("Usage: antenna event --add-host --code abc123 --id <platform>:<user_id> --ref 1"); |
| 267 | const result = await addCohost({ code: f.code, device_id: f.id, ref: f.ref }); |
| 268 | if (result.added) { |
| 269 | console.log("\n✅ Co-host added\n"); |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 241 | } |
| 242 | |
| 243 | if (f.reject) { |
| 244 | if (!f.code || !f.id || !f.ref) return console.error("Usage: antenna event --reject --code abc123 --id <platform>:<user_id> --ref 1"); |
| 245 | const result = await rejectParticipant({ code: f.code, device_id: f.id, ref: f.ref }); |
| 246 | if (result.rejected) { |
| 247 | console.log("\n✅ Participant rejected\n"); |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 252 | } |
| 253 | |
| 254 | if (f.update) { |
| 255 | if (!f.code || !f.id) return console.error("Usage: antenna event --update --code abc123 --id <platform>:<user_id> [--name 'New Name'] [--desc 'New desc']"); |
| 256 | const result = await updateEvent({ code: f.code, device_id: f.id, name: f.name, description: f.desc, og_image: f['og-image'], lat: f.lat ? +f.lat : undefined, lng: f.lng ? +f.lng : undefined, starts_at: f['starts-at'], ends_at: f['ends-at'] }); |
| 257 | if (result.updated) { |
| 258 | console.log("\n✅ Event updated\n"); |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 230 | } |
| 231 | |
| 232 | if (f.approve) { |
| 233 | if (!f.code || !f.id || !f.ref) return console.error("Usage: antenna event --approve --code abc123 --id <platform>:<user_id> --ref 1"); |
| 234 | const result = await approveParticipant({ code: f.code, device_id: f.id, ref: f.ref }); |
| 235 | if (result.approved) { |
| 236 | console.log("\n✅ Participant approved\n"); |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 149 | const sub = f._?.[0] || Object.keys(f).find(k => ["create", "join", "scan", "end", "checkin", "upload-image"].includes(k)); |
| 150 | |
| 151 | if (f['upload-image']) { |
| 152 | if (!f.code || !f.file) return console.error("Usage: antenna event --upload-image --code abc123 --file /path/to/image.png"); |
| 153 | const fileBuf = readFileSync(f.file); |
| 154 | const image_data = fileBuf.toString("base64"); |
| 155 | const ext = extname(f.file).slice(1) || "png"; |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 284 | return; |
| 285 | } |
| 286 | |
| 287 | console.log(`Usage: |
| 288 | antenna event --create --name 'AI Meetup' --starts-at '...' --ends-at '...' [--id <platform>:<user_id>] [--lat 34.05 --lng -118.25] [--desc 'description'] [--og-image 'url'] [--requires-approval] [--screening-questions 'Q1|Q2'] |
| 289 | antenna event --join --code abc123 --id <platform>:<user_id> |
| 290 | antenna event --scan --code abc123 [--id <platform>:<user_id>] |
| 291 | antenna event --checkin --code abc123 --id <platform>:<user_id> [--lat 34.05 --lng -118.24] |
| 292 | antenna eve |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 193 | } |
| 194 | |
| 195 | if (f.join) { |
| 196 | if (!f.code || !f.id) return console.error("Usage: antenna event --join --code abc123 --id <platform>:<user_id>"); |
| 197 | const result = await joinEvent({ code: f.code, device_id: f.id, lat: f.lat ? +f.lat : undefined, lng: f.lng ? +f.lng : undefined, application_context: f['application-context'] || undefined }); |
| 198 | if (result.joined) { |
| 199 | if (result.status === 'pending') { |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 199 | if (result.status === 'pending') { |
| 200 | console.log(`\n🟡 申请已提交,等待主办方审批\n`); |
| 201 | } else { |
| 202 | console.log(`\n✅ Joined "${result.event}"\n`); |
| 203 | if (result.checked_in) console.log(` 自动签到 ✅\n`); |
| 204 | } |
| 205 | } else if (result.needs_screening) { |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 162 | } |
| 163 | |
| 164 | if (f.end) { |
| 165 | if (!f.code || !f.id) return console.error("Usage: antenna event --end --code abc123 --id <platform>:<user_id>"); |
| 166 | const result = await endEvent({ code: f.code, device_id: f.id }); |
| 167 | if (result.ended) { |
| 168 | console.log(`\n✅ Event ended.\n`); |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 180 | } |
| 181 | |
| 182 | if (f.create || (!f.join && !f.scan && !f.end && !f.update && !f.approve && !f.reject && !f['add-host'] && f.name)) { |
| 183 | if (!f.name) return console.error("Usage: antenna event --create --name 'AI Meetup' --id <platform>:<user_id> --starts-at '2026-04-19T14:00' --ends-at '2026-04-19T18:00' [--lat 34.05 --lng -118.25] [--desc 'description'] [--og-image 'url'] [--requires-approval] [--screening-questions 'Q1|Q2']"); |
| 184 | if (!f.id) return console.error("❌ --id is required (e.g. --id <platform |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
MCP tool input schema exposes an unconstrained string/any field with a risky name (command/query/sql/code/script/url/path/expr/ eval). Any caller can pass arbitrary values, which typically widens the tool's blast radius well beyond its intent. Narrow the schema with `.enum()`, `.regex()`, `.max()`, `Literal[...]`, Pydantic `Field(max_length=..., pattern=...)`, or a JSON Schema `enum` / `pattern` / `maxLength`.
Evidence
| 217 | "parameters": { |
| 218 | "type": "object", |
| 219 | "properties": { |
| 220 | "code": {"type": "string", "description": "Event code"}, |
| 221 | "sender_id": {"type": "string", "description": "The sender's user ID"}, |
| 222 | "channel": {"type": "string", "description": "Platform name (any platform works)"}, |
| 223 | "lat": {"type": "number", "description": "Latitude (optional, for auto-checkin)"}, |
Remediation
Shape the schema to the tool's actual intent: - Zod: chain `.enum([...])`, `.regex(/.../)`, or `.max(n)`; prefer `z.enum([...])` or `z.literal(...)` when the value set is small. - Pydantic: use `Literal["a", "b"]` or `Field(max_length=..., pattern=r"...")`. - JSON Schema: add `"enum"`, `"pattern"`, or `"maxLength"` to the property. An overbroad schema is an "overpowered tool" — the model has nothing to prevent it from calling the tool with input far beyond what the tool's prose contract
MCP tool input schema exposes an unconstrained string/any field with a risky name (command/query/sql/code/script/url/path/expr/ eval). Any caller can pass arbitrary values, which typically widens the tool's blast radius well beyond its intent. Narrow the schema with `.enum()`, `.regex()`, `.max()`, `Literal[...]`, Pydantic `Field(max_length=..., pattern=...)`, or a JSON Schema `enum` / `pattern` / `maxLength`.
Evidence
| 403 | "antenna_event_update", |
| 404 | "Update event info. Only the creator or co-host can update.", |
| 405 | { |
| 406 | code: z.string().describe("Event code"), |
| 407 | sender_id: z.string().describe("The sender's user ID"), |
| 408 | channel: z.string().describe("Channel name"), |
| 409 | name: z.string().optional().describe("New event name"), |
Remediation
Shape the schema to the tool's actual intent: - Zod: chain `.enum([...])`, `.regex(/.../)`, or `.max(n)`; prefer `z.enum([...])` or `z.literal(...)` when the value set is small. - Pydantic: use `Literal["a", "b"]` or `Field(max_length=..., pattern=r"...")`. - JSON Schema: add `"enum"`, `"pattern"`, or `"maxLength"` to the property. An overbroad schema is an "overpowered tool" — the model has nothing to prevent it from calling the tool with input far beyond what the tool's prose contract
MCP tool input schema exposes an unconstrained string/any field with a risky name (command/query/sql/code/script/url/path/expr/ eval). Any caller can pass arbitrary values, which typically widens the tool's blast radius well beyond its intent. Narrow the schema with `.enum()`, `.regex()`, `.max()`, `Literal[...]`, Pydantic `Field(max_length=..., pattern=...)`, or a JSON Schema `enum` / `pattern` / `maxLength`.
Evidence
| 296 | "parameters": { |
| 297 | "type": "object", |
| 298 | "properties": { |
| 299 | "code": {"type": "string"}, |
| 300 | "sender_id": {"type": "string"}, |
| 301 | "channel": {"type": "string"}, |
| 302 | "chat_id": {"type": "string", "description": "REQUIRED for notifications. Pass chat/channel ID from message context."}, |
Remediation
Shape the schema to the tool's actual intent: - Zod: chain `.enum([...])`, `.regex(/.../)`, or `.max(n)`; prefer `z.enum([...])` or `z.literal(...)` when the value set is small. - Pydantic: use `Literal["a", "b"]` or `Field(max_length=..., pattern=r"...")`. - JSON Schema: add `"enum"`, `"pattern"`, or `"maxLength"` to the property. An overbroad schema is an "overpowered tool" — the model has nothing to prevent it from calling the tool with input far beyond what the tool's prose contract
MCP tool input schema exposes an unconstrained string/any field with a risky name (command/query/sql/code/script/url/path/expr/ eval). Any caller can pass arbitrary values, which typically widens the tool's blast radius well beyond its intent. Narrow the schema with `.enum()`, `.regex()`, `.max()`, `Literal[...]`, Pydantic `Field(max_length=..., pattern=...)`, or a JSON Schema `enum` / `pattern` / `maxLength`.
Evidence
| 352 | "parameters": { |
| 353 | "type": "object", |
| 354 | "properties": { |
| 355 | "code": {"type": "string"}, |
| 356 | "sender_id": {"type": "string"}, |
| 357 | "channel": {"type": "string"}, |
| 358 | "chat_id": {"type": "string", "description": "REQUIRED for notifications. Pass chat/channel ID from message context."}, |
Remediation
Shape the schema to the tool's actual intent: - Zod: chain `.enum([...])`, `.regex(/.../)`, or `.max(n)`; prefer `z.enum([...])` or `z.literal(...)` when the value set is small. - Pydantic: use `Literal["a", "b"]` or `Field(max_length=..., pattern=r"...")`. - JSON Schema: add `"enum"`, `"pattern"`, or `"maxLength"` to the property. An overbroad schema is an "overpowered tool" — the model has nothing to prevent it from calling the tool with input far beyond what the tool's prose contract
MCP tool input schema exposes an unconstrained string/any field with a risky name (command/query/sql/code/script/url/path/expr/ eval). Any caller can pass arbitrary values, which typically widens the tool's blast radius well beyond its intent. Narrow the schema with `.enum()`, `.regex()`, `.max()`, `Literal[...]`, Pydantic `Field(max_length=..., pattern=...)`, or a JSON Schema `enum` / `pattern` / `maxLength`.
Evidence
| 449 | "antenna_event_reject", |
| 450 | "Reject a pending participant. Only the creator or co-host can reject.", |
| 451 | { |
| 452 | code: z.string().describe("Event code"), |
| 453 | sender_id: z.string().describe("The sender's user ID"), |
| 454 | channel: z.string().describe("Channel name"), |
| 455 | ref: z.string().describe("Ref number of the participant to reject"), |
Remediation
Shape the schema to the tool's actual intent: - Zod: chain `.enum([...])`, `.regex(/.../)`, or `.max(n)`; prefer `z.enum([...])` or `z.literal(...)` when the value set is small. - Pydantic: use `Literal["a", "b"]` or `Field(max_length=..., pattern=r"...")`. - JSON Schema: add `"enum"`, `"pattern"`, or `"maxLength"` to the property. An overbroad schema is an "overpowered tool" — the model has nothing to prevent it from calling the tool with input far beyond what the tool's prose contract
MCP tool input schema exposes an unconstrained string/any field with a risky name (command/query/sql/code/script/url/path/expr/ eval). Any caller can pass arbitrary values, which typically widens the tool's blast radius well beyond its intent. Narrow the schema with `.enum()`, `.regex()`, `.max()`, `Literal[...]`, Pydantic `Field(max_length=..., pattern=...)`, or a JSON Schema `enum` / `pattern` / `maxLength`.
Evidence
| 487 | "antenna_event_message", |
| 488 | "Send a message to event participants. Only creator or co-host can send. Omit ref to broadcast to all.", |
| 489 | { |
| 490 | code: z.string().describe("Event code"), |
| 491 | sender_id: z.string().describe("The sender's user ID"), |
| 492 | channel: z.string().describe("Channel name"), |
| 493 | chat_id: z.string().describe("REQUIRED for notifications"), |
Remediation
Shape the schema to the tool's actual intent: - Zod: chain `.enum([...])`, `.regex(/.../)`, or `.max(n)`; prefer `z.enum([...])` or `z.literal(...)` when the value set is small. - Pydantic: use `Literal["a", "b"]` or `Field(max_length=..., pattern=r"...")`. - JSON Schema: add `"enum"`, `"pattern"`, or `"maxLength"` to the property. An overbroad schema is an "overpowered tool" — the model has nothing to prevent it from calling the tool with input far beyond what the tool's prose contract
MCP tool input schema exposes an unconstrained string/any field with a risky name (command/query/sql/code/script/url/path/expr/ eval). Any caller can pass arbitrary values, which typically widens the tool's blast radius well beyond its intent. Narrow the schema with `.enum()`, `.regex()`, `.max()`, `Literal[...]`, Pydantic `Field(max_length=..., pattern=...)`, or a JSON Schema `enum` / `pattern` / `maxLength`.
Evidence
| 468 | "antenna_event_add_host", |
| 469 | "Add a co-host to an event. Only the creator can add co-hosts.", |
| 470 | { |
| 471 | code: z.string().describe("Event code"), |
| 472 | sender_id: z.string().describe("The sender's user ID"), |
| 473 | channel: z.string().describe("Channel name"), |
| 474 | ref: z.string().describe("Ref number of the participant to make co-host"), |
Remediation
Shape the schema to the tool's actual intent: - Zod: chain `.enum([...])`, `.regex(/.../)`, or `.max(n)`; prefer `z.enum([...])` or `z.literal(...)` when the value set is small. - Pydantic: use `Literal["a", "b"]` or `Field(max_length=..., pattern=r"...")`. - JSON Schema: add `"enum"`, `"pattern"`, or `"maxLength"` to the property. An overbroad schema is an "overpowered tool" — the model has nothing to prevent it from calling the tool with input far beyond what the tool's prose contract
MCP tool input schema exposes an unconstrained string/any field with a risky name (command/query/sql/code/script/url/path/expr/ eval). Any caller can pass arbitrary values, which typically widens the tool's blast radius well beyond its intent. Narrow the schema with `.enum()`, `.regex()`, `.max()`, `Literal[...]`, Pydantic `Field(max_length=..., pattern=...)`, or a JSON Schema `enum` / `pattern` / `maxLength`.
Evidence
| 380 | "antenna_event_scan", |
| 381 | "Scan people in an event. No distance limit — returns all event participants.", |
| 382 | { |
| 383 | code: z.string().describe("Event code"), |
| 384 | sender_id: z.string().describe("The sender's user ID"), |
| 385 | channel: z.string().describe("Channel name"), |
| 386 | }, |
Remediation
Shape the schema to the tool's actual intent: - Zod: chain `.enum([...])`, `.regex(/.../)`, or `.max(n)`; prefer `z.enum([...])` or `z.literal(...)` when the value set is small. - Pydantic: use `Literal["a", "b"]` or `Field(max_length=..., pattern=r"...")`. - JSON Schema: add `"enum"`, `"pattern"`, or `"maxLength"` to the property. An overbroad schema is an "overpowered tool" — the model has nothing to prevent it from calling the tool with input far beyond what the tool's prose contract
MCP tool input schema exposes an unconstrained string/any field with a risky name (command/query/sql/code/script/url/path/expr/ eval). Any caller can pass arbitrary values, which typically widens the tool's blast radius well beyond its intent. Narrow the schema with `.enum()`, `.regex()`, `.max()`, `Literal[...]`, Pydantic `Field(max_length=..., pattern=...)`, or a JSON Schema `enum` / `pattern` / `maxLength`.
Evidence
| 279 | "parameters": { |
| 280 | "type": "object", |
| 281 | "properties": { |
| 282 | "code": {"type": "string", "description": "Event code"}, |
| 283 | "sender_id": {"type": "string", "description": "The sender's user ID"}, |
| 284 | "channel": {"type": "string", "description": "Platform name (any platform works)"}, |
| 285 | "lat": {"type": "number", "description": "Latitude (optional)"}, |
Remediation
Shape the schema to the tool's actual intent: - Zod: chain `.enum([...])`, `.regex(/.../)`, or `.max(n)`; prefer `z.enum([...])` or `z.literal(...)` when the value set is small. - Pydantic: use `Literal["a", "b"]` or `Field(max_length=..., pattern=r"...")`. - JSON Schema: add `"enum"`, `"pattern"`, or `"maxLength"` to the property. An overbroad schema is an "overpowered tool" — the model has nothing to prevent it from calling the tool with input far beyond what the tool's prose contract
MCP tool input schema exposes an unconstrained string/any field with a risky name (command/query/sql/code/script/url/path/expr/ eval). Any caller can pass arbitrary values, which typically widens the tool's blast radius well beyond its intent. Narrow the schema with `.enum()`, `.regex()`, `.max()`, `Literal[...]`, Pydantic `Field(max_length=..., pattern=...)`, or a JSON Schema `enum` / `pattern` / `maxLength`.
Evidence
| 430 | "antenna_event_approve", |
| 431 | "Approve a pending participant. Only the creator or co-host can approve.", |
| 432 | { |
| 433 | code: z.string().describe("Event code"), |
| 434 | sender_id: z.string().describe("The sender's user ID"), |
| 435 | channel: z.string().describe("Channel name"), |
| 436 | ref: z.string().describe("Ref number of the participant to approve"), |
Remediation
Shape the schema to the tool's actual intent: - Zod: chain `.enum([...])`, `.regex(/.../)`, or `.max(n)`; prefer `z.enum([...])` or `z.literal(...)` when the value set is small. - Pydantic: use `Literal["a", "b"]` or `Field(max_length=..., pattern=r"...")`. - JSON Schema: add `"enum"`, `"pattern"`, or `"maxLength"` to the property. An overbroad schema is an "overpowered tool" — the model has nothing to prevent it from calling the tool with input far beyond what the tool's prose contract
MCP tool input schema exposes an unconstrained string/any field with a risky name (command/query/sql/code/script/url/path/expr/ eval). Any caller can pass arbitrary values, which typically widens the tool's blast radius well beyond its intent. Narrow the schema with `.enum()`, `.regex()`, `.max()`, `Literal[...]`, Pydantic `Field(max_length=..., pattern=...)`, or a JSON Schema `enum` / `pattern` / `maxLength`.
Evidence
| 250 | "parameters": { |
| 251 | "type": "object", |
| 252 | "properties": { |
| 253 | "code": {"type": "string", "description": "Event code"}, |
| 254 | "sender_id": {"type": "string", "description": "The sender's user ID"}, |
| 255 | "channel": {"type": "string", "description": "Platform name (any platform works)"}, |
| 256 | "chat_id": {"type": "string", "description": "REQUIRED for notifications. Pass chat/channel ID from message context."}, |
Remediation
Shape the schema to the tool's actual intent: - Zod: chain `.enum([...])`, `.regex(/.../)`, or `.max(n)`; prefer `z.enum([...])` or `z.literal(...)` when the value set is small. - Pydantic: use `Literal["a", "b"]` or `Field(max_length=..., pattern=r"...")`. - JSON Schema: add `"enum"`, `"pattern"`, or `"maxLength"` to the property. An overbroad schema is an "overpowered tool" — the model has nothing to prevent it from calling the tool with input far beyond what the tool's prose contract
MCP tool input schema exposes an unconstrained string/any field with a risky name (command/query/sql/code/script/url/path/expr/ eval). Any caller can pass arbitrary values, which typically widens the tool's blast radius well beyond its intent. Narrow the schema with `.enum()`, `.regex()`, `.max()`, `Literal[...]`, Pydantic `Field(max_length=..., pattern=...)`, or a JSON Schema `enum` / `pattern` / `maxLength`.
Evidence
| 360 | "antenna_event_checkin", |
| 361 | "Check in at an event — marks you as present at the event location. Optionally updates GPS.", |
| 362 | { |
| 363 | code: z.string().describe("Event code"), |
| 364 | sender_id: z.string().describe("The sender's user ID"), |
| 365 | channel: z.string().describe("Channel name"), |
| 366 | lat: z.number().optional().describe("Latitude (optional)"), |
Remediation
Shape the schema to the tool's actual intent: - Zod: chain `.enum([...])`, `.regex(/.../)`, or `.max(n)`; prefer `z.enum([...])` or `z.literal(...)` when the value set is small. - Pydantic: use `Literal["a", "b"]` or `Field(max_length=..., pattern=r"...")`. - JSON Schema: add `"enum"`, `"pattern"`, or `"maxLength"` to the property. An overbroad schema is an "overpowered tool" — the model has nothing to prevent it from calling the tool with input far beyond what the tool's prose contract
MCP tool input schema exposes an unconstrained string/any field with a risky name (command/query/sql/code/script/url/path/expr/ eval). Any caller can pass arbitrary values, which typically widens the tool's blast radius well beyond its intent. Narrow the schema with `.enum()`, `.regex()`, `.max()`, `Literal[...]`, Pydantic `Field(max_length=..., pattern=...)`, or a JSON Schema `enum` / `pattern` / `maxLength`.
Evidence
| 235 | "parameters": { |
| 236 | "type": "object", |
| 237 | "properties": { |
| 238 | "code": {"type": "string", "description": "Event code"}, |
| 239 | "sender_id": {"type": "string", "description": "The sender's user ID"}, |
| 240 | "channel": {"type": "string", "description": "Platform name (any platform works)"}, |
| 241 | "chat_id": {"type": "string", "description": "REQUIRED for notifications. Pass chat/channel ID from message context."}, |
Remediation
Shape the schema to the tool's actual intent: - Zod: chain `.enum([...])`, `.regex(/.../)`, or `.max(n)`; prefer `z.enum([...])` or `z.literal(...)` when the value set is small. - Pydantic: use `Literal["a", "b"]` or `Field(max_length=..., pattern=r"...")`. - JSON Schema: add `"enum"`, `"pattern"`, or `"maxLength"` to the property. An overbroad schema is an "overpowered tool" — the model has nothing to prevent it from calling the tool with input far beyond what the tool's prose contract
MCP tool input schema exposes an unconstrained string/any field with a risky name (command/query/sql/code/script/url/path/expr/ eval). Any caller can pass arbitrary values, which typically widens the tool's blast radius well beyond its intent. Narrow the schema with `.enum()`, `.regex()`, `.max()`, `Literal[...]`, Pydantic `Field(max_length=..., pattern=...)`, or a JSON Schema `enum` / `pattern` / `maxLength`.
Evidence
| 336 | "parameters": { |
| 337 | "type": "object", |
| 338 | "properties": { |
| 339 | "code": {"type": "string"}, |
| 340 | "sender_id": {"type": "string"}, |
| 341 | "channel": {"type": "string"}, |
| 342 | "chat_id": {"type": "string", "description": "REQUIRED for notifications. Pass chat/channel ID from message context."}, |
Remediation
Shape the schema to the tool's actual intent: - Zod: chain `.enum([...])`, `.regex(/.../)`, or `.max(n)`; prefer `z.enum([...])` or `z.literal(...)` when the value set is small. - Pydantic: use `Literal["a", "b"]` or `Field(max_length=..., pattern=r"...")`. - JSON Schema: add `"enum"`, `"pattern"`, or `"maxLength"` to the property. An overbroad schema is an "overpowered tool" — the model has nothing to prevent it from calling the tool with input far beyond what the tool's prose contract
MCP tool input schema exposes an unconstrained string/any field with a risky name (command/query/sql/code/script/url/path/expr/ eval). Any caller can pass arbitrary values, which typically widens the tool's blast radius well beyond its intent. Narrow the schema with `.enum()`, `.regex()`, `.max()`, `Literal[...]`, Pydantic `Field(max_length=..., pattern=...)`, or a JSON Schema `enum` / `pattern` / `maxLength`.
Evidence
| 339 | "antenna_event_join", |
| 340 | "Join an event by its code. The code is from the event URL (antenna.fyi/events/CODE). Auto-checks in if the event has already started and you're within 1km.", |
| 341 | { |
| 342 | code: z.string().describe("Event code"), |
| 343 | sender_id: z.string().describe("The sender's user ID"), |
| 344 | channel: z.string().describe("Channel name"), |
| 345 | lat: z.number().optional().describe("Latitude (optional, for auto-checkin)"), |
Remediation
Shape the schema to the tool's actual intent: - Zod: chain `.enum([...])`, `.regex(/.../)`, or `.max(n)`; prefer `z.enum([...])` or `z.literal(...)` when the value set is small. - Pydantic: use `Literal["a", "b"]` or `Field(max_length=..., pattern=r"...")`. - JSON Schema: add `"enum"`, `"pattern"`, or `"maxLength"` to the property. An overbroad schema is an "overpowered tool" — the model has nothing to prevent it from calling the tool with input far beyond what the tool's prose contract
MCP tool input schema exposes an unconstrained string/any field with a risky name (command/query/sql/code/script/url/path/expr/ eval). Any caller can pass arbitrary values, which typically widens the tool's blast radius well beyond its intent. Narrow the schema with `.enum()`, `.regex()`, `.max()`, `Literal[...]`, Pydantic `Field(max_length=..., pattern=...)`, or a JSON Schema `enum` / `pattern` / `maxLength`.
Evidence
| 320 | "parameters": { |
| 321 | "type": "object", |
| 322 | "properties": { |
| 323 | "code": {"type": "string"}, |
| 324 | "sender_id": {"type": "string"}, |
| 325 | "channel": {"type": "string"}, |
| 326 | "chat_id": {"type": "string", "description": "REQUIRED for notifications. Pass chat/channel ID from message context."}, |
Remediation
Shape the schema to the tool's actual intent: - Zod: chain `.enum([...])`, `.regex(/.../)`, or `.max(n)`; prefer `z.enum([...])` or `z.literal(...)` when the value set is small. - Pydantic: use `Literal["a", "b"]` or `Field(max_length=..., pattern=r"...")`. - JSON Schema: add `"enum"`, `"pattern"`, or `"maxLength"` to the property. An overbroad schema is an "overpowered tool" — the model has nothing to prevent it from calling the tool with input far beyond what the tool's prose contract
MCP tool input schema exposes an unconstrained string/any field with a risky name (command/query/sql/code/script/url/path/expr/ eval). Any caller can pass arbitrary values, which typically widens the tool's blast radius well beyond its intent. Narrow the schema with `.enum()`, `.regex()`, `.max()`, `Literal[...]`, Pydantic `Field(max_length=..., pattern=...)`, or a JSON Schema `enum` / `pattern` / `maxLength`.
Evidence
| 321 | "antenna_event_end", |
| 322 | "End an event. Only the creator can end it.", |
| 323 | { |
| 324 | code: z.string().describe("Event code"), |
| 325 | sender_id: z.string().describe("The sender's user ID"), |
| 326 | channel: z.string().describe("Channel name"), |
| 327 | }, |
Remediation
Shape the schema to the tool's actual intent: - Zod: chain `.enum([...])`, `.regex(/.../)`, or `.max(n)`; prefer `z.enum([...])` or `z.literal(...)` when the value set is small. - Pydantic: use `Literal["a", "b"]` or `Field(max_length=..., pattern=r"...")`. - JSON Schema: add `"enum"`, `"pattern"`, or `"maxLength"` to the property. An overbroad schema is an "overpowered tool" — the model has nothing to prevent it from calling the tool with input far beyond what the tool's prose contract
MCP tool input schema exposes an unconstrained string/any field with a risky name (command/query/sql/code/script/url/path/expr/ eval). Any caller can pass arbitrary values, which typically widens the tool's blast radius well beyond its intent. Narrow the schema with `.enum()`, `.regex()`, `.max()`, `Literal[...]`, Pydantic `Field(max_length=..., pattern=...)`, or a JSON Schema `enum` / `pattern` / `maxLength`.
Evidence
| 368 | "parameters": { |
| 369 | "type": "object", |
| 370 | "properties": { |
| 371 | "code": {"type": "string", "description": "Event code"}, |
| 372 | "sender_id": {"type": "string"}, |
| 373 | "channel": {"type": "string"}, |
| 374 | "chat_id": {"type": "string", "description": "REQUIRED for notifications. Pass chat/channel ID from message context."}, |
Remediation
Shape the schema to the tool's actual intent: - Zod: chain `.enum([...])`, `.regex(/.../)`, or `.max(n)`; prefer `z.enum([...])` or `z.literal(...)` when the value set is small. - Pydantic: use `Literal["a", "b"]` or `Field(max_length=..., pattern=r"...")`. - JSON Schema: add `"enum"`, `"pattern"`, or `"maxLength"` to the property. An overbroad schema is an "overpowered tool" — the model has nothing to prevent it from calling the tool with input far beyond what the tool's prose contract
Package declares an install-time hook (npm postinstall/preinstall/prepare, setup.py cmdclass override, custom setuptools install class, or non-default pyproject build-backend). Anyone installing this package runs the hook. Confirm the hook is necessary and review its contents; prefer shipping a plain library without install-time execution.
Evidence
| 8 | "antenna": "bin/antenna.js" |
| 9 | }, |
| 10 | "scripts": { |
| 11 | "postinstall": "node install.js" |
| 12 | }, |
| 13 | "keywords": [ |
| 14 | "antenna", |
Remediation
Prefer libraries that do not require install-time code execution: - Drop `postinstall`/`preinstall`/`prepare` scripts if the work can happen at runtime or build-time instead. - Ship pre-built native binaries rather than compiling via a custom `cmdclass` or `build_ext` override. - For Dockerfiles: replace `RUN curl … | sh` with a pinned download + checksum verification + explicit `RUN` of a named script. - If the hook is unavoidable, document exactly what it does so downstream reviewers
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 507 | try { |
| 508 | const { data: loc } = await sb.rpc("get_profile_location", { p_device_id: device_id }); |
| 509 | if (loc?.lat && loc?.lng) { lat = loc.lat; lng = loc.lng; } |
| 510 | } catch {} |
| 511 | } |
| 512 | |
| 513 | const fuzzy = (lat != null && lng != null) ? fuzzyCoord(lat, lng) : { lat: null, lng: null }; |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 216 | f"[Antenna] 📡 有用户通过网页分享了位置 " |
| 217 | f"({evt['lat']}, {evt['lng']})。" |
| 218 | f"请使用 antenna_scan 查看附近有谁。" |
| 219 | ) |
| 220 | except Exception: |
| 221 | pass |
| 222 | |
| 223 | # 2. Check message content for coordinates |
| 224 | if messages: |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 292 | _last_ref_map[m["ref"]] = m["_device_id"] |
| 293 | if did and _last_ref_map: |
| 294 | try: |
| 295 | sb.rpc("save_scan_refs", {"p_owner": did, "p_refs": _last_ref_map}).execute() |
| 296 | except Exception: |
| 297 | pass |
| 298 | |
| 299 | return _ok({ |
| 300 | "mutual_matches": mutual, |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 262 | notifications.append({"message": msg, "timestamp": time.time()}) |
| 263 | # Keep max 50 |
| 264 | notifications = notifications[-50:] |
| 265 | _notif_file.write_text(json.dumps(notifications, ensure_ascii=False)) |
| 266 | except Exception: |
| 267 | pass |
| 268 | |
| 269 | def _realtime_listener(): |
| 270 | """Background thread: listen to Supabase Realtime for matches + event participants.""" |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 109 | if pending: |
| 110 | for n in pending: |
| 111 | hints.append(f"[Antenna] {n['message']}") |
| 112 | _nf.write_text("[]") |
| 113 | except Exception: |
| 114 | pass |
| 115 | |
| 116 | # 0. Check for new matches (every 60s) |
| 117 | if now - _last_match_check > _MATCH_CHECK_INTERVAL and _my_device_ids: |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 133 | # Persist refs to DB so accept works after restart |
| 134 | if did and _last_ref_map: |
| 135 | try: |
| 136 | sb.rpc("save_scan_refs", {"p_owner": did, "p_refs": _last_ref_map}).execute() |
| 137 | except Exception: |
| 138 | pass |
| 139 | |
| 140 | return _ok({ |
| 141 | "profiles": profiles, |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 540 | } catch {} |
| 541 | process.on('exit', () => { try { unlinkSync(pidFile); } catch {} }); |
| 542 | process.on('SIGINT', () => { try { unlinkSync(pidFile); } catch {} process.exit(0); }); |
| 543 | process.on('SIGTERM', () => { try { unlinkSync(pidFile); } catch {} process.exit(0); }); |
| 544 | |
| 545 | const sb = getClient(); |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 388 | # Save refs and log recommendations |
| 389 | try: |
| 390 | sb.rpc("save_scan_refs", {"p_owner": did, "p_refs": ref_map}).execute() |
| 391 | except Exception: |
| 392 | pass |
| 393 | for p in results: |
| 394 | try: |
| 395 | sb.rpc("log_recommendation", {"p_device_id": did, "p_recommended_id": p["device_id"]}).execute() |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 819 | const event = await sb.rpc("get_event_by_id", { p_event_id: row.event_id }).then(r => r.data); |
| 820 | pushNotify(`❌ Your application to \"${event?.name || 'an event'}\" was not approved.`); |
| 821 | } |
| 822 | } catch {} |
| 823 | } |
| 824 | ) |
| 825 | .subscribe((status) => { |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 305 | p = prof.data or {} |
| 306 | name = p.get("display_name") or "有人" |
| 307 | emoji = p.get("emoji") or "👤" |
| 308 | _append_notification(f"📩 {emoji} {name} 想认识你!用 antenna_check_matches 查看详情。") |
| 309 | except Exception: |
| 310 | pass |
| 311 | |
| 312 | def _handle_event_change(payload): |
| 313 | try: |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 601 | // Log to file as fallback |
| 602 | const logDir = path.join(os.homedir(), '.antenna'); |
| 603 | const logFile = path.join(logDir, 'watch.log'); |
| 604 | try { if (!existsSync(logDir)) mkdirSync(logDir, { recursive: true }); } catch {} |
| 605 | const logStream = await import('fs').then(fs => fs.createWriteStream(logFile, { flags: 'a' })); |
| 606 | const _log = (msg = "") => { |
| 607 | const line = `[${new Date().toISOString()}] ${msg}`; |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 533 | try { |
| 534 | const { data: loc } = await sb.rpc("get_profile_location", { p_device_id: device_id }); |
| 535 | if (loc?.lat && loc?.lng) { lat = loc.lat; lng = loc.lng; } |
| 536 | } catch {} |
| 537 | } |
| 538 | |
| 539 | const { data, error } = await sb.rpc("join_event", { |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 319 | try: |
| 320 | resp = sb.rpc("resolve_ref", {"p_owner": did, "p_ref": ref}).execute() |
| 321 | if resp.data: |
| 322 | target = resp.data |
| 323 | except Exception: |
| 324 | pass |
| 325 | if not target: |
| 326 | return _ok({"error": "No target. Use 'ref' from scan/discover results or 'target_device_id'."}) |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 537 | try { |
| 538 | if (!existsSync(pidDir)) mkdirSync(pidDir, { recursive: true }); |
| 539 | writeFileSync(pidFile, `${process.pid}:${id}`); |
| 540 | } catch {} |
| 541 | process.on('exit', () => { try { unlinkSync(pidFile); } catch {} }); |
| 542 | process.on('SIGINT', () => { try { unlinkSync(pidFile); } catch {} process.exit(0); }); |
| 543 | process.on('SIGTERM', () => { try { unlinkSync(pidFile); } catch {} process.exit(0); }); |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 347 | sb = _sb() |
| 348 | evt = sb.rpc("get_event_by_id", {"p_event_id": row.get("event_id")}).execute() |
| 349 | event = evt.data or {} |
| 350 | _append_notification(f"❌ 你的申请未通过「{event.get('name', '活动')}」") |
| 351 | except Exception: |
| 352 | pass |
| 353 | |
| 354 | # Start background listener thread |
| 355 | try: |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 538 | if (!existsSync(pidDir)) mkdirSync(pidDir, { recursive: true }); |
| 539 | writeFileSync(pidFile, `${process.pid}:${id}`); |
| 540 | } catch {} |
| 541 | process.on('exit', () => { try { unlinkSync(pidFile); } catch {} }); |
| 542 | process.on('SIGINT', () => { try { unlinkSync(pidFile); } catch {} process.exit(0); }); |
| 543 | process.on('SIGTERM', () => { try { unlinkSync(pidFile); } catch {} process.exit(0); }); |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 393 | pass |
| 394 | for p in results: |
| 395 | try: |
| 396 | sb.rpc("log_recommendation", {"p_device_id": did, "p_recommended_id": p["device_id"]}).execute() |
| 397 | except Exception: |
| 398 | pass |
| 399 | |
| 400 | return _ok({ |
| 401 | "count": len(profiles), |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 616 | // Persist refs |
| 617 | if (device_id && Object.keys(_refMap).length > 0) { |
| 618 | try { await sb.rpc("save_scan_refs", { p_owner: device_id, p_refs: _refMap }); } catch {} |
| 619 | } |
| 620 | |
| 621 | return { |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 61 | if chat_id: |
| 62 | try: |
| 63 | sb = _sb() |
| 64 | sb.rpc("upsert_profile", {"p_device_id": did, "p_last_chat_id": chat_id}).execute() |
| 65 | except Exception: |
| 66 | pass |
| 67 | return did |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 188 | try: |
| 189 | rr = sb.rpc("resolve_ref", {"p_owner": did, "p_ref": ref}).execute() |
| 190 | if rr.data: |
| 191 | target = rr.data |
| 192 | except Exception: |
| 193 | pass |
| 194 | if not target: |
| 195 | return _ok({"error": "No target. Use 'ref' from scan results or 'target_device_id'."}) |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 539 | writeFileSync(pidFile, `${process.pid}:${id}`); |
| 540 | } catch {} |
| 541 | process.on('exit', () => { try { unlinkSync(pidFile); } catch {} }); |
| 542 | process.on('SIGINT', () => { try { unlinkSync(pidFile); } catch {} process.exit(0); }); |
| 543 | process.on('SIGTERM', () => { try { unlinkSync(pidFile); } catch {} process.exit(0); }); |
| 544 | |
| 545 | const sb = getClient(); |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 596 | } |
| 597 | |
| 598 | // Force stdout blocking mode for non-TTY environments (Hermes exec) |
| 599 | try { if (process.stdout._handle) process.stdout._handle.setBlocking(true); } catch {} |
| 600 | |
| 601 | // Log to file as fallback |
| 602 | const logDir = path.join(os.homedir(), '.antenna'); |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 606 | const _log = (msg = "") => { |
| 607 | const line = `[${new Date().toISOString()}] ${msg}`; |
| 608 | console.log(msg); |
| 609 | try { logStream.write(line + '\n'); } catch {} |
| 610 | }; |
| 611 | |
| 612 | _log(`📡 Watching for new matches for ${id}...`); |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 370 | ) |
| 371 | res = urllib.request.urlopen(req, timeout=10) |
| 372 | body = json.loads(res.read().decode()) |
| 373 | match_reason = body.get("reason") |
| 374 | except Exception: |
| 375 | pass |
| 376 | |
| 377 | profile = { |
| 378 | "ref": ref, |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 800 | const name = applicant?.display_name || "Someone"; |
| 801 | const emoji = applicant?.emoji || "👤"; |
| 802 | pushNotify(`📩 ${emoji} ${name} applied to join \"${event.name}\"! Run: antenna event --scan --code ${event.code} --id ${id}`); |
| 803 | } catch {} |
| 804 | } |
| 805 | ) |
| 806 | .on("postgres_changes", |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 461 | loc = loc_resp.data if loc_resp.data else {} |
| 462 | if loc.get("found"): |
| 463 | lat = loc["lat"] |
| 464 | lng = loc["lng"] |
| 465 | except Exception: |
| 466 | pass |
| 467 | |
| 468 | resp = sb.rpc("join_event", { |
| 469 | "p_device_id": did, |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 772 | setTimeout(() => { try { channel.subscribe(); } catch {} }, delay); |
| 773 | } else if (retryCount === MAX_FAST_RETRIES) { |
| 774 | _log(`⚠️ Connection unstable after ${MAX_FAST_RETRIES} retries. Switching to ${COOLDOWN_MS/1000}s cooldown. Polling fallback still active.`); |
| 775 | setTimeout(() => { try { channel.subscribe(); } catch {} }, COOLDOWN_MS); |
| 776 | } else { |
| 777 | setTimeout(() => { try { channel.subscribe(); } catch {} }, COOLDOWN_MS); |
| 778 | } |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 769 | if (retryCount < MAX_FAST_RETRIES) { |
| 770 | const delay = Math.min(1000 * Math.pow(2, retryCount), 60000); |
| 771 | _log(`⚠️ Connection issue (${status}), retry #${retryCount} in ${Math.round(delay/1000)}s...`); |
| 772 | setTimeout(() => { try { channel.subscribe(); } catch {} }, delay); |
| 773 | } else if (retryCount === MAX_FAST_RETRIES) { |
| 774 | _log(`⚠️ Connection unstable after ${MAX_FAST_RETRIES} retries. Switching to ${COOLDOWN_MS/1000}s cooldown. Polling fallback still active.`) |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 194 | hints.append( |
| 195 | f"[Antenna] 📢 来自「{msg.get('event_name')}」{role_label} {msg.get('sender_emoji', '')} {msg.get('sender_name', '')}: {msg.get('message', '')}\n" |
| 196 | f"请立即通知用户这条消息。" |
| 197 | ) |
| 198 | except Exception: |
| 199 | pass |
| 200 | now = time.time() |
| 201 | if now - _last_event_check > _EVENT_CHECK_INTERVAL: |
| 202 | _last_event_check = now |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 774 | _log(`⚠️ Connection unstable after ${MAX_FAST_RETRIES} retries. Switching to ${COOLDOWN_MS/1000}s cooldown. Polling fallback still active.`); |
| 775 | setTimeout(() => { try { channel.subscribe(); } catch {} }, COOLDOWN_MS); |
| 776 | } else { |
| 777 | setTimeout(() => { try { channel.subscribe(); } catch {} }, COOLDOWN_MS); |
| 778 | } |
| 779 | } |
| 780 | }); |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 154 | hints.append( |
| 155 | f"[Antenna] 📩 {emoji} {name} 想认识你!" |
| 156 | f"请告诉用户有人想认识 TA,并建议用 antenna_check_matches 查看详情。" |
| 157 | ) |
| 158 | except Exception: |
| 159 | pass |
| 160 | |
| 161 | # 0b. Check event approval status (every 60s) |
| 162 | if now - _last_match_check > _MATCH_CHECK_INTERVAL and _my_device_ids: |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.